Skip to content

Commit b5b5ead

Browse files
CSS fix for shadow dom
1 parent c36926a commit b5b5ead

1 file changed

Lines changed: 22 additions & 8 deletions

File tree

src/views/renderers/DomRenderer.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,39 @@ export class DomRenderer {
2121
const shadowHost = container.createDiv({cls: "html-reader-shadow-host"});
2222
const shadow = shadowHost.attachShadow({mode: "open"});
2323

24-
if (settings.darkModeSupport) {
25-
const sheet = new CSSStyleSheet();
26-
sheet.replaceSync(DARK_MODE_SHADOW_CSS);
27-
shadow.adoptedStyleSheets = [sheet];
28-
}
29-
3024
const parser = new DOMParser();
3125
let doc: Document;
3226

3327
if (settings.securityMode === SecurityMode.Unrestricted) {
34-
// Parse directly and strip only scripts for DOM safety.
35-
// Avoids the serialize→re-parse round-trip that can lose style elements.
3628
doc = parser.parseFromString(html, "text/html");
3729
doc.querySelectorAll("script").forEach(el => el.remove());
3830
} else {
3931
const sanitized = sanitizeHtml(html, settings);
4032
doc = parser.parseFromString(sanitized, "text/html");
4133
}
4234

35+
// Extract <style> elements into adoptedStyleSheets.
36+
// Obsidian strips <style> DOM nodes (no-forbidden-elements); adopted sheets bypass this.
37+
const sheets: CSSStyleSheet[] = [];
38+
if (settings.darkModeSupport) {
39+
const darkSheet = new CSSStyleSheet();
40+
darkSheet.replaceSync(DARK_MODE_SHADOW_CSS);
41+
sheets.push(darkSheet);
42+
}
43+
for (const style of Array.from(doc.querySelectorAll("style"))) {
44+
let css = style.textContent ?? "";
45+
// :root and body selectors have no target in shadow DOM; remap to :host
46+
css = css.replace(/:root/g, ":host");
47+
css = css.replace(/(^|[\s,}])body(?=\s*\{)/gm, "$1:host");
48+
try {
49+
const sheet = new CSSStyleSheet();
50+
sheet.replaceSync(css);
51+
sheets.push(sheet);
52+
} catch { /* skip unparseable CSS */ }
53+
style.remove();
54+
}
55+
shadow.adoptedStyleSheets = sheets;
56+
4357
const wrapper = document.createElement("div");
4458
for (const node of Array.from(doc.head.childNodes)) {
4559
wrapper.appendChild(node);

0 commit comments

Comments
 (0)