diff options
Diffstat (limited to 'src/client/views/nodes/WebBox.tsx')
-rw-r--r-- | src/client/views/nodes/WebBox.tsx | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 838dbea9d..1e158f484 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -505,6 +505,98 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { this._scrollHeight = this._iframe?.contentDocument?.body?.scrollHeight ?? 0; this.addWebStyleSheetRule(this.addWebStyleSheet(this._iframe?.contentDocument), '::selection', { color: 'white', background: 'orange' }, ''); + // Add error handler to suppress font CORS errors + if (this._iframe?.contentWindow) { + try { + // Track if any resource errors occurred + let hasResourceErrors = false; + + // Override the console.error to filter out font CORS errors + const win = this._iframe.contentWindow as Window & { console: Console }; + const originalConsoleError = win.console.error; + win.console.error = (...args: unknown[]) => { + const errorMsg = args.map(arg => String(arg)).join(' '); + if (errorMsg.includes('Access to font') && errorMsg.includes('has been blocked by CORS policy')) { + // Mark that we have font errors + hasResourceErrors = true; + // Ignore font CORS errors + return; + } + // Also catch other resource loading errors + if (errorMsg.includes('ERR_FAILED') || errorMsg.includes('ERR_BLOCKED_BY_CLIENT')) { + hasResourceErrors = true; + } + originalConsoleError.apply(win.console, args); + }; + + // Listen for resource loading errors + this._iframe.contentWindow.addEventListener( + 'error', + (e: Event) => { + const target = e.target as HTMLElement; + if (target instanceof HTMLElement) { + // If it's a resource that failed to load + if (target.tagName === 'LINK' || target.tagName === 'IMG' || target.tagName === 'SCRIPT') { + hasResourceErrors = true; + // Apply error class after a short delay to allow initial content to load + setTimeout(() => { + if (this._iframe && hasResourceErrors) { + this._iframe.classList.add('loading-error'); + } + }, 1000); + } + } + }, + true + ); + + // Add fallback CSS for fonts that fail to load + const style = this._iframe.contentDocument?.createElement('style'); + if (style) { + style.textContent = ` + @font-face { + font-family: 'CORS-fallback-serif'; + src: local('Times New Roman'), local('Georgia'), serif; + } + @font-face { + font-family: 'CORS-fallback-sans'; + src: local('Arial'), local('Helvetica'), sans-serif; + } + /* Fallback for all fonts that fail to load */ + @font-face { + font-display: swap !important; + } + + /* Add a script to find and fix elements with failed fonts */ + @font-face { + font-family: '__failed_font__'; + src: local('Arial'); + unicode-range: U+0000; + } + `; + this._iframe.contentDocument?.head.appendChild(style); + + // Add a script to detect and fix font loading issues + const script = this._iframe.contentDocument?.createElement('script'); + if (script) { + script.textContent = ` + // Fix font loading issues with fallbacks + setTimeout(function() { + document.querySelectorAll('*').forEach(function(el) { + if (window.getComputedStyle(el).fontFamily.includes('__failed_font__')) { + el.classList.add('font-error-hidden'); + } + }); + }, 1000); + `; + this._iframe.contentDocument?.head.appendChild(script); + } + } + } catch (e) { + console.log('Error setting up font error handling:', e); + } + } + let href: Opt<string>; try { href = iframe?.contentWindow?.location.href; |