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')), 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}); })() """; }