fix: HTML 预览锚点点击同步 hash,修复多页面技能子页面切换失效
预览 iframe 注入的锚点拦截脚本只 preventDefault + scrollIntoView, URL hash 从未改变,html-multipage 技能基于 CSS :target 的子页面 切换永远不命中,子页面 section 保持隐藏,点击无效。改为拦截后 同步 location.hash 触发 :target 切页,仅当目标元素已渲染时再平滑滚动。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
74113b3e6e
commit
21e53310f8
1 file changed
+16
-5
@@ -100,9 +100,16 @@ function candidateTextFromHref(href: string): string {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Injects a small runtime script into generated HTML so that clicking an
|
* Injects a small runtime script into generated HTML so that clicking an
|
||||||
* in-page anchor (`<a href="#section">`) scrolls within the iframe instead of
|
* in-page anchor (`<a href="#section">`) works inside the preview iframe.
|
||||||
* navigating it. The preview iframe loads from a sandboxed `blob:` URL, where a
|
*
|
||||||
* fragment navigation blanks the frame; intercepting the click avoids that.
|
* The hash MUST really change on click: multi-page documents (the
|
||||||
|
* html-multipage skill) show/hide their sub-page `<section class="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.
|
||||||
*/
|
*/
|
||||||
export function injectInPageAnchorHandler(html: string): string {
|
export function injectInPageAnchorHandler(html: string): string {
|
||||||
const script = `<script>(function(){
|
const script = `<script>(function(){
|
||||||
@@ -119,8 +126,8 @@ export function injectInPageAnchorHandler(html: string): string {
|
|||||||
var href=el.getAttribute("href");
|
var href=el.getAttribute("href");
|
||||||
if(!href||href.charAt(0)!=="#"||href.length<2)return;
|
if(!href||href.charAt(0)!=="#"||href.length<2)return;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var id=decode(href.slice(1));
|
|
||||||
var raw=href.slice(1);
|
var raw=href.slice(1);
|
||||||
|
var id=decode(raw);
|
||||||
var target=
|
var target=
|
||||||
document.getElementById(id)||
|
document.getElementById(id)||
|
||||||
document.getElementById(raw)||
|
document.getElementById(raw)||
|
||||||
@@ -128,7 +135,11 @@ export function injectInPageAnchorHandler(html: string): string {
|
|||||||
document.getElementsByName(raw)[0]||
|
document.getElementsByName(raw)[0]||
|
||||||
bySelector(id)||
|
bySelector(id)||
|
||||||
bySelector(raw);
|
bySelector(raw);
|
||||||
if(target){target.scrollIntoView({behavior:"smooth",block:"start"});}
|
try{if(location.hash!=="#"+raw){location.hash=raw;}}catch(err){}
|
||||||
|
if(!target)return;
|
||||||
|
requestAnimationFrame(function(){
|
||||||
|
if(target.getClientRects().length){target.scrollIntoView({behavior:"smooth",block:"start"});}
|
||||||
|
});
|
||||||
},true);
|
},true);
|
||||||
})();</script>`;
|
})();</script>`;
|
||||||
if (/<\/body>/i.test(html)) {
|
if (/<\/body>/i.test(html)) {
|
||||||
|
|||||||
Reference in new issue
Block a user