From 2f414c6e08e8c1014a85c05b1d4893c9f18bb6df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=89=E9=91=AB=E5=8D=87?= Date: Tue, 16 Jun 2026 09:19:15 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20HTML=20=E9=A2=84=E8=A7=88=E5=AD=90?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E6=94=B9=E7=94=A8=20JS=20=E5=88=87=E6=8D=A2?= =?UTF-8?q?=EF=BC=8C=E9=81=BF=E5=85=8D=E6=B2=99=E7=AE=B1=20blob=20?= =?UTF-8?q?=E5=AF=BC=E8=88=AA=E8=A2=AB=E6=8B=A6=E6=88=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 上一版通过设置 location.hash 触发 CSS :target 切页,但沙箱 blob iframe 禁止导航到自身 blob URL,浏览器报 Not allowed to load local resource,且 :target 仅在真实片段导航时更新,注定失效。改为完全 不动 hash,用 JS 模拟 html-multipage 技能的 .page/.pages 显示隐藏 (内联 display 覆盖类级 CSS),普通目录锚点仍平滑滚动。 Co-Authored-By: Claude Fable 5 --- frontend-web/src/core/utils/markdown.ts | 52 +++++++++++++++---------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/frontend-web/src/core/utils/markdown.ts b/frontend-web/src/core/utils/markdown.ts index 4ab819ce..c5b80575 100644 --- a/frontend-web/src/core/utils/markdown.ts +++ b/frontend-web/src/core/utils/markdown.ts @@ -102,14 +102,18 @@ function candidateTextFromHref(href: string): string { * Injects a small runtime script into generated HTML so that clicking an * in-page anchor (``) works inside the preview iframe. * - * The hash MUST really change on click: multi-page documents (the - * html-multipage skill) show/hide their sub-page `
` - * blocks with CSS `:target` rules, which only fire on a fragment navigation. - * Intercepting with preventDefault + scrollIntoView alone leaves the hash - * untouched, so sub-pages stay `display:none` and clicks look dead. The - * handler therefore syncs `location.hash` (a same-document navigation — - * safe in the sandboxed blob: frame) and only smooth-scrolls afterwards when - * the target is actually rendered. + * The preview loads from a sandboxed `blob:` URL (opaque origin). Such a frame + * is FORBIDDEN from navigating to its own `blob:` URL, so changing the hash + * throws "Not allowed to load local resource: blob:…#page-x". And because CSS + * `:target` only updates on a real fragment navigation, the html-multipage + * skill's `:target`-based sub-page switching can never fire here. + * + * So we never touch the hash. Instead the handler emulates the skill's + * show/hide in JS: a "page" is a `.page` inside a `.pages` container; clicking + * a link to one shows it and hides its siblings (mirroring the + * `.page:target` + `~ #page-home` rules via inline `display`, which outranks + * the skill's class-level CSS). Plain in-page anchors (TOC headings, etc.) just + * smooth-scroll as before. */ export function injectInPageAnchorHandler(html: string): string { const script = ``; if (/<\/body>/i.test(html)) {