From 17465b855fae268298327aac75c6c7f6449a923a Mon Sep 17 00:00:00 2001 From: olwater <52482488+olwater@users.noreply.github.com> Date: Mon, 6 Jul 2026 14:00:31 +0800 Subject: [PATCH] =?UTF-8?q?fix(html):=20=E4=BF=AE=E5=A4=8D=20Shadow=20DOM?= =?UTF-8?q?=20=E9=9A=94=E7=A6=BB=E6=B8=B2=E6=9F=93=E4=B8=8B=E6=B7=B1?= =?UTF-8?q?=E6=B5=85=E8=89=B2=E6=A8=A1=E5=BC=8F=E6=97=A0=E6=B3=95=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E5=88=87=E6=8D=A2=E7=9A=84=E9=97=AE=E9=A2=98=20(#5890?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Shadow DOM 的样式隔离特性导致外部 html 元素上的 dark class 无法被 Shadow DOM 内部的 Tailwind dark: 选择器匹配到。通过 MutationObserver 监听 document.documentElement 的 class 变化,将 dark class 同步到 Shadow DOM 内的包装容器上,使深色模式样式正常生效。 --- web/default/src/components/html-content.tsx | 23 +++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/web/default/src/components/html-content.tsx b/web/default/src/components/html-content.tsx index e31bf820..c9f9f294 100644 --- a/web/default/src/components/html-content.tsx +++ b/web/default/src/components/html-content.tsx @@ -134,6 +134,11 @@ function sanitizeHtmlContent( return DOMPurify.sanitize(content) } +function syncDarkClass(wrapper: HTMLElement): void { + const isDark = document.documentElement.classList.contains('dark') + wrapper.classList.toggle('dark', isDark) +} + function IsolatedHtmlContent(props: { className?: string html: string @@ -153,13 +158,27 @@ function IsolatedHtmlContent(props: { 'style, link[rel="stylesheet"]' ), ].map((node) => node.cloneNode(true)) + + const wrapper = document.createElement('div') + syncDarkClass(wrapper) + wrapper.innerHTML = props.html + const contentTemplate = document.createElement('template') - contentTemplate.innerHTML = `${isolatedContentBaseStyles}${props.html}` + contentTemplate.innerHTML = isolatedContentBaseStyles shadowRoot.replaceChildren( ...applicationStyleNodes, - contentTemplate.content + contentTemplate.content, + wrapper ) + + const observer = new MutationObserver(() => syncDarkClass(wrapper)) + observer.observe(document.documentElement, { + attributes: true, + attributeFilter: ['class'], + }) + + return () => observer.disconnect() }, [props.html]) return (