namespace XFESystem.Browser;
public sealed partial class BrowserService
{
/// Read-only caret diagnostics for a caller that owns this page's
/// UI thread. Background editor callers must use their published snapshot.
public string ReadEditorNavigationProof() => WithGate(() => IsMonacoAddress(currentAddress) && runtime is not null
? runtime.Evaluate("typeof xfeMonacoEditor==='object' ? JSON.stringify({Kind:'ActualMonacoNavigation',Position:xfeMonacoEditor.getPosition(),Selection:xfeMonacoEditor.getSelection(),LineCount:xfeMonacoEditor.getModel().getLineCount(),LastLineMaxColumn:xfeMonacoEditor.getModel().getLineMaxColumn(xfeMonacoEditor.getModel().getLineCount()),FocusedTag:document.activeElement?document.activeElement.tagName:null}) : '{}' ").Text
: "{}");
/// Reading diagnostics must not invalidate the document or schedule a repaint.
public string ReadMonacoProof() => WithGate(() => IsMonacoAddress(currentAddress) && runtime is not null
? runtime.Evaluate("typeof xfeWebsiteHighlight==='object' && typeof xfeMonacoEditor==='object' && xfeMonacoEditor.getModel().getLanguageId()==='csharp' ? JSON.stringify(xfeWebsiteHighlight.getProof(xfeMonacoEditor)) : '{}' ").Text
: "{}");
/// Fixed read-only diagnostics for the native serial acceptance
/// harness. Only the generated, sanitized local-document profile qualifies.
/// It does not inject source, alter document state or synthesize pixels.
public string ReadWebsiteDocumentProof() => WithGate(() => trustedDocument && runtime is not null && !documentEnhancementsPending
? runtime.Evaluate(WebsiteDocumentProofScript).Text : "{}");
private const string WebsiteDocumentProofScript = """
(function(){
const article=document.querySelector('.markdown-body');
if(!article)return '{}';
function rect(element){if(!element)return null;const value=element.getBoundingClientRect();return {X:value.x,Y:value.y,Width:value.width,Height:value.height};}
function style(element){if(!element)return null;const value=getComputedStyle(element);return {Color:value.color,BackgroundColor:value.backgroundColor,FontFamily:value.fontFamily,FontSize:value.fontSize,FontWeight:value.fontWeight,LineHeight:value.lineHeight,BorderRadius:value.borderRadius,Padding:value.padding,Display:value.display};}
function element(value){return value?{Text:value.textContent.slice(0,2048),Bounds:rect(value),Style:style(value)}:null;}
const blocks=Array.from(article.querySelectorAll('pre.code-block-enhanced')).slice(0,8).map(pre=>{
const code=pre.querySelector('code');
return {Classes:pre.className,Bounds:rect(pre),Style:style(pre),CodeText:code?code.textContent:'',CodeHtml:code?code.innerHTML:'',CodeClasses:code?code.className:'',CodeBounds:rect(code),CodeStyle:style(code),
LineNumberCount:pre.querySelectorAll('.code-line-numbers > span').length,
Buttons:Array.from(pre.querySelectorAll('[data-code-action]')).map(button=>({Action:button.getAttribute('data-code-action'),Pressed:button.getAttribute('aria-pressed'),Title:button.title,Bounds:rect(button)})),
Tokens:code?Array.from(code.querySelectorAll('span[class]')).slice(0,256).map(span=>({Text:span.textContent,Classes:span.className,Color:getComputedStyle(span).color,Bounds:rect(span)})):[]};
});
return JSON.stringify({Kind:'ActualWebsiteDocumentDomReadback',Address:location.href,Title:document.title,
Theme:document.documentElement.getAttribute('data-bs-theme'),Article:element(article),Heading:element(article.querySelector('h1')),
Paragraphs:Array.from(article.querySelectorAll('p')).slice(0,16).map(element),
BodyText:article.textContent.slice(0,8192),Styles:Array.from(document.querySelectorAll('link[rel="stylesheet"]')).map(link=>link.href),
Scripts:Array.from(document.querySelectorAll('script[src]')).map(script=>script.src),
WebsiteHighlighterAvailable:typeof hljs==='object',WebsiteCodeToolsAvailable:typeof XFECodeBlocks==='object',
CodeBlocks:blocks,Table:element(article.querySelector('table')),Blockquote:element(article.querySelector('blockquote')),
KatexCount:article.querySelectorAll('.katex').length,MermaidSvgCount:article.querySelectorAll('.mermaid-wrapper svg').length,
MermaidState:element(article.querySelector('.mermaid-wrapper')),
Links:Array.from(article.querySelectorAll('a[href]')).slice(0,32).map(link=>({Text:link.textContent,Href:link.href,Bounds:rect(link)})),
NoHostScreenshotSubstitution:true,ReadOnly:true});
})()
""";
}