diff --git a/frontend/src/components/shell/SecondaryDisplay.tsx b/frontend/src/components/shell/SecondaryDisplay.tsx
index 4616bec3..24282b5c 100644
--- a/frontend/src/components/shell/SecondaryDisplay.tsx
+++ b/frontend/src/components/shell/SecondaryDisplay.tsx
@@ -18,14 +18,100 @@ function defaultGeometry(): SecondaryDisplayGeometry {
}
}
+/**
+ * Neemt de opmaak van het hoofdvenster mee naar de console.
+ *
+ * De vorige versie kloonde de naar het nieuwe venster.
+ * Dat venster wordt geopend met window.open('') en is dus about:blank; daar
+ * werd de link wel in de head gezet maar nooit opgehaald — nagemeten leverde
+ * link.sheet === null op. Gevolg: de console stond volledig onopgemaakt, in
+ * Times New Roman op wit, terwijl de werkbank ernaast donker was. Het verklaart
+ * ook waarom de paneelregels voor dit venster met !important stonden: die
+ * probeerden iets te overschrijven dat er nooit aankwam. Sinds de opmaak hier
+ * wel aankomt zijn ze overbodig gebleken en verwijderd.
+ *
+ * Nu worden de regels zelf ingeschreven. Dat is dezelfde oorsprong, dus
+ * cssRules is leesbaar, en er komt geen netwerkverzoek aan te pas. Lukt het
+ * lezen toch niet, dan valt hij terug op de gekloonde link.
+ */
function copyDocumentStyles(target: Document): void {
+ const regels: string[] = []
+ let alleenGelezen = true
+
+ // Verwijzingen in de regels — lettertypen, iconen, achtergronden — staan
+ // relatief. Het nieuwe venster is about:blank en heeft dus geen basis om ze
+ // tegen op te lossen; zonder deze stap blijft het wachten op lettertypen die
+ // nooit aankomen. Ze worden hier absoluut gemaakt tegen de bron van het blad.
+ const maakAbsoluut = (tekst: string, basis: string): string =>
+ tekst.replace(/url\((['"]?)([^'")]+)\1\)/g, (heel, quote, verwijzing) => {
+ if (/^(data:|blob:|https?:|\/\/)/i.test(verwijzing)) return heel
+ try {
+ return `url("${new URL(verwijzing, basis).href}")`
+ } catch {
+ return heel
+ }
+ })
+
+ // @font-face gaat bewust niet mee. De bestanden komen in dit venster wel
+ // binnen met status 200, maar de FontFace springt nooit naar 'loaded': in een
+ // document dat op about:blank staat voltooit het lettertypeladen niet. Het
+ // gevolg was dat document.fonts.status eeuwig op 'loading' bleef en de console
+ // kort in terugvalletters opende. De gezichten worden in plaats daarvan
+ // overgenomen uit het hoofdvenster, waar ze al geladen zijn — zie
+ // copyLoadedFonts hieronder.
+ const isFontFace = (regel: CSSRule): boolean =>
+ typeof CSSFontFaceRule !== 'undefined' && regel instanceof CSSFontFaceRule
+
+ for (const sheet of Array.from(document.styleSheets)) {
+ try {
+ const basis = sheet.href ?? document.baseURI
+ const tekst = Array.from(sheet.cssRules)
+ .filter((regel) => !isFontFace(regel))
+ .map((regel) => maakAbsoluut(regel.cssText, basis))
+ .join('\n')
+ if (tekst) regels.push(tekst)
+ } catch {
+ alleenGelezen = false
+ }
+ }
+
+ if (regels.length > 0) {
+ const stijl = target.createElement('style')
+ stijl.setAttribute('data-herkomst', 'hoofdvenster')
+ stijl.textContent = regels.join('\n')
+ target.head.append(stijl)
+ }
+
+ if (alleenGelezen && regels.length > 0) return
+
+ // Terugval voor bladen die niet te lezen zijn, bijvoorbeeld van een ander domein.
document.head.querySelectorAll('link[rel="stylesheet"], style').forEach((node) => {
const clone = node.cloneNode(true) as HTMLLinkElement | HTMLStyleElement
- if (clone instanceof HTMLLinkElement) clone.href = node instanceof HTMLLinkElement ? node.href : ''
+ if (clone instanceof HTMLLinkElement && node instanceof HTMLLinkElement) clone.href = node.href
target.head.append(clone)
})
}
+/**
+ * Neemt de al geladen lettertypegezichten van het hoofdvenster over.
+ *
+ * Een FontFace hangt niet aan een document, dus een gezicht dat hier al
+ * ingeladen is kan rechtstreeks aan de FontFaceSet van het nieuwe venster
+ * worden toegevoegd. Dat scheelt niet alleen een tweede download, het omzeilt
+ * ook dat het laden in een about:blank-document nooit voltooit.
+ */
+function copyLoadedFonts(target: Window): void {
+ const doel = target.document.fonts
+ if (!doel || typeof document.fonts === 'undefined') return
+ document.fonts.forEach((gezicht) => {
+ try {
+ doel.add(gezicht)
+ } catch {
+ // Al aanwezig, of dit gezicht laat zich niet overdragen.
+ }
+ })
+}
+
function initialiseSecondaryDocument(target: Window, onClose: () => void): HTMLElement {
const targetDocument = target.document
targetDocument.title = 'GeoIntel · Analyseconsole'
@@ -37,6 +123,7 @@ function initialiseSecondaryDocument(target: Window, onClose: () => void): HTMLE
viewport.content = 'width=device-width, initial-scale=1'
targetDocument.head.append(viewport)
copyDocumentStyles(targetDocument)
+ copyLoadedFonts(target)
const shell = targetDocument.createElement('div')
shell.className = 'secondary-display-shell'