markdown-flow-ui 0.1.104-alpha.13 → 0.1.104-alpha.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/index.cjs10.js +1 -1
- package/dist/_virtual/index.cjs11.js +1 -1
- package/dist/_virtual/index.es10.js +2 -3
- package/dist/_virtual/index.es10.js.map +1 -1
- package/dist/_virtual/index.es11.js +3 -2
- package/dist/_virtual/index.es11.js.map +1 -1
- package/dist/components/ContentRender/IframeSandbox.cjs.js +9 -4
- package/dist/components/ContentRender/IframeSandbox.cjs.js.map +1 -1
- package/dist/components/ContentRender/IframeSandbox.es.js +103 -99
- package/dist/components/ContentRender/IframeSandbox.es.js.map +1 -1
- package/dist/node_modules/@braintree/sanitize-url/dist/index.cjs.js +1 -1
- package/dist/node_modules/@braintree/sanitize-url/dist/index.es.js +1 -1
- package/dist/node_modules/rc-util/es/ref.cjs.js +1 -1
- package/dist/node_modules/rc-util/es/ref.es.js +1 -1
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});var e={};exports.__exports=e;
|
|
2
2
|
//# sourceMappingURL=index.cjs10.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../node_modules/rc-util/node_modules/react-is/index.cjs.js");var r=e.__require();exports.reactIsExports=r;
|
|
2
2
|
//# sourceMappingURL=index.cjs11.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es10.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.es10.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es11.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.es11.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const x=require("../../_virtual/jsx-runtime.cjs.js"),t=require("react"),Te=require("react-dom/client"),Ae=require("./SandboxApp.cjs.js"),
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const x=require("../../_virtual/jsx-runtime.cjs.js"),t=require("react"),Te=require("react-dom/client"),Ae=require("./SandboxApp.cjs.js"),je=require("./ContentRender.cjs.js"),p=require("./utils/iframe-viewport-height.cjs.js"),be=require("../../lib/sandboxInteraction.cjs.js");let Y=null;const Fe=()=>(Y||(Y=Promise.resolve().then(()=>require("./blackboard-vendor.cjs.js")).then(c=>c.injectBlackboardLibraries)),Y),Ie=/<img\b[^>]*>/i,Ne=180,Oe=240,_e=c=>c.split(/\s+/).filter(Boolean).map(s=>{const i=s.split(":");return i[i.length-1]!=="h-screen"&&i[i.length-1]!=="min-h-screen"?s:(i[i.length-1]="h-full",i.join(":"))}).join(" "),Ve=(c,s)=>!s||!c.trim()?c:c.replace(/^(\s*<[a-zA-Z][\w:-]*)(\s[^>]*?)?>/,(i,I,E="")=>{const a=E.match(/\bclass\s*=\s*(["'])([^"']*)\1/i);if(!a)return i;const N=_e(a[2]);return N===a[2]?i:`${I}${E.replace(a[0],`class=${a[1]}${N}${a[1]}`)}>`}),ke=({content:c,type:s,className:i,styleLoadingText:I,scriptLoadingText:E,fullScreenButtonText:a,hideFullScreen:N=!1,mode:l="content",replaceRootScreenHeightWithFull:pe=!1})=>{const O=t.useRef(null),m=t.useRef(null),P=t.useRef(null),R=t.useRef(()=>{}),[we,He]=t.useState(480),[Z,xe]=t.useState(0),[q,J]=t.useState(0),B=t.useRef(!1),K=t.useRef(0),[Q,Ee]=t.useState(0),[L,Re]=t.useState(!1),ve=s==="sandbox",f=l==="blackboard",v=f&&s==="sandbox",w=v&&pe,$=t.useRef(""),_=t.useMemo(()=>s==="sandbox"?c:"",[c,s]),r=t.useMemo(()=>Ve(_,w),[_,w]),ee=t.useMemo(()=>w?p.inspectViewportHeightFromHtmlRootString(_):p.EMPTY_ROOT_HEIGHT_META,[_,w]),te=t.useMemo(()=>w&&ee.hasFullViewportHeight,[ee.hasFullViewportHeight,w]),[V,ne]=t.useState(r),re=t.useRef(r),W=t.useRef(r),S=t.useRef(null),M=t.useRef(null),oe=t.useRef(null),H=t.useCallback(n=>{if(typeof window>"u")return;const e=Date.now();e-K.current<Oe||(K.current=e,window.postMessage({source:be.SANDBOX_INTERACTION_MESSAGE_SOURCE,type:be.SANDBOX_INTERACTION_MESSAGE_TYPE,eventType:n},window.location.origin))},[]),z=()=>{S.current!==null&&(window.clearTimeout(S.current),S.current=null)},Se=()=>{M.current!==null&&(window.cancelAnimationFrame(M.current),M.current=null)};t.useEffect(()=>()=>{z(),Se()},[]),t.useEffect(()=>{const n=re.current;re.current=r;const e=!!n&&r.length>n.length&&r.startsWith(n),u=Ie.test(r);if(!(e&&u)){z(),W.current=r,ne(r);return}W.current=r,z(),S.current=window.setTimeout(()=>{ne(W.current),S.current=null},Ne)},[r]);const k=t.useMemo(()=>v?p.inspectViewportHeightFromHtmlRootString(V).viewportHeightCss:null,[V,v]);t.useEffect(()=>{oe.current=k},[k]);const se=!!k,C=f&&s==="sandbox"?te?"100%":k??`${we}px`:void 0;t.useEffect(()=>{if(l!=="blackboard"){$.current=r;return}const n=$.current;!(n&&r.startsWith(n))&&n&&Ee(u=>u+1),$.current=r},[l,r]),t.useEffect(()=>{const n=m.current;if(!n)return;const e=n.contentDocument;if(!e)return;e.open(),e.write(`<!DOCTYPE html>
|
|
2
2
|
<html${l==="blackboard"?' style="height: 100%;"':""}>
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8" />
|
|
@@ -6,14 +6,19 @@
|
|
|
6
6
|
<style>
|
|
7
7
|
:root { color-scheme: light; }
|
|
8
8
|
html, body, #root { width: 100%; }
|
|
9
|
-
${l==="blackboard"?"html, body, #root { height: 100%; }":"
|
|
9
|
+
${l==="blackboard"?"html, body, #root { height: 100%; }":""}
|
|
10
10
|
html, body { margin: 0; padding: 0; overflow: ${l==="blackboard"?"auto":"hidden"}; }
|
|
11
11
|
*, *::before, *::after { box-sizing: border-box; }
|
|
12
|
-
${l!=="blackboard"
|
|
12
|
+
${l!=="blackboard"?`
|
|
13
|
+
.h-screen { height: auto !important; }
|
|
14
|
+
.min-h-screen { min-height: auto !important; }
|
|
15
|
+
.h-dvh, .h-svh, .h-lvh { height: auto !important; }
|
|
16
|
+
.min-h-dvh, .min-h-svh, .min-h-lvh { min-height: auto !important; }
|
|
17
|
+
`:""}
|
|
13
18
|
</style>
|
|
14
19
|
</head>
|
|
15
20
|
<body>
|
|
16
21
|
<div id="root"></div>
|
|
17
22
|
</body>
|
|
18
|
-
</html>`),e.close(),e.documentElement.setAttribute("data-theme","light"),e.documentElement.style.colorScheme="light",e.body?.style.setProperty("color-scheme","light");const u=f&&s==="sandbox",G=()=>
|
|
23
|
+
</html>`),e.close(),e.documentElement.setAttribute("data-theme","light"),e.documentElement.style.colorScheme="light",e.body?.style.setProperty("color-scheme","light");const u=f&&s==="sandbox",G=()=>H("pointerdown"),ce=()=>H("mousedown"),le=()=>H("touchstart");u&&(e.addEventListener("pointerdown",G,!0),e.addEventListener("mousedown",ce,!0),e.addEventListener("touchstart",le,!0));const y=e.getElementById("root");if(!y)return;const ue=Te.createRoot(y);P.current=ue;let T=!1;const ae=o=>({heightAttrValue:o.getAttribute("height"),styleAttrValue:o.getAttribute("style"),classAttrValue:o.getAttribute("class")}),he=o=>{const g=Array.from(o.children);return g.length===1?g[0]:null},ye=()=>{if(!v||!m.current||!e.body)return null;const o=m.current.ownerDocument?.documentElement?.clientHeight||window.innerHeight,g=oe.current,D=g?p.parseExplicitHeight(g,o):null;if(D!==null)return Math.ceil(D);const h=e.body.querySelector(".sandbox-wrapper")?.firstElementChild;if(!h)return null;const d=Array.from(h.children),b=d.length===1?d[0]:null,j=p.inspectViewportHeightFromNodeChain(b,{getNode:ae,getSingleChild:he}).viewportHeightCss;if(j){const ge=p.parseExplicitHeight(j,o);if(ge!==null)return Math.ceil(ge)}const F=p.resolveExplicitHeightFromNodeChain(b,o,{getNode:ae,getSingleChild:he});return F!==null?Math.ceil(F):null},U=()=>{if(!m.current||!e.body)return;if(!f){if(B.current)return;B.current=!0;const h=m.current,d=O.current?.clientWidth||0,b=h.style.height;if(d>0){h.style.height=d+"px",e.body.offsetHeight;const fe=e.body.scrollHeight;h.style.height=b,xe(j=>{const F=Math.max(200,Math.ceil(fe));return j===F?j:F})}setTimeout(()=>{B.current=!1},50);return}const o=e.body.scrollHeight,g=e.documentElement?.scrollHeight||0,D=y?.scrollHeight||0,me=Math.max(o,g,D);if(v){const h=ye(),d=Math.max(200,h??Math.ceil(me));He(b=>b===d?b:d)}},A=()=>{requestAnimationFrame(()=>{T||U()})};R.current=A,U(),A(),ve&&Fe().then(o=>{T||(o(e),requestAnimationFrame(()=>{T||A()}))}).catch(()=>{T||A()});const X=new ResizeObserver(()=>U());X.observe(e.body),y&&X.observe(y);const de=new MutationObserver(()=>{A()});return de.observe(e.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["style","class"]}),()=>{T=!0,X.disconnect(),de.disconnect(),u&&(e.removeEventListener("pointerdown",G,!0),e.removeEventListener("mousedown",ce,!0),e.removeEventListener("touchstart",le,!0)),setTimeout(()=>{ue.unmount(),P.current=null,R.current=()=>{}},0)}},[]),t.useEffect(()=>{const n=()=>{Re(!!document.fullscreenElement)};return document.addEventListener("fullscreenchange",n),()=>document.removeEventListener("fullscreenchange",n)},[]),t.useEffect(()=>{const n=O.current;if(!n)return;const e=new ResizeObserver(u=>{J(u[0]?.contentRect.width??n.clientWidth)});return e.observe(n),J(n.clientWidth),()=>e.disconnect()},[]);const ie=t.useMemo(()=>{if(f||q===0||L)return;const n=Math.round(q*9/16);return{height:Math.max(n,Z)}},[f,q,Z,L]),Me=()=>{const n=O.current||m.current;if(n){if(document.fullscreenElement){document.exitFullscreen().catch(()=>{});return}n.requestFullscreen&&n.requestFullscreen().catch(()=>{})}};t.useEffect(()=>{const n=P.current;if(!n)return;n.render(x.jsxRuntimeExports.jsx(Ae.default,{html:V,styleLoadingText:I,scriptLoadingText:E,resetToken:Q,hasRootVhHeight:se,mode:l,stretchRootHeight:te})),M.current=window.requestAnimationFrame(()=>{R.current?.(),M.current=null});const e=setTimeout(()=>R.current?.(),100),u=setTimeout(()=>R.current?.(),500);return()=>{clearTimeout(e),clearTimeout(u)}},[V,I,E,Q,l]);const Ce=["w-full relative content-render-iframe-sandbox",f?"h-full overflow-auto flex flex-col":ie?"overflow-hidden flex items-center justify-center":"aspect-[16/9] overflow-hidden flex items-center justify-center"].filter(Boolean).join(" ");return x.jsxRuntimeExports.jsxs("div",{ref:O,"data-root-vh":se?"true":"false",className:Ce,style:C?{height:C,minHeight:C}:ie,children:[!N&&x.jsxRuntimeExports.jsx("button",{type:"button",onClick:Me,className:"absolute top-2 right-2 z-50 p-1.5 bg-black/75 text-white rounded-md cursor-pointer",children:L?"退出全屏":a||"全屏浏览"}),l==="blackboard"&&s==="markdown"?x.jsxRuntimeExports.jsx("div",{onMouseDown:()=>H("mousedown"),onPointerDown:()=>H("pointerdown"),onTouchStart:()=>H("touchstart"),children:x.jsxRuntimeExports.jsx(je.default,{content:c})}):x.jsxRuntimeExports.jsx("iframe",{ref:m,sandbox:"allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox",allow:"fullscreen",allowFullScreen:!0,className:[i,"w-full h-full mx-auto my-auto block"].filter(Boolean).join(" "),style:{height:C??"100%",minHeight:C,margin:"auto"}})]})};exports.default=ke;
|
|
19
24
|
//# sourceMappingURL=IframeSandbox.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IframeSandbox.cjs.js","sources":["../../../src/components/ContentRender/IframeSandbox.tsx"],"sourcesContent":["import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { createRoot, Root } from \"react-dom/client\";\nimport SandboxApp from \"./SandboxApp\";\nimport ContentRender from \"./ContentRender\";\nimport {\n EMPTY_ROOT_HEIGHT_META,\n inspectViewportHeightFromHtmlRootString,\n inspectViewportHeightFromNodeChain,\n parseExplicitHeight,\n resolveExplicitHeightFromNodeChain,\n} from \"./utils/iframe-viewport-height\";\nimport {\n SANDBOX_INTERACTION_MESSAGE_SOURCE,\n SANDBOX_INTERACTION_MESSAGE_TYPE,\n} from \"../../lib/sandboxInteraction\";\n\ntype InjectBlackboardLibraries =\n typeof import(\"./blackboard-vendor\").injectBlackboardLibraries;\n\n// Cache the sandbox vendor loader so every iframe reuses the same preload request.\nlet blackboardVendorPromise: Promise<InjectBlackboardLibraries> | null = null;\n\nconst loadBlackboardVendor = () => {\n if (!blackboardVendorPromise) {\n blackboardVendorPromise = import(\"./blackboard-vendor\").then(\n (m) => m.injectBlackboardLibraries\n );\n }\n\n return blackboardVendorPromise;\n};\n\nconst COMPLETE_IMAGE_TAG_PATTERN = /<img\\b[^>]*>/i;\nconst POST_IMAGE_STREAM_DEBOUNCE_MS = 180;\nconst SANDBOX_INTERACTION_THROTTLE_MS = 240;\n\nexport interface IframeSandboxProps {\n content: string;\n className?: string;\n loadingText?: string;\n styleLoadingText?: string;\n scriptLoadingText?: string;\n fullScreenButtonText?: string;\n hideFullScreen?: boolean;\n mode?: \"content\" | \"blackboard\";\n type: \"sandbox\" | \"markdown\";\n replaceRootScreenHeightWithFull?: boolean;\n}\n\nconst replaceRootScreenHeightToken = (className: string) =>\n className\n .split(/\\s+/)\n .filter(Boolean)\n .map((token) => {\n const segments = token.split(\":\");\n if (\n segments[segments.length - 1] !== \"h-screen\" &&\n segments[segments.length - 1] !== \"min-h-screen\"\n ) {\n return token;\n }\n segments[segments.length - 1] = \"h-full\";\n return segments.join(\":\");\n })\n .join(\" \");\n\nconst replaceRootScreenHeightWithFullClass = (\n html: string,\n enabled: boolean\n) => {\n if (!enabled || !html.trim()) {\n return html;\n }\n\n return html.replace(\n /^(\\s*<[a-zA-Z][\\w:-]*)(\\s[^>]*?)?>/,\n (match, tagStart: string, attrs = \"\") => {\n const classMatch = attrs.match(/\\bclass\\s*=\\s*([\"'])([^\"']*)\\1/i);\n\n if (!classMatch) {\n return match;\n }\n\n const nextClassName = replaceRootScreenHeightToken(classMatch[2]);\n\n if (nextClassName === classMatch[2]) {\n return match;\n }\n\n return `${tagStart}${attrs.replace(\n classMatch[0],\n `class=${classMatch[1]}${nextClassName}${classMatch[1]}`\n )}>`;\n }\n );\n};\n\nconst IframeSandbox: React.FC<IframeSandboxProps> = ({\n content,\n type,\n className,\n styleLoadingText,\n scriptLoadingText,\n fullScreenButtonText,\n hideFullScreen = false,\n mode = \"content\",\n replaceRootScreenHeightWithFull = false,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const rootRef = useRef<Root | null>(null);\n const updateHeightRef = useRef<() => void>(() => {});\n const [height, setHeight] = useState(480);\n const [contentHeight, setContentHeight] = useState(0);\n const [containerWidth, setContainerWidth] = useState(0);\n const isMeasuringContentRef = useRef(false);\n const lastSandboxInteractionTimeRef = useRef(0);\n const [resetToken, setResetToken] = useState(0);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const shouldInjectSandboxVendor = type === \"sandbox\";\n\n const isBlackboardMode = mode === \"blackboard\";\n const shouldMeasureDynamicHeight = isBlackboardMode && type === \"sandbox\";\n const shouldProcessRootScreenHeight =\n shouldMeasureDynamicHeight && replaceRootScreenHeightWithFull;\n const prevHtmlRef = useRef<string>(\"\");\n const htmlContent = React.useMemo(\n () => (type === \"sandbox\" ? content : \"\"),\n [content, type]\n );\n const normalizedHtmlContent = React.useMemo(\n () =>\n replaceRootScreenHeightWithFullClass(\n htmlContent,\n shouldProcessRootScreenHeight\n ),\n [htmlContent, shouldProcessRootScreenHeight]\n );\n const originalRootHeightMeta = React.useMemo(\n () =>\n shouldProcessRootScreenHeight\n ? inspectViewportHeightFromHtmlRootString(htmlContent)\n : EMPTY_ROOT_HEIGHT_META,\n [htmlContent, shouldProcessRootScreenHeight]\n );\n const shouldStretchRootHeight = React.useMemo(\n () =>\n shouldProcessRootScreenHeight &&\n originalRootHeightMeta.hasFullViewportHeight,\n [\n originalRootHeightMeta.hasFullViewportHeight,\n shouldProcessRootScreenHeight,\n ]\n );\n const [renderHtmlContent, setRenderHtmlContent] = useState(\n normalizedHtmlContent\n );\n const prevIncomingHtmlRef = useRef(normalizedHtmlContent);\n const pendingHtmlRef = useRef(normalizedHtmlContent);\n const deferRenderTimerRef = useRef<number | null>(null);\n const initialPaintFrameRef = useRef<number | null>(null);\n const renderViewportHeightCssRef = useRef<string | null>(null);\n\n const emitSandboxInteraction = useCallback((eventType: string) => {\n if (typeof window === \"undefined\") {\n return;\n }\n const now = Date.now();\n if (\n now - lastSandboxInteractionTimeRef.current <\n SANDBOX_INTERACTION_THROTTLE_MS\n ) {\n return;\n }\n lastSandboxInteractionTimeRef.current = now;\n window.postMessage(\n {\n source: SANDBOX_INTERACTION_MESSAGE_SOURCE,\n type: SANDBOX_INTERACTION_MESSAGE_TYPE,\n eventType,\n },\n window.location.origin\n );\n }, []);\n\n const clearDeferredRenderTimer = () => {\n if (deferRenderTimerRef.current === null) return;\n window.clearTimeout(deferRenderTimerRef.current);\n deferRenderTimerRef.current = null;\n };\n\n const clearInitialPaintFrames = () => {\n if (initialPaintFrameRef.current !== null) {\n window.cancelAnimationFrame(initialPaintFrameRef.current);\n initialPaintFrameRef.current = null;\n }\n };\n\n useEffect(\n () => () => {\n clearDeferredRenderTimer();\n clearInitialPaintFrames();\n },\n []\n );\n\n useEffect(() => {\n const prevIncomingHtml = prevIncomingHtmlRef.current;\n prevIncomingHtmlRef.current = normalizedHtmlContent;\n\n const isAppendOnlyStream =\n !!prevIncomingHtml &&\n normalizedHtmlContent.length > prevIncomingHtml.length &&\n normalizedHtmlContent.startsWith(prevIncomingHtml);\n const containsCompleteImage = COMPLETE_IMAGE_TAG_PATTERN.test(\n normalizedHtmlContent\n );\n const shouldDeferRender = isAppendOnlyStream && containsCompleteImage;\n\n if (!shouldDeferRender) {\n clearDeferredRenderTimer();\n pendingHtmlRef.current = normalizedHtmlContent;\n setRenderHtmlContent(normalizedHtmlContent);\n return;\n }\n\n pendingHtmlRef.current = normalizedHtmlContent;\n clearDeferredRenderTimer();\n deferRenderTimerRef.current = window.setTimeout(() => {\n setRenderHtmlContent(pendingHtmlRef.current);\n deferRenderTimerRef.current = null;\n }, POST_IMAGE_STREAM_DEBOUNCE_MS);\n }, [normalizedHtmlContent]);\n\n const rootViewportHeightCss = React.useMemo(() => {\n if (!shouldMeasureDynamicHeight) {\n return null;\n }\n\n return inspectViewportHeightFromHtmlRootString(renderHtmlContent)\n .viewportHeightCss;\n }, [renderHtmlContent, shouldMeasureDynamicHeight]);\n\n useEffect(() => {\n renderViewportHeightCssRef.current = rootViewportHeightCss;\n }, [rootViewportHeightCss]);\n\n const hasRootVhHeight = Boolean(rootViewportHeightCss);\n const sandboxViewportHeight =\n isBlackboardMode && type === \"sandbox\"\n ? shouldStretchRootHeight\n ? \"100%\"\n : (rootViewportHeightCss ?? `${height}px`)\n : undefined;\n useEffect(() => {\n if (mode !== \"blackboard\") {\n prevHtmlRef.current = normalizedHtmlContent;\n return;\n }\n const prev = prevHtmlRef.current;\n const isContinuation = prev && normalizedHtmlContent.startsWith(prev);\n if (!isContinuation && prev) {\n setResetToken((token) => token + 1);\n }\n prevHtmlRef.current = normalizedHtmlContent;\n }, [mode, normalizedHtmlContent]);\n\n useEffect(() => {\n const iframe = iframeRef.current;\n if (!iframe) return undefined;\n\n const doc = iframe.contentDocument;\n if (!doc) return undefined;\n\n doc.open();\n doc.write(`<!DOCTYPE html>\n<html${mode === \"blackboard\" ? ' style=\"height: 100%;\"' : \"\"}>\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <style>\n :root { color-scheme: light; }\n html, body, #root { width: 100%; }\n ${mode === \"blackboard\" ? \"html, body, #root { height: 100%; }\" : \"html { height: 100%; overflow: hidden; }\"}\n html, body { margin: 0; padding: 0; overflow: ${mode === \"blackboard\" ? \"auto\" : \"hidden\"}; }\n *, *::before, *::after { box-sizing: border-box; }\n ${mode !== \"blackboard\" ? \".overflow-y-auto, .overflow-auto { scrollbar-width: none !important; } .overflow-y-auto::-webkit-scrollbar, .overflow-auto::-webkit-scrollbar { display: none !important; }\" : \"\"}\n </style>\n </head>\n <body>\n <div id=\"root\"></div>\n </body>\n</html>`);\n doc.close();\n\n // Force iframe theme to stay in light mode regardless of host OS preference.\n doc.documentElement.setAttribute(\"data-theme\", \"light\");\n doc.documentElement.style.colorScheme = \"light\";\n doc.body?.style.setProperty(\"color-scheme\", \"light\");\n\n const shouldBridgeSandboxInteraction =\n isBlackboardMode && type === \"sandbox\";\n const handleSandboxPointerDown = () =>\n emitSandboxInteraction(\"pointerdown\");\n const handleSandboxMouseDown = () => emitSandboxInteraction(\"mousedown\");\n const handleSandboxTouchStart = () => emitSandboxInteraction(\"touchstart\");\n\n if (shouldBridgeSandboxInteraction) {\n doc.addEventListener(\"pointerdown\", handleSandboxPointerDown, true);\n doc.addEventListener(\"mousedown\", handleSandboxMouseDown, true);\n doc.addEventListener(\"touchstart\", handleSandboxTouchStart, true);\n }\n\n const rootEl = doc.getElementById(\"root\");\n if (!rootEl) return undefined;\n\n const root = createRoot(rootEl);\n rootRef.current = root;\n let isDestroyed = false;\n const getHeightInspectionNode = (node: HTMLElement) => ({\n heightAttrValue: node.getAttribute(\"height\"),\n styleAttrValue: node.getAttribute(\"style\"),\n classAttrValue: node.getAttribute(\"class\"),\n });\n const getSingleChildElement = (node: HTMLElement) => {\n const childElements = Array.from(node.children) as HTMLElement[];\n\n return childElements.length === 1 ? childElements[0] : null;\n };\n\n const resolveExplicitHeight = () => {\n if (!shouldMeasureDynamicHeight) return null;\n if (!iframeRef.current || !doc.body) return null;\n const parentViewportHeight =\n iframeRef.current.ownerDocument?.documentElement?.clientHeight ||\n window.innerHeight;\n // Reuse parsed height metadata from the current html snapshot first to\n // avoid re-inspecting the same DOM chain on every height tick.\n const precomputedViewportHeightCss = renderViewportHeightCssRef.current;\n const parsed = precomputedViewportHeightCss\n ? parseExplicitHeight(\n precomputedViewportHeightCss,\n parentViewportHeight\n )\n : null;\n\n if (parsed !== null) {\n return Math.ceil(parsed);\n }\n\n const wrapper = doc.body.querySelector(\n \".sandbox-wrapper\"\n ) as HTMLElement | null;\n const container = wrapper?.firstElementChild as HTMLElement | null;\n if (!container) return null;\n const containerChildren = Array.from(container.children) as HTMLElement[];\n const rootContentElement =\n containerChildren.length === 1 ? containerChildren[0] : null;\n const runtimeHeightMeta = inspectViewportHeightFromNodeChain(\n rootContentElement,\n {\n getNode: getHeightInspectionNode,\n getSingleChild: getSingleChildElement,\n }\n );\n const runtimeViewportHeightCss = runtimeHeightMeta.viewportHeightCss;\n\n if (runtimeViewportHeightCss) {\n const runtimeViewportHeight = parseExplicitHeight(\n runtimeViewportHeightCss,\n parentViewportHeight\n );\n\n if (runtimeViewportHeight !== null) {\n return Math.ceil(runtimeViewportHeight);\n }\n }\n\n const explicitPixelHeight = resolveExplicitHeightFromNodeChain(\n rootContentElement,\n parentViewportHeight,\n {\n getNode: getHeightInspectionNode,\n getSingleChild: getSingleChildElement,\n }\n );\n\n return explicitPixelHeight !== null\n ? Math.ceil(explicitPixelHeight)\n : null;\n };\n\n const updateHeight = () => {\n if (!iframeRef.current || !doc.body) return;\n\n if (!isBlackboardMode) {\n // Guard: prevent re-entrant measurement from ResizeObserver /\n // MutationObserver callbacks triggered by our own height changes.\n if (isMeasuringContentRef.current) return;\n isMeasuringContentRef.current = true;\n\n const sc = doc.querySelector(\n \".sandbox-container\"\n ) as HTMLElement | null;\n const fc = sc?.firstElementChild as HTMLElement | null;\n\n // Detect viewport-filling content (slides using vh-based sizing).\n // Such content cannot be auto-sized because 100vh = iframe viewport\n // height, creating an infinite feedback loop.\n const isViewportFilling =\n fc &&\n /\\b(min-)?h-(screen|dvh|svh|lvh)\\b/.test(fc.className || \"\");\n\n if (!isViewportFilling && sc) {\n // Normal content: sandbox-container has no height:100% in content\n // mode (SandboxApp sets it to undefined), so its scrollHeight\n // reflects the true content height, unaffected by iframe viewport.\n const h = sc.scrollHeight;\n setContentHeight((prev) => {\n const next = Math.max(200, Math.ceil(h));\n return prev === next ? prev : next;\n });\n }\n // For viewport-filling content: contentHeight stays at 0,\n // so contentModeStyle will use the 16:9 minimum.\n\n setTimeout(() => {\n isMeasuringContentRef.current = false;\n }, 50);\n return;\n }\n\n // Blackboard mode: use existing measurement logic\n const bodyScrollH = doc.body.scrollHeight;\n const htmlScrollH = doc.documentElement?.scrollHeight || 0;\n const rootScrollH = rootEl?.scrollHeight || 0;\n const measuredHeight = Math.max(bodyScrollH, htmlScrollH, rootScrollH);\n\n if (shouldMeasureDynamicHeight) {\n const explicitHeight = resolveExplicitHeight();\n const nextHeight = Math.max(\n 200,\n explicitHeight ?? Math.ceil(measuredHeight)\n );\n setHeight((prevHeight) =>\n prevHeight === nextHeight ? prevHeight : nextHeight\n );\n }\n };\n const scheduleHeightUpdate = () => {\n requestAnimationFrame(() => {\n if (isDestroyed) return;\n updateHeight();\n });\n };\n updateHeightRef.current = scheduleHeightUpdate;\n\n updateHeight();\n scheduleHeightUpdate();\n\n if (shouldInjectSandboxVendor) {\n // Inject Tailwind/DaisyUI/GSAP before rendering sandbox content to avoid FOUC.\n loadBlackboardVendor()\n .then((inject) => {\n if (isDestroyed) return;\n inject(doc);\n requestAnimationFrame(() => {\n if (isDestroyed) return;\n scheduleHeightUpdate();\n });\n })\n .catch(() => {\n if (isDestroyed) return;\n scheduleHeightUpdate();\n });\n }\n\n const resizeObserver = new ResizeObserver(() => updateHeight());\n resizeObserver.observe(doc.body);\n if (rootEl) {\n resizeObserver.observe(rootEl);\n }\n\n // MutationObserver: detect DOM changes that ResizeObserver might miss\n // (e.g. content injected by scripts, images loading, dynamic rendering)\n const mutationObserver = new MutationObserver(() => {\n scheduleHeightUpdate();\n });\n mutationObserver.observe(doc.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\"style\", \"class\"],\n });\n\n return () => {\n isDestroyed = true;\n resizeObserver.disconnect();\n mutationObserver.disconnect();\n if (shouldBridgeSandboxInteraction) {\n doc.removeEventListener(\"pointerdown\", handleSandboxPointerDown, true);\n doc.removeEventListener(\"mousedown\", handleSandboxMouseDown, true);\n doc.removeEventListener(\"touchstart\", handleSandboxTouchStart, true);\n }\n // Defer unmount to avoid React warning when parent is mid-render\n setTimeout(() => {\n root.unmount();\n rootRef.current = null;\n updateHeightRef.current = () => {};\n }, 0);\n };\n }, []);\n\n useEffect(() => {\n const onFullscreenChange = () => {\n setIsFullscreen(Boolean(document.fullscreenElement));\n };\n document.addEventListener(\"fullscreenchange\", onFullscreenChange);\n return () =>\n document.removeEventListener(\"fullscreenchange\", onFullscreenChange);\n }, []);\n\n // Track container width for computing min-height in content mode\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n const ro = new ResizeObserver((entries) => {\n setContainerWidth(entries[0]?.contentRect.width ?? el.clientWidth);\n });\n ro.observe(el);\n setContainerWidth(el.clientWidth);\n return () => ro.disconnect();\n }, []);\n\n // Content mode: min 16:9 aspect ratio, grow to fit content (no scrollbar)\n const contentModeStyle = useMemo<React.CSSProperties | undefined>(() => {\n if (isBlackboardMode || containerWidth === 0 || isFullscreen)\n return undefined;\n const minH = Math.round((containerWidth * 9) / 16);\n const h = Math.max(minH, contentHeight);\n return { height: h };\n }, [isBlackboardMode, containerWidth, contentHeight, isFullscreen]);\n\n const toggleFullscreen = () => {\n const target = containerRef.current || iframeRef.current;\n if (!target) return;\n if (document.fullscreenElement) {\n document.exitFullscreen().catch(() => {});\n return;\n }\n if (target.requestFullscreen) {\n target.requestFullscreen().catch(() => {});\n }\n };\n\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n\n root.render(\n <SandboxApp\n html={renderHtmlContent}\n styleLoadingText={styleLoadingText}\n scriptLoadingText={scriptLoadingText}\n resetToken={resetToken}\n hasRootVhHeight={hasRootVhHeight}\n mode={mode}\n stretchRootHeight={shouldStretchRootHeight}\n />\n );\n\n // Schedule multiple measurements to catch async content (scripts, images, styles).\n initialPaintFrameRef.current = window.requestAnimationFrame(() => {\n updateHeightRef.current?.();\n initialPaintFrameRef.current = null;\n });\n const t1 = setTimeout(() => updateHeightRef.current?.(), 100);\n const t2 = setTimeout(() => updateHeightRef.current?.(), 500);\n return () => {\n clearTimeout(t1);\n clearTimeout(t2);\n };\n }, [\n renderHtmlContent,\n styleLoadingText,\n scriptLoadingText,\n resetToken,\n mode,\n ]);\n const containerClassName = [\n \"w-full relative content-render-iframe-sandbox\",\n isBlackboardMode\n ? \"h-full overflow-auto flex flex-col\"\n : contentModeStyle\n ? \"overflow-hidden flex items-center justify-center\"\n : \"aspect-[16/9] overflow-hidden flex items-center justify-center\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div\n ref={containerRef}\n data-root-vh={hasRootVhHeight ? \"true\" : \"false\"}\n className={containerClassName}\n style={\n sandboxViewportHeight\n ? {\n height: sandboxViewportHeight,\n minHeight: sandboxViewportHeight,\n }\n : contentModeStyle\n }\n >\n {!hideFullScreen && (\n <button\n type=\"button\"\n onClick={toggleFullscreen}\n className={\n \"absolute top-2 right-2 z-50 p-1.5 bg-black/75 text-white rounded-md cursor-pointer\"\n }\n >\n {isFullscreen ? \"退出全屏\" : fullScreenButtonText || \"全屏浏览\"}\n </button>\n )}\n {mode === \"blackboard\" && type === \"markdown\" ? (\n <div\n onMouseDown={() => emitSandboxInteraction(\"mousedown\")}\n onPointerDown={() => emitSandboxInteraction(\"pointerdown\")}\n onTouchStart={() => emitSandboxInteraction(\"touchstart\")}\n >\n <ContentRender content={content} />\n </div>\n ) : (\n <iframe\n ref={iframeRef}\n sandbox=\"allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox\"\n allow=\"fullscreen\"\n allowFullScreen\n className={[className, \"w-full h-full mx-auto my-auto block\"]\n .filter(Boolean)\n .join(\" \")}\n style={{\n height: sandboxViewportHeight ?? \"100%\",\n minHeight: sandboxViewportHeight,\n margin: \"auto\",\n }}\n />\n )}\n </div>\n );\n};\n\nexport default IframeSandbox;\n"],"names":["blackboardVendorPromise","loadBlackboardVendor","m","COMPLETE_IMAGE_TAG_PATTERN","POST_IMAGE_STREAM_DEBOUNCE_MS","SANDBOX_INTERACTION_THROTTLE_MS","replaceRootScreenHeightToken","className","token","segments","replaceRootScreenHeightWithFullClass","html","enabled","match","tagStart","attrs","classMatch","nextClassName","IframeSandbox","content","type","styleLoadingText","scriptLoadingText","fullScreenButtonText","hideFullScreen","mode","replaceRootScreenHeightWithFull","containerRef","useRef","iframeRef","rootRef","updateHeightRef","height","setHeight","useState","contentHeight","setContentHeight","containerWidth","setContainerWidth","isMeasuringContentRef","lastSandboxInteractionTimeRef","resetToken","setResetToken","isFullscreen","setIsFullscreen","shouldInjectSandboxVendor","isBlackboardMode","shouldMeasureDynamicHeight","shouldProcessRootScreenHeight","prevHtmlRef","htmlContent","React","normalizedHtmlContent","originalRootHeightMeta","inspectViewportHeightFromHtmlRootString","EMPTY_ROOT_HEIGHT_META","shouldStretchRootHeight","renderHtmlContent","setRenderHtmlContent","prevIncomingHtmlRef","pendingHtmlRef","deferRenderTimerRef","initialPaintFrameRef","renderViewportHeightCssRef","emitSandboxInteraction","useCallback","eventType","now","SANDBOX_INTERACTION_MESSAGE_SOURCE","SANDBOX_INTERACTION_MESSAGE_TYPE","clearDeferredRenderTimer","clearInitialPaintFrames","useEffect","prevIncomingHtml","isAppendOnlyStream","containsCompleteImage","rootViewportHeightCss","hasRootVhHeight","sandboxViewportHeight","prev","iframe","doc","shouldBridgeSandboxInteraction","handleSandboxPointerDown","handleSandboxMouseDown","handleSandboxTouchStart","rootEl","root","createRoot","isDestroyed","getHeightInspectionNode","node","getSingleChildElement","childElements","resolveExplicitHeight","parentViewportHeight","precomputedViewportHeightCss","parsed","parseExplicitHeight","container","containerChildren","rootContentElement","runtimeViewportHeightCss","inspectViewportHeightFromNodeChain","runtimeViewportHeight","explicitPixelHeight","resolveExplicitHeightFromNodeChain","updateHeight","sc","fc","h","next","bodyScrollH","htmlScrollH","rootScrollH","measuredHeight","explicitHeight","nextHeight","prevHeight","scheduleHeightUpdate","inject","resizeObserver","mutationObserver","onFullscreenChange","el","ro","entries","contentModeStyle","useMemo","minH","toggleFullscreen","target","jsx","SandboxApp","t1","t2","containerClassName","jsxs","ContentRender"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"IframeSandbox.cjs.js","sources":["../../../src/components/ContentRender/IframeSandbox.tsx"],"sourcesContent":["import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { createRoot, Root } from \"react-dom/client\";\nimport SandboxApp from \"./SandboxApp\";\nimport ContentRender from \"./ContentRender\";\nimport {\n EMPTY_ROOT_HEIGHT_META,\n inspectViewportHeightFromHtmlRootString,\n inspectViewportHeightFromNodeChain,\n parseExplicitHeight,\n resolveExplicitHeightFromNodeChain,\n} from \"./utils/iframe-viewport-height\";\nimport {\n SANDBOX_INTERACTION_MESSAGE_SOURCE,\n SANDBOX_INTERACTION_MESSAGE_TYPE,\n} from \"../../lib/sandboxInteraction\";\n\ntype InjectBlackboardLibraries =\n typeof import(\"./blackboard-vendor\").injectBlackboardLibraries;\n\n// Cache the sandbox vendor loader so every iframe reuses the same preload request.\nlet blackboardVendorPromise: Promise<InjectBlackboardLibraries> | null = null;\n\nconst loadBlackboardVendor = () => {\n if (!blackboardVendorPromise) {\n blackboardVendorPromise = import(\"./blackboard-vendor\").then(\n (m) => m.injectBlackboardLibraries\n );\n }\n\n return blackboardVendorPromise;\n};\n\nconst COMPLETE_IMAGE_TAG_PATTERN = /<img\\b[^>]*>/i;\nconst POST_IMAGE_STREAM_DEBOUNCE_MS = 180;\nconst SANDBOX_INTERACTION_THROTTLE_MS = 240;\n\nexport interface IframeSandboxProps {\n content: string;\n className?: string;\n loadingText?: string;\n styleLoadingText?: string;\n scriptLoadingText?: string;\n fullScreenButtonText?: string;\n hideFullScreen?: boolean;\n mode?: \"content\" | \"blackboard\";\n type: \"sandbox\" | \"markdown\";\n replaceRootScreenHeightWithFull?: boolean;\n}\n\nconst replaceRootScreenHeightToken = (className: string) =>\n className\n .split(/\\s+/)\n .filter(Boolean)\n .map((token) => {\n const segments = token.split(\":\");\n if (\n segments[segments.length - 1] !== \"h-screen\" &&\n segments[segments.length - 1] !== \"min-h-screen\"\n ) {\n return token;\n }\n segments[segments.length - 1] = \"h-full\";\n return segments.join(\":\");\n })\n .join(\" \");\n\nconst replaceRootScreenHeightWithFullClass = (\n html: string,\n enabled: boolean\n) => {\n if (!enabled || !html.trim()) {\n return html;\n }\n\n return html.replace(\n /^(\\s*<[a-zA-Z][\\w:-]*)(\\s[^>]*?)?>/,\n (match, tagStart: string, attrs = \"\") => {\n const classMatch = attrs.match(/\\bclass\\s*=\\s*([\"'])([^\"']*)\\1/i);\n\n if (!classMatch) {\n return match;\n }\n\n const nextClassName = replaceRootScreenHeightToken(classMatch[2]);\n\n if (nextClassName === classMatch[2]) {\n return match;\n }\n\n return `${tagStart}${attrs.replace(\n classMatch[0],\n `class=${classMatch[1]}${nextClassName}${classMatch[1]}`\n )}>`;\n }\n );\n};\n\nconst IframeSandbox: React.FC<IframeSandboxProps> = ({\n content,\n type,\n className,\n styleLoadingText,\n scriptLoadingText,\n fullScreenButtonText,\n hideFullScreen = false,\n mode = \"content\",\n replaceRootScreenHeightWithFull = false,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const rootRef = useRef<Root | null>(null);\n const updateHeightRef = useRef<() => void>(() => {});\n const [height, setHeight] = useState(480);\n const [contentHeight, setContentHeight] = useState(0);\n const [containerWidth, setContainerWidth] = useState(0);\n const isMeasuringContentRef = useRef(false);\n const lastSandboxInteractionTimeRef = useRef(0);\n const [resetToken, setResetToken] = useState(0);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const shouldInjectSandboxVendor = type === \"sandbox\";\n\n const isBlackboardMode = mode === \"blackboard\";\n const shouldMeasureDynamicHeight = isBlackboardMode && type === \"sandbox\";\n const shouldProcessRootScreenHeight =\n shouldMeasureDynamicHeight && replaceRootScreenHeightWithFull;\n const prevHtmlRef = useRef<string>(\"\");\n const htmlContent = React.useMemo(\n () => (type === \"sandbox\" ? content : \"\"),\n [content, type]\n );\n const normalizedHtmlContent = React.useMemo(\n () =>\n replaceRootScreenHeightWithFullClass(\n htmlContent,\n shouldProcessRootScreenHeight\n ),\n [htmlContent, shouldProcessRootScreenHeight]\n );\n const originalRootHeightMeta = React.useMemo(\n () =>\n shouldProcessRootScreenHeight\n ? inspectViewportHeightFromHtmlRootString(htmlContent)\n : EMPTY_ROOT_HEIGHT_META,\n [htmlContent, shouldProcessRootScreenHeight]\n );\n const shouldStretchRootHeight = React.useMemo(\n () =>\n shouldProcessRootScreenHeight &&\n originalRootHeightMeta.hasFullViewportHeight,\n [\n originalRootHeightMeta.hasFullViewportHeight,\n shouldProcessRootScreenHeight,\n ]\n );\n const [renderHtmlContent, setRenderHtmlContent] = useState(\n normalizedHtmlContent\n );\n const prevIncomingHtmlRef = useRef(normalizedHtmlContent);\n const pendingHtmlRef = useRef(normalizedHtmlContent);\n const deferRenderTimerRef = useRef<number | null>(null);\n const initialPaintFrameRef = useRef<number | null>(null);\n const renderViewportHeightCssRef = useRef<string | null>(null);\n\n const emitSandboxInteraction = useCallback((eventType: string) => {\n if (typeof window === \"undefined\") {\n return;\n }\n const now = Date.now();\n if (\n now - lastSandboxInteractionTimeRef.current <\n SANDBOX_INTERACTION_THROTTLE_MS\n ) {\n return;\n }\n lastSandboxInteractionTimeRef.current = now;\n window.postMessage(\n {\n source: SANDBOX_INTERACTION_MESSAGE_SOURCE,\n type: SANDBOX_INTERACTION_MESSAGE_TYPE,\n eventType,\n },\n window.location.origin\n );\n }, []);\n\n const clearDeferredRenderTimer = () => {\n if (deferRenderTimerRef.current === null) return;\n window.clearTimeout(deferRenderTimerRef.current);\n deferRenderTimerRef.current = null;\n };\n\n const clearInitialPaintFrames = () => {\n if (initialPaintFrameRef.current !== null) {\n window.cancelAnimationFrame(initialPaintFrameRef.current);\n initialPaintFrameRef.current = null;\n }\n };\n\n useEffect(\n () => () => {\n clearDeferredRenderTimer();\n clearInitialPaintFrames();\n },\n []\n );\n\n useEffect(() => {\n const prevIncomingHtml = prevIncomingHtmlRef.current;\n prevIncomingHtmlRef.current = normalizedHtmlContent;\n\n const isAppendOnlyStream =\n !!prevIncomingHtml &&\n normalizedHtmlContent.length > prevIncomingHtml.length &&\n normalizedHtmlContent.startsWith(prevIncomingHtml);\n const containsCompleteImage = COMPLETE_IMAGE_TAG_PATTERN.test(\n normalizedHtmlContent\n );\n const shouldDeferRender = isAppendOnlyStream && containsCompleteImage;\n\n if (!shouldDeferRender) {\n clearDeferredRenderTimer();\n pendingHtmlRef.current = normalizedHtmlContent;\n setRenderHtmlContent(normalizedHtmlContent);\n return;\n }\n\n pendingHtmlRef.current = normalizedHtmlContent;\n clearDeferredRenderTimer();\n deferRenderTimerRef.current = window.setTimeout(() => {\n setRenderHtmlContent(pendingHtmlRef.current);\n deferRenderTimerRef.current = null;\n }, POST_IMAGE_STREAM_DEBOUNCE_MS);\n }, [normalizedHtmlContent]);\n\n const rootViewportHeightCss = React.useMemo(() => {\n if (!shouldMeasureDynamicHeight) {\n return null;\n }\n\n return inspectViewportHeightFromHtmlRootString(renderHtmlContent)\n .viewportHeightCss;\n }, [renderHtmlContent, shouldMeasureDynamicHeight]);\n\n useEffect(() => {\n renderViewportHeightCssRef.current = rootViewportHeightCss;\n }, [rootViewportHeightCss]);\n\n const hasRootVhHeight = Boolean(rootViewportHeightCss);\n const sandboxViewportHeight =\n isBlackboardMode && type === \"sandbox\"\n ? shouldStretchRootHeight\n ? \"100%\"\n : (rootViewportHeightCss ?? `${height}px`)\n : undefined;\n useEffect(() => {\n if (mode !== \"blackboard\") {\n prevHtmlRef.current = normalizedHtmlContent;\n return;\n }\n const prev = prevHtmlRef.current;\n const isContinuation = prev && normalizedHtmlContent.startsWith(prev);\n if (!isContinuation && prev) {\n setResetToken((token) => token + 1);\n }\n prevHtmlRef.current = normalizedHtmlContent;\n }, [mode, normalizedHtmlContent]);\n\n useEffect(() => {\n const iframe = iframeRef.current;\n if (!iframe) return undefined;\n\n const doc = iframe.contentDocument;\n if (!doc) return undefined;\n\n doc.open();\n doc.write(`<!DOCTYPE html>\n<html${mode === \"blackboard\" ? ' style=\"height: 100%;\"' : \"\"}>\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <style>\n :root { color-scheme: light; }\n html, body, #root { width: 100%; }\n ${mode === \"blackboard\" ? \"html, body, #root { height: 100%; }\" : \"\"}\n html, body { margin: 0; padding: 0; overflow: ${mode === \"blackboard\" ? \"auto\" : \"hidden\"}; }\n *, *::before, *::after { box-sizing: border-box; }\n ${mode !== \"blackboard\" ? `\n .h-screen { height: auto !important; }\n .min-h-screen { min-height: auto !important; }\n .h-dvh, .h-svh, .h-lvh { height: auto !important; }\n .min-h-dvh, .min-h-svh, .min-h-lvh { min-height: auto !important; }\n ` : \"\"}\n </style>\n </head>\n <body>\n <div id=\"root\"></div>\n </body>\n</html>`);\n doc.close();\n\n // Force iframe theme to stay in light mode regardless of host OS preference.\n doc.documentElement.setAttribute(\"data-theme\", \"light\");\n doc.documentElement.style.colorScheme = \"light\";\n doc.body?.style.setProperty(\"color-scheme\", \"light\");\n\n const shouldBridgeSandboxInteraction =\n isBlackboardMode && type === \"sandbox\";\n const handleSandboxPointerDown = () =>\n emitSandboxInteraction(\"pointerdown\");\n const handleSandboxMouseDown = () => emitSandboxInteraction(\"mousedown\");\n const handleSandboxTouchStart = () => emitSandboxInteraction(\"touchstart\");\n\n if (shouldBridgeSandboxInteraction) {\n doc.addEventListener(\"pointerdown\", handleSandboxPointerDown, true);\n doc.addEventListener(\"mousedown\", handleSandboxMouseDown, true);\n doc.addEventListener(\"touchstart\", handleSandboxTouchStart, true);\n }\n\n const rootEl = doc.getElementById(\"root\");\n if (!rootEl) return undefined;\n\n const root = createRoot(rootEl);\n rootRef.current = root;\n let isDestroyed = false;\n const getHeightInspectionNode = (node: HTMLElement) => ({\n heightAttrValue: node.getAttribute(\"height\"),\n styleAttrValue: node.getAttribute(\"style\"),\n classAttrValue: node.getAttribute(\"class\"),\n });\n const getSingleChildElement = (node: HTMLElement) => {\n const childElements = Array.from(node.children) as HTMLElement[];\n\n return childElements.length === 1 ? childElements[0] : null;\n };\n\n const resolveExplicitHeight = () => {\n if (!shouldMeasureDynamicHeight) return null;\n if (!iframeRef.current || !doc.body) return null;\n const parentViewportHeight =\n iframeRef.current.ownerDocument?.documentElement?.clientHeight ||\n window.innerHeight;\n // Reuse parsed height metadata from the current html snapshot first to\n // avoid re-inspecting the same DOM chain on every height tick.\n const precomputedViewportHeightCss = renderViewportHeightCssRef.current;\n const parsed = precomputedViewportHeightCss\n ? parseExplicitHeight(\n precomputedViewportHeightCss,\n parentViewportHeight\n )\n : null;\n\n if (parsed !== null) {\n return Math.ceil(parsed);\n }\n\n const wrapper = doc.body.querySelector(\n \".sandbox-wrapper\"\n ) as HTMLElement | null;\n const container = wrapper?.firstElementChild as HTMLElement | null;\n if (!container) return null;\n const containerChildren = Array.from(container.children) as HTMLElement[];\n const rootContentElement =\n containerChildren.length === 1 ? containerChildren[0] : null;\n const runtimeHeightMeta = inspectViewportHeightFromNodeChain(\n rootContentElement,\n {\n getNode: getHeightInspectionNode,\n getSingleChild: getSingleChildElement,\n }\n );\n const runtimeViewportHeightCss = runtimeHeightMeta.viewportHeightCss;\n\n if (runtimeViewportHeightCss) {\n const runtimeViewportHeight = parseExplicitHeight(\n runtimeViewportHeightCss,\n parentViewportHeight\n );\n\n if (runtimeViewportHeight !== null) {\n return Math.ceil(runtimeViewportHeight);\n }\n }\n\n const explicitPixelHeight = resolveExplicitHeightFromNodeChain(\n rootContentElement,\n parentViewportHeight,\n {\n getNode: getHeightInspectionNode,\n getSingleChild: getSingleChildElement,\n }\n );\n\n return explicitPixelHeight !== null\n ? Math.ceil(explicitPixelHeight)\n : null;\n };\n\n const updateHeight = () => {\n if (!iframeRef.current || !doc.body) return;\n\n if (!isBlackboardMode) {\n // Guard: prevent re-entrant measurement from ResizeObserver /\n // MutationObserver callbacks triggered by our own height changes.\n if (isMeasuringContentRef.current) return;\n isMeasuringContentRef.current = true;\n\n // Content mode height measurement strategy:\n // The iframe CSS overrides .h-screen/.min-h-screen to height:auto,\n // removing viewport-height constraints. But content may still use\n // vmin units (font-size, padding, gap) which depend on\n // min(width, height). To get a stable measurement, temporarily\n // set iframe height >= containerWidth so vmin = width/100 (constant).\n const iframe = iframeRef.current;\n const cw = containerRef.current?.clientWidth || 0;\n const prevH = iframe.style.height;\n\n if (cw > 0) {\n iframe.style.height = cw + \"px\";\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n doc.body.offsetHeight; // force layout\n\n const measuredH = doc.body.scrollHeight;\n\n // Restore iframe to let React control it via contentModeStyle\n iframe.style.height = prevH;\n\n setContentHeight((prev) => {\n const next = Math.max(200, Math.ceil(measuredH));\n return prev === next ? prev : next;\n });\n }\n\n setTimeout(() => {\n isMeasuringContentRef.current = false;\n }, 50);\n return;\n }\n\n // Blackboard mode: use existing measurement logic\n const bodyScrollH = doc.body.scrollHeight;\n const htmlScrollH = doc.documentElement?.scrollHeight || 0;\n const rootScrollH = rootEl?.scrollHeight || 0;\n const measuredHeight = Math.max(bodyScrollH, htmlScrollH, rootScrollH);\n\n if (shouldMeasureDynamicHeight) {\n const explicitHeight = resolveExplicitHeight();\n const nextHeight = Math.max(\n 200,\n explicitHeight ?? Math.ceil(measuredHeight)\n );\n setHeight((prevHeight) =>\n prevHeight === nextHeight ? prevHeight : nextHeight\n );\n }\n };\n const scheduleHeightUpdate = () => {\n requestAnimationFrame(() => {\n if (isDestroyed) return;\n updateHeight();\n });\n };\n updateHeightRef.current = scheduleHeightUpdate;\n\n updateHeight();\n scheduleHeightUpdate();\n\n if (shouldInjectSandboxVendor) {\n // Inject Tailwind/DaisyUI/GSAP before rendering sandbox content to avoid FOUC.\n loadBlackboardVendor()\n .then((inject) => {\n if (isDestroyed) return;\n inject(doc);\n requestAnimationFrame(() => {\n if (isDestroyed) return;\n scheduleHeightUpdate();\n });\n })\n .catch(() => {\n if (isDestroyed) return;\n scheduleHeightUpdate();\n });\n }\n\n const resizeObserver = new ResizeObserver(() => updateHeight());\n resizeObserver.observe(doc.body);\n if (rootEl) {\n resizeObserver.observe(rootEl);\n }\n\n // MutationObserver: detect DOM changes that ResizeObserver might miss\n // (e.g. content injected by scripts, images loading, dynamic rendering)\n const mutationObserver = new MutationObserver(() => {\n scheduleHeightUpdate();\n });\n mutationObserver.observe(doc.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\"style\", \"class\"],\n });\n\n return () => {\n isDestroyed = true;\n resizeObserver.disconnect();\n mutationObserver.disconnect();\n if (shouldBridgeSandboxInteraction) {\n doc.removeEventListener(\"pointerdown\", handleSandboxPointerDown, true);\n doc.removeEventListener(\"mousedown\", handleSandboxMouseDown, true);\n doc.removeEventListener(\"touchstart\", handleSandboxTouchStart, true);\n }\n // Defer unmount to avoid React warning when parent is mid-render\n setTimeout(() => {\n root.unmount();\n rootRef.current = null;\n updateHeightRef.current = () => {};\n }, 0);\n };\n }, []);\n\n useEffect(() => {\n const onFullscreenChange = () => {\n setIsFullscreen(Boolean(document.fullscreenElement));\n };\n document.addEventListener(\"fullscreenchange\", onFullscreenChange);\n return () =>\n document.removeEventListener(\"fullscreenchange\", onFullscreenChange);\n }, []);\n\n // Track container width for computing min-height in content mode\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n const ro = new ResizeObserver((entries) => {\n setContainerWidth(entries[0]?.contentRect.width ?? el.clientWidth);\n });\n ro.observe(el);\n setContainerWidth(el.clientWidth);\n return () => ro.disconnect();\n }, []);\n\n // Content mode: min 16:9 aspect ratio, grow to fit content (no scrollbar)\n const contentModeStyle = useMemo<React.CSSProperties | undefined>(() => {\n if (isBlackboardMode || containerWidth === 0 || isFullscreen)\n return undefined;\n const minH = Math.round((containerWidth * 9) / 16);\n const h = Math.max(minH, contentHeight);\n return { height: h };\n }, [isBlackboardMode, containerWidth, contentHeight, isFullscreen]);\n\n const toggleFullscreen = () => {\n const target = containerRef.current || iframeRef.current;\n if (!target) return;\n if (document.fullscreenElement) {\n document.exitFullscreen().catch(() => {});\n return;\n }\n if (target.requestFullscreen) {\n target.requestFullscreen().catch(() => {});\n }\n };\n\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n\n root.render(\n <SandboxApp\n html={renderHtmlContent}\n styleLoadingText={styleLoadingText}\n scriptLoadingText={scriptLoadingText}\n resetToken={resetToken}\n hasRootVhHeight={hasRootVhHeight}\n mode={mode}\n stretchRootHeight={shouldStretchRootHeight}\n />\n );\n\n // Schedule multiple measurements to catch async content (scripts, images, styles).\n initialPaintFrameRef.current = window.requestAnimationFrame(() => {\n updateHeightRef.current?.();\n initialPaintFrameRef.current = null;\n });\n const t1 = setTimeout(() => updateHeightRef.current?.(), 100);\n const t2 = setTimeout(() => updateHeightRef.current?.(), 500);\n return () => {\n clearTimeout(t1);\n clearTimeout(t2);\n };\n }, [\n renderHtmlContent,\n styleLoadingText,\n scriptLoadingText,\n resetToken,\n mode,\n ]);\n const containerClassName = [\n \"w-full relative content-render-iframe-sandbox\",\n isBlackboardMode\n ? \"h-full overflow-auto flex flex-col\"\n : contentModeStyle\n ? \"overflow-hidden flex items-center justify-center\"\n : \"aspect-[16/9] overflow-hidden flex items-center justify-center\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div\n ref={containerRef}\n data-root-vh={hasRootVhHeight ? \"true\" : \"false\"}\n className={containerClassName}\n style={\n sandboxViewportHeight\n ? {\n height: sandboxViewportHeight,\n minHeight: sandboxViewportHeight,\n }\n : contentModeStyle\n }\n >\n {!hideFullScreen && (\n <button\n type=\"button\"\n onClick={toggleFullscreen}\n className={\n \"absolute top-2 right-2 z-50 p-1.5 bg-black/75 text-white rounded-md cursor-pointer\"\n }\n >\n {isFullscreen ? \"退出全屏\" : fullScreenButtonText || \"全屏浏览\"}\n </button>\n )}\n {mode === \"blackboard\" && type === \"markdown\" ? (\n <div\n onMouseDown={() => emitSandboxInteraction(\"mousedown\")}\n onPointerDown={() => emitSandboxInteraction(\"pointerdown\")}\n onTouchStart={() => emitSandboxInteraction(\"touchstart\")}\n >\n <ContentRender content={content} />\n </div>\n ) : (\n <iframe\n ref={iframeRef}\n sandbox=\"allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox\"\n allow=\"fullscreen\"\n allowFullScreen\n className={[className, \"w-full h-full mx-auto my-auto block\"]\n .filter(Boolean)\n .join(\" \")}\n style={{\n height: sandboxViewportHeight ?? \"100%\",\n minHeight: sandboxViewportHeight,\n margin: \"auto\",\n }}\n />\n )}\n </div>\n );\n};\n\nexport default IframeSandbox;\n"],"names":["blackboardVendorPromise","loadBlackboardVendor","m","COMPLETE_IMAGE_TAG_PATTERN","POST_IMAGE_STREAM_DEBOUNCE_MS","SANDBOX_INTERACTION_THROTTLE_MS","replaceRootScreenHeightToken","className","token","segments","replaceRootScreenHeightWithFullClass","html","enabled","match","tagStart","attrs","classMatch","nextClassName","IframeSandbox","content","type","styleLoadingText","scriptLoadingText","fullScreenButtonText","hideFullScreen","mode","replaceRootScreenHeightWithFull","containerRef","useRef","iframeRef","rootRef","updateHeightRef","height","setHeight","useState","contentHeight","setContentHeight","containerWidth","setContainerWidth","isMeasuringContentRef","lastSandboxInteractionTimeRef","resetToken","setResetToken","isFullscreen","setIsFullscreen","shouldInjectSandboxVendor","isBlackboardMode","shouldMeasureDynamicHeight","shouldProcessRootScreenHeight","prevHtmlRef","htmlContent","React","normalizedHtmlContent","originalRootHeightMeta","inspectViewportHeightFromHtmlRootString","EMPTY_ROOT_HEIGHT_META","shouldStretchRootHeight","renderHtmlContent","setRenderHtmlContent","prevIncomingHtmlRef","pendingHtmlRef","deferRenderTimerRef","initialPaintFrameRef","renderViewportHeightCssRef","emitSandboxInteraction","useCallback","eventType","now","SANDBOX_INTERACTION_MESSAGE_SOURCE","SANDBOX_INTERACTION_MESSAGE_TYPE","clearDeferredRenderTimer","clearInitialPaintFrames","useEffect","prevIncomingHtml","isAppendOnlyStream","containsCompleteImage","rootViewportHeightCss","hasRootVhHeight","sandboxViewportHeight","prev","iframe","doc","shouldBridgeSandboxInteraction","handleSandboxPointerDown","handleSandboxMouseDown","handleSandboxTouchStart","rootEl","root","createRoot","isDestroyed","getHeightInspectionNode","node","getSingleChildElement","childElements","resolveExplicitHeight","parentViewportHeight","precomputedViewportHeightCss","parsed","parseExplicitHeight","container","containerChildren","rootContentElement","runtimeViewportHeightCss","inspectViewportHeightFromNodeChain","runtimeViewportHeight","explicitPixelHeight","resolveExplicitHeightFromNodeChain","updateHeight","cw","prevH","measuredH","next","bodyScrollH","htmlScrollH","rootScrollH","measuredHeight","explicitHeight","nextHeight","prevHeight","scheduleHeightUpdate","inject","resizeObserver","mutationObserver","onFullscreenChange","el","ro","entries","contentModeStyle","useMemo","minH","toggleFullscreen","target","jsx","SandboxApp","t1","t2","containerClassName","jsxs","ContentRender"],"mappings":"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"}
|
|
@@ -1,61 +1,61 @@
|
|
|
1
1
|
import { j as v } from "../../_virtual/jsx-runtime.es.js";
|
|
2
|
-
import _, { useRef as s, useState as x, useCallback as
|
|
2
|
+
import _, { useRef as s, useState as x, useCallback as Ie, useEffect as m, useMemo as Ne } from "react";
|
|
3
3
|
import { createRoot as _e } from "react-dom/client";
|
|
4
|
-
import
|
|
5
|
-
import
|
|
4
|
+
import Oe from "./SandboxApp.es.js";
|
|
5
|
+
import ke from "./ContentRender.es.js";
|
|
6
6
|
import { inspectViewportHeightFromHtmlRootString as we, EMPTY_ROOT_HEIGHT_META as Ve, parseExplicitHeight as He, inspectViewportHeightFromNodeChain as De, resolveExplicitHeightFromNodeChain as je } from "./utils/iframe-viewport-height.es.js";
|
|
7
7
|
import { SANDBOX_INTERACTION_MESSAGE_TYPE as Be, SANDBOX_INTERACTION_MESSAGE_SOURCE as Pe } from "../../lib/sandboxInteraction.es.js";
|
|
8
8
|
let J = null;
|
|
9
9
|
const Le = () => (J || (J = import("./blackboard-vendor.es.js").then(
|
|
10
|
-
(
|
|
11
|
-
)), J), $e = /<img\b[^>]*>/i,
|
|
10
|
+
(c) => c.injectBlackboardLibraries
|
|
11
|
+
)), J), $e = /<img\b[^>]*>/i, We = 180, ze = 240, qe = (c) => c.split(/\s+/).filter(Boolean).map((o) => {
|
|
12
12
|
const i = o.split(":");
|
|
13
13
|
return i[i.length - 1] !== "h-screen" && i[i.length - 1] !== "min-h-screen" ? o : (i[i.length - 1] = "h-full", i.join(":"));
|
|
14
|
-
}).join(" "), Ge = (
|
|
14
|
+
}).join(" "), Ge = (c, o) => !o || !c.trim() ? c : c.replace(
|
|
15
15
|
/^(\s*<[a-zA-Z][\w:-]*)(\s[^>]*?)?>/,
|
|
16
|
-
(i,
|
|
16
|
+
(i, O, E = "") => {
|
|
17
17
|
const a = E.match(/\bclass\s*=\s*(["'])([^"']*)\1/i);
|
|
18
18
|
if (!a)
|
|
19
19
|
return i;
|
|
20
|
-
const
|
|
21
|
-
return
|
|
20
|
+
const k = qe(a[2]);
|
|
21
|
+
return k === a[2] ? i : `${O}${E.replace(
|
|
22
22
|
a[0],
|
|
23
|
-
`class=${a[1]}${
|
|
23
|
+
`class=${a[1]}${k}${a[1]}`
|
|
24
24
|
)}>`;
|
|
25
25
|
}
|
|
26
26
|
), et = ({
|
|
27
|
-
content:
|
|
27
|
+
content: c,
|
|
28
28
|
type: o,
|
|
29
29
|
className: i,
|
|
30
|
-
styleLoadingText:
|
|
30
|
+
styleLoadingText: O,
|
|
31
31
|
scriptLoadingText: E,
|
|
32
32
|
fullScreenButtonText: a,
|
|
33
|
-
hideFullScreen:
|
|
34
|
-
mode:
|
|
33
|
+
hideFullScreen: k = !1,
|
|
34
|
+
mode: l = "content",
|
|
35
35
|
replaceRootScreenHeightWithFull: ve = !1
|
|
36
36
|
}) => {
|
|
37
|
-
const
|
|
38
|
-
}), [xe, Ee] = x(480), [K, Re] = x(0), [$, Q] = x(0),
|
|
39
|
-
() => o === "sandbox" ?
|
|
40
|
-
[
|
|
37
|
+
const V = s(null), f = s(null), L = s(null), R = s(() => {
|
|
38
|
+
}), [xe, Ee] = x(480), [K, Re] = x(0), [$, Q] = x(0), W = s(!1), ee = s(0), [te, Se] = x(0), [z, Ce] = x(!1), Me = o === "sandbox", g = l === "blackboard", S = g && o === "sandbox", w = S && ve, q = s(""), D = _.useMemo(
|
|
39
|
+
() => o === "sandbox" ? c : "",
|
|
40
|
+
[c, o]
|
|
41
41
|
), n = _.useMemo(
|
|
42
42
|
() => Ge(
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
D,
|
|
44
|
+
w
|
|
45
45
|
),
|
|
46
|
-
[
|
|
46
|
+
[D, w]
|
|
47
47
|
), ne = _.useMemo(
|
|
48
|
-
() =>
|
|
49
|
-
[
|
|
48
|
+
() => w ? we(D) : Ve,
|
|
49
|
+
[D, w]
|
|
50
50
|
), re = _.useMemo(
|
|
51
|
-
() =>
|
|
51
|
+
() => w && ne.hasFullViewportHeight,
|
|
52
52
|
[
|
|
53
53
|
ne.hasFullViewportHeight,
|
|
54
|
-
|
|
54
|
+
w
|
|
55
55
|
]
|
|
56
|
-
), [
|
|
56
|
+
), [j, oe] = x(
|
|
57
57
|
n
|
|
58
|
-
), ie = s(n), G = s(n), C = s(null), M = s(null), se = s(null),
|
|
58
|
+
), ie = s(n), G = s(n), C = s(null), M = s(null), se = s(null), H = Ie((t) => {
|
|
59
59
|
if (typeof window > "u")
|
|
60
60
|
return;
|
|
61
61
|
const e = Date.now();
|
|
@@ -89,44 +89,49 @@ const Le = () => (J || (J = import("./blackboard-vendor.es.js").then(
|
|
|
89
89
|
}
|
|
90
90
|
G.current = n, U(), C.current = window.setTimeout(() => {
|
|
91
91
|
oe(G.current), C.current = null;
|
|
92
|
-
},
|
|
92
|
+
}, We);
|
|
93
93
|
}, [n]);
|
|
94
|
-
const
|
|
94
|
+
const B = _.useMemo(() => S ? we(j).viewportHeightCss : null, [j, S]);
|
|
95
95
|
m(() => {
|
|
96
|
-
se.current =
|
|
97
|
-
}, [
|
|
98
|
-
const
|
|
96
|
+
se.current = B;
|
|
97
|
+
}, [B]);
|
|
98
|
+
const ce = !!B, y = g && o === "sandbox" ? re ? "100%" : B ?? `${xe}px` : void 0;
|
|
99
99
|
m(() => {
|
|
100
|
-
if (
|
|
101
|
-
|
|
100
|
+
if (l !== "blackboard") {
|
|
101
|
+
q.current = n;
|
|
102
102
|
return;
|
|
103
103
|
}
|
|
104
|
-
const t =
|
|
105
|
-
!(t && n.startsWith(t)) && t && Se((u) => u + 1),
|
|
106
|
-
}, [
|
|
107
|
-
const t =
|
|
104
|
+
const t = q.current;
|
|
105
|
+
!(t && n.startsWith(t)) && t && Se((u) => u + 1), q.current = n;
|
|
106
|
+
}, [l, n]), m(() => {
|
|
107
|
+
const t = f.current;
|
|
108
108
|
if (!t) return;
|
|
109
109
|
const e = t.contentDocument;
|
|
110
110
|
if (!e) return;
|
|
111
111
|
e.open(), e.write(`<!DOCTYPE html>
|
|
112
|
-
<html${
|
|
112
|
+
<html${l === "blackboard" ? ' style="height: 100%;"' : ""}>
|
|
113
113
|
<head>
|
|
114
114
|
<meta charset="utf-8" />
|
|
115
115
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
116
116
|
<style>
|
|
117
117
|
:root { color-scheme: light; }
|
|
118
118
|
html, body, #root { width: 100%; }
|
|
119
|
-
${
|
|
120
|
-
html, body { margin: 0; padding: 0; overflow: ${
|
|
119
|
+
${l === "blackboard" ? "html, body, #root { height: 100%; }" : ""}
|
|
120
|
+
html, body { margin: 0; padding: 0; overflow: ${l === "blackboard" ? "auto" : "hidden"}; }
|
|
121
121
|
*, *::before, *::after { box-sizing: border-box; }
|
|
122
|
-
${
|
|
122
|
+
${l !== "blackboard" ? `
|
|
123
|
+
.h-screen { height: auto !important; }
|
|
124
|
+
.min-h-screen { min-height: auto !important; }
|
|
125
|
+
.h-dvh, .h-svh, .h-lvh { height: auto !important; }
|
|
126
|
+
.min-h-dvh, .min-h-svh, .min-h-lvh { min-height: auto !important; }
|
|
127
|
+
` : ""}
|
|
123
128
|
</style>
|
|
124
129
|
</head>
|
|
125
130
|
<body>
|
|
126
131
|
<div id="root"></div>
|
|
127
132
|
</body>
|
|
128
133
|
</html>`), e.close(), e.documentElement.setAttribute("data-theme", "light"), e.documentElement.style.colorScheme = "light", e.body?.style.setProperty("color-scheme", "light");
|
|
129
|
-
const u =
|
|
134
|
+
const u = g && o === "sandbox", X = () => H("pointerdown"), ue = () => H("mousedown"), ae = () => H("touchstart");
|
|
130
135
|
u && (e.addEventListener("pointerdown", X, !0), e.addEventListener("mousedown", ue, !0), e.addEventListener("touchstart", ae, !0));
|
|
131
136
|
const T = e.getElementById("root");
|
|
132
137
|
if (!T) return;
|
|
@@ -138,72 +143,71 @@ const Le = () => (J || (J = import("./blackboard-vendor.es.js").then(
|
|
|
138
143
|
styleAttrValue: r.getAttribute("style"),
|
|
139
144
|
classAttrValue: r.getAttribute("class")
|
|
140
145
|
}), me = (r) => {
|
|
141
|
-
const
|
|
142
|
-
return
|
|
146
|
+
const p = Array.from(r.children);
|
|
147
|
+
return p.length === 1 ? p[0] : null;
|
|
143
148
|
}, Fe = () => {
|
|
144
|
-
if (!S || !
|
|
145
|
-
const r =
|
|
146
|
-
|
|
149
|
+
if (!S || !f.current || !e.body) return null;
|
|
150
|
+
const r = f.current.ownerDocument?.documentElement?.clientHeight || window.innerHeight, p = se.current, P = p ? He(
|
|
151
|
+
p,
|
|
147
152
|
r
|
|
148
153
|
) : null;
|
|
149
|
-
if (
|
|
150
|
-
return Math.ceil(
|
|
154
|
+
if (P !== null)
|
|
155
|
+
return Math.ceil(P);
|
|
151
156
|
const h = e.body.querySelector(
|
|
152
157
|
".sandbox-wrapper"
|
|
153
158
|
)?.firstElementChild;
|
|
154
159
|
if (!h) return null;
|
|
155
|
-
const d = Array.from(h.children),
|
|
156
|
-
|
|
160
|
+
const d = Array.from(h.children), b = d.length === 1 ? d[0] : null, I = De(
|
|
161
|
+
b,
|
|
157
162
|
{
|
|
158
163
|
getNode: de,
|
|
159
164
|
getSingleChild: me
|
|
160
165
|
}
|
|
161
166
|
).viewportHeightCss;
|
|
162
|
-
if (
|
|
163
|
-
const
|
|
164
|
-
|
|
167
|
+
if (I) {
|
|
168
|
+
const be = He(
|
|
169
|
+
I,
|
|
165
170
|
r
|
|
166
171
|
);
|
|
167
|
-
if (
|
|
168
|
-
return Math.ceil(
|
|
172
|
+
if (be !== null)
|
|
173
|
+
return Math.ceil(be);
|
|
169
174
|
}
|
|
170
|
-
const
|
|
171
|
-
|
|
175
|
+
const N = je(
|
|
176
|
+
b,
|
|
172
177
|
r,
|
|
173
178
|
{
|
|
174
179
|
getNode: de,
|
|
175
180
|
getSingleChild: me
|
|
176
181
|
}
|
|
177
182
|
);
|
|
178
|
-
return
|
|
183
|
+
return N !== null ? Math.ceil(N) : null;
|
|
179
184
|
}, Y = () => {
|
|
180
|
-
if (!
|
|
181
|
-
if (!
|
|
182
|
-
if (
|
|
183
|
-
|
|
184
|
-
const h =
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
return N === I ? N : I;
|
|
185
|
+
if (!f.current || !e.body) return;
|
|
186
|
+
if (!g) {
|
|
187
|
+
if (W.current) return;
|
|
188
|
+
W.current = !0;
|
|
189
|
+
const h = f.current, d = V.current?.clientWidth || 0, b = h.style.height;
|
|
190
|
+
if (d > 0) {
|
|
191
|
+
h.style.height = d + "px", e.body.offsetHeight;
|
|
192
|
+
const pe = e.body.scrollHeight;
|
|
193
|
+
h.style.height = b, Re((I) => {
|
|
194
|
+
const N = Math.max(200, Math.ceil(pe));
|
|
195
|
+
return I === N ? I : N;
|
|
192
196
|
});
|
|
193
197
|
}
|
|
194
198
|
setTimeout(() => {
|
|
195
|
-
|
|
199
|
+
W.current = !1;
|
|
196
200
|
}, 50);
|
|
197
201
|
return;
|
|
198
202
|
}
|
|
199
|
-
const r = e.body.scrollHeight,
|
|
203
|
+
const r = e.body.scrollHeight, p = e.documentElement?.scrollHeight || 0, P = T?.scrollHeight || 0, ge = Math.max(r, p, P);
|
|
200
204
|
if (S) {
|
|
201
205
|
const h = Fe(), d = Math.max(
|
|
202
206
|
200,
|
|
203
207
|
h ?? Math.ceil(ge)
|
|
204
208
|
);
|
|
205
209
|
Ee(
|
|
206
|
-
(
|
|
210
|
+
(b) => b === d ? b : d
|
|
207
211
|
);
|
|
208
212
|
}
|
|
209
213
|
}, F = () => {
|
|
@@ -240,20 +244,20 @@ const Le = () => (J || (J = import("./blackboard-vendor.es.js").then(
|
|
|
240
244
|
};
|
|
241
245
|
return document.addEventListener("fullscreenchange", t), () => document.removeEventListener("fullscreenchange", t);
|
|
242
246
|
}, []), m(() => {
|
|
243
|
-
const t =
|
|
247
|
+
const t = V.current;
|
|
244
248
|
if (!t) return;
|
|
245
249
|
const e = new ResizeObserver((u) => {
|
|
246
250
|
Q(u[0]?.contentRect.width ?? t.clientWidth);
|
|
247
251
|
});
|
|
248
252
|
return e.observe(t), Q(t.clientWidth), () => e.disconnect();
|
|
249
253
|
}, []);
|
|
250
|
-
const
|
|
251
|
-
if (
|
|
254
|
+
const le = Ne(() => {
|
|
255
|
+
if (g || $ === 0 || z)
|
|
252
256
|
return;
|
|
253
257
|
const t = Math.round($ * 9 / 16);
|
|
254
258
|
return { height: Math.max(t, K) };
|
|
255
|
-
}, [
|
|
256
|
-
const t =
|
|
259
|
+
}, [g, $, K, z]), Te = () => {
|
|
260
|
+
const t = V.current || f.current;
|
|
257
261
|
if (t) {
|
|
258
262
|
if (document.fullscreenElement) {
|
|
259
263
|
document.exitFullscreen().catch(() => {
|
|
@@ -269,14 +273,14 @@ const Le = () => (J || (J = import("./blackboard-vendor.es.js").then(
|
|
|
269
273
|
if (!t) return;
|
|
270
274
|
t.render(
|
|
271
275
|
/* @__PURE__ */ v.jsx(
|
|
272
|
-
|
|
276
|
+
Oe,
|
|
273
277
|
{
|
|
274
|
-
html:
|
|
275
|
-
styleLoadingText:
|
|
278
|
+
html: j,
|
|
279
|
+
styleLoadingText: O,
|
|
276
280
|
scriptLoadingText: E,
|
|
277
281
|
resetToken: te,
|
|
278
|
-
hasRootVhHeight:
|
|
279
|
-
mode:
|
|
282
|
+
hasRootVhHeight: ce,
|
|
283
|
+
mode: l,
|
|
280
284
|
stretchRootHeight: re
|
|
281
285
|
}
|
|
282
286
|
)
|
|
@@ -288,28 +292,28 @@ const Le = () => (J || (J = import("./blackboard-vendor.es.js").then(
|
|
|
288
292
|
clearTimeout(e), clearTimeout(u);
|
|
289
293
|
};
|
|
290
294
|
}, [
|
|
291
|
-
|
|
292
|
-
|
|
295
|
+
j,
|
|
296
|
+
O,
|
|
293
297
|
E,
|
|
294
298
|
te,
|
|
295
|
-
|
|
299
|
+
l
|
|
296
300
|
]);
|
|
297
301
|
const Ae = [
|
|
298
302
|
"w-full relative content-render-iframe-sandbox",
|
|
299
|
-
|
|
303
|
+
g ? "h-full overflow-auto flex flex-col" : le ? "overflow-hidden flex items-center justify-center" : "aspect-[16/9] overflow-hidden flex items-center justify-center"
|
|
300
304
|
].filter(Boolean).join(" ");
|
|
301
305
|
return /* @__PURE__ */ v.jsxs(
|
|
302
306
|
"div",
|
|
303
307
|
{
|
|
304
|
-
ref:
|
|
305
|
-
"data-root-vh":
|
|
308
|
+
ref: V,
|
|
309
|
+
"data-root-vh": ce ? "true" : "false",
|
|
306
310
|
className: Ae,
|
|
307
311
|
style: y ? {
|
|
308
312
|
height: y,
|
|
309
313
|
minHeight: y
|
|
310
|
-
} :
|
|
314
|
+
} : le,
|
|
311
315
|
children: [
|
|
312
|
-
!
|
|
316
|
+
!k && /* @__PURE__ */ v.jsx(
|
|
313
317
|
"button",
|
|
314
318
|
{
|
|
315
319
|
type: "button",
|
|
@@ -318,18 +322,18 @@ const Le = () => (J || (J = import("./blackboard-vendor.es.js").then(
|
|
|
318
322
|
children: z ? "退出全屏" : a || "全屏浏览"
|
|
319
323
|
}
|
|
320
324
|
),
|
|
321
|
-
|
|
325
|
+
l === "blackboard" && o === "markdown" ? /* @__PURE__ */ v.jsx(
|
|
322
326
|
"div",
|
|
323
327
|
{
|
|
324
|
-
onMouseDown: () =>
|
|
325
|
-
onPointerDown: () =>
|
|
326
|
-
onTouchStart: () =>
|
|
327
|
-
children: /* @__PURE__ */ v.jsx(
|
|
328
|
+
onMouseDown: () => H("mousedown"),
|
|
329
|
+
onPointerDown: () => H("pointerdown"),
|
|
330
|
+
onTouchStart: () => H("touchstart"),
|
|
331
|
+
children: /* @__PURE__ */ v.jsx(ke, { content: c })
|
|
328
332
|
}
|
|
329
333
|
) : /* @__PURE__ */ v.jsx(
|
|
330
334
|
"iframe",
|
|
331
335
|
{
|
|
332
|
-
ref:
|
|
336
|
+
ref: f,
|
|
333
337
|
sandbox: "allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox",
|
|
334
338
|
allow: "fullscreen",
|
|
335
339
|
allowFullScreen: !0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IframeSandbox.es.js","sources":["../../../src/components/ContentRender/IframeSandbox.tsx"],"sourcesContent":["import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { createRoot, Root } from \"react-dom/client\";\nimport SandboxApp from \"./SandboxApp\";\nimport ContentRender from \"./ContentRender\";\nimport {\n EMPTY_ROOT_HEIGHT_META,\n inspectViewportHeightFromHtmlRootString,\n inspectViewportHeightFromNodeChain,\n parseExplicitHeight,\n resolveExplicitHeightFromNodeChain,\n} from \"./utils/iframe-viewport-height\";\nimport {\n SANDBOX_INTERACTION_MESSAGE_SOURCE,\n SANDBOX_INTERACTION_MESSAGE_TYPE,\n} from \"../../lib/sandboxInteraction\";\n\ntype InjectBlackboardLibraries =\n typeof import(\"./blackboard-vendor\").injectBlackboardLibraries;\n\n// Cache the sandbox vendor loader so every iframe reuses the same preload request.\nlet blackboardVendorPromise: Promise<InjectBlackboardLibraries> | null = null;\n\nconst loadBlackboardVendor = () => {\n if (!blackboardVendorPromise) {\n blackboardVendorPromise = import(\"./blackboard-vendor\").then(\n (m) => m.injectBlackboardLibraries\n );\n }\n\n return blackboardVendorPromise;\n};\n\nconst COMPLETE_IMAGE_TAG_PATTERN = /<img\\b[^>]*>/i;\nconst POST_IMAGE_STREAM_DEBOUNCE_MS = 180;\nconst SANDBOX_INTERACTION_THROTTLE_MS = 240;\n\nexport interface IframeSandboxProps {\n content: string;\n className?: string;\n loadingText?: string;\n styleLoadingText?: string;\n scriptLoadingText?: string;\n fullScreenButtonText?: string;\n hideFullScreen?: boolean;\n mode?: \"content\" | \"blackboard\";\n type: \"sandbox\" | \"markdown\";\n replaceRootScreenHeightWithFull?: boolean;\n}\n\nconst replaceRootScreenHeightToken = (className: string) =>\n className\n .split(/\\s+/)\n .filter(Boolean)\n .map((token) => {\n const segments = token.split(\":\");\n if (\n segments[segments.length - 1] !== \"h-screen\" &&\n segments[segments.length - 1] !== \"min-h-screen\"\n ) {\n return token;\n }\n segments[segments.length - 1] = \"h-full\";\n return segments.join(\":\");\n })\n .join(\" \");\n\nconst replaceRootScreenHeightWithFullClass = (\n html: string,\n enabled: boolean\n) => {\n if (!enabled || !html.trim()) {\n return html;\n }\n\n return html.replace(\n /^(\\s*<[a-zA-Z][\\w:-]*)(\\s[^>]*?)?>/,\n (match, tagStart: string, attrs = \"\") => {\n const classMatch = attrs.match(/\\bclass\\s*=\\s*([\"'])([^\"']*)\\1/i);\n\n if (!classMatch) {\n return match;\n }\n\n const nextClassName = replaceRootScreenHeightToken(classMatch[2]);\n\n if (nextClassName === classMatch[2]) {\n return match;\n }\n\n return `${tagStart}${attrs.replace(\n classMatch[0],\n `class=${classMatch[1]}${nextClassName}${classMatch[1]}`\n )}>`;\n }\n );\n};\n\nconst IframeSandbox: React.FC<IframeSandboxProps> = ({\n content,\n type,\n className,\n styleLoadingText,\n scriptLoadingText,\n fullScreenButtonText,\n hideFullScreen = false,\n mode = \"content\",\n replaceRootScreenHeightWithFull = false,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const rootRef = useRef<Root | null>(null);\n const updateHeightRef = useRef<() => void>(() => {});\n const [height, setHeight] = useState(480);\n const [contentHeight, setContentHeight] = useState(0);\n const [containerWidth, setContainerWidth] = useState(0);\n const isMeasuringContentRef = useRef(false);\n const lastSandboxInteractionTimeRef = useRef(0);\n const [resetToken, setResetToken] = useState(0);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const shouldInjectSandboxVendor = type === \"sandbox\";\n\n const isBlackboardMode = mode === \"blackboard\";\n const shouldMeasureDynamicHeight = isBlackboardMode && type === \"sandbox\";\n const shouldProcessRootScreenHeight =\n shouldMeasureDynamicHeight && replaceRootScreenHeightWithFull;\n const prevHtmlRef = useRef<string>(\"\");\n const htmlContent = React.useMemo(\n () => (type === \"sandbox\" ? content : \"\"),\n [content, type]\n );\n const normalizedHtmlContent = React.useMemo(\n () =>\n replaceRootScreenHeightWithFullClass(\n htmlContent,\n shouldProcessRootScreenHeight\n ),\n [htmlContent, shouldProcessRootScreenHeight]\n );\n const originalRootHeightMeta = React.useMemo(\n () =>\n shouldProcessRootScreenHeight\n ? inspectViewportHeightFromHtmlRootString(htmlContent)\n : EMPTY_ROOT_HEIGHT_META,\n [htmlContent, shouldProcessRootScreenHeight]\n );\n const shouldStretchRootHeight = React.useMemo(\n () =>\n shouldProcessRootScreenHeight &&\n originalRootHeightMeta.hasFullViewportHeight,\n [\n originalRootHeightMeta.hasFullViewportHeight,\n shouldProcessRootScreenHeight,\n ]\n );\n const [renderHtmlContent, setRenderHtmlContent] = useState(\n normalizedHtmlContent\n );\n const prevIncomingHtmlRef = useRef(normalizedHtmlContent);\n const pendingHtmlRef = useRef(normalizedHtmlContent);\n const deferRenderTimerRef = useRef<number | null>(null);\n const initialPaintFrameRef = useRef<number | null>(null);\n const renderViewportHeightCssRef = useRef<string | null>(null);\n\n const emitSandboxInteraction = useCallback((eventType: string) => {\n if (typeof window === \"undefined\") {\n return;\n }\n const now = Date.now();\n if (\n now - lastSandboxInteractionTimeRef.current <\n SANDBOX_INTERACTION_THROTTLE_MS\n ) {\n return;\n }\n lastSandboxInteractionTimeRef.current = now;\n window.postMessage(\n {\n source: SANDBOX_INTERACTION_MESSAGE_SOURCE,\n type: SANDBOX_INTERACTION_MESSAGE_TYPE,\n eventType,\n },\n window.location.origin\n );\n }, []);\n\n const clearDeferredRenderTimer = () => {\n if (deferRenderTimerRef.current === null) return;\n window.clearTimeout(deferRenderTimerRef.current);\n deferRenderTimerRef.current = null;\n };\n\n const clearInitialPaintFrames = () => {\n if (initialPaintFrameRef.current !== null) {\n window.cancelAnimationFrame(initialPaintFrameRef.current);\n initialPaintFrameRef.current = null;\n }\n };\n\n useEffect(\n () => () => {\n clearDeferredRenderTimer();\n clearInitialPaintFrames();\n },\n []\n );\n\n useEffect(() => {\n const prevIncomingHtml = prevIncomingHtmlRef.current;\n prevIncomingHtmlRef.current = normalizedHtmlContent;\n\n const isAppendOnlyStream =\n !!prevIncomingHtml &&\n normalizedHtmlContent.length > prevIncomingHtml.length &&\n normalizedHtmlContent.startsWith(prevIncomingHtml);\n const containsCompleteImage = COMPLETE_IMAGE_TAG_PATTERN.test(\n normalizedHtmlContent\n );\n const shouldDeferRender = isAppendOnlyStream && containsCompleteImage;\n\n if (!shouldDeferRender) {\n clearDeferredRenderTimer();\n pendingHtmlRef.current = normalizedHtmlContent;\n setRenderHtmlContent(normalizedHtmlContent);\n return;\n }\n\n pendingHtmlRef.current = normalizedHtmlContent;\n clearDeferredRenderTimer();\n deferRenderTimerRef.current = window.setTimeout(() => {\n setRenderHtmlContent(pendingHtmlRef.current);\n deferRenderTimerRef.current = null;\n }, POST_IMAGE_STREAM_DEBOUNCE_MS);\n }, [normalizedHtmlContent]);\n\n const rootViewportHeightCss = React.useMemo(() => {\n if (!shouldMeasureDynamicHeight) {\n return null;\n }\n\n return inspectViewportHeightFromHtmlRootString(renderHtmlContent)\n .viewportHeightCss;\n }, [renderHtmlContent, shouldMeasureDynamicHeight]);\n\n useEffect(() => {\n renderViewportHeightCssRef.current = rootViewportHeightCss;\n }, [rootViewportHeightCss]);\n\n const hasRootVhHeight = Boolean(rootViewportHeightCss);\n const sandboxViewportHeight =\n isBlackboardMode && type === \"sandbox\"\n ? shouldStretchRootHeight\n ? \"100%\"\n : (rootViewportHeightCss ?? `${height}px`)\n : undefined;\n useEffect(() => {\n if (mode !== \"blackboard\") {\n prevHtmlRef.current = normalizedHtmlContent;\n return;\n }\n const prev = prevHtmlRef.current;\n const isContinuation = prev && normalizedHtmlContent.startsWith(prev);\n if (!isContinuation && prev) {\n setResetToken((token) => token + 1);\n }\n prevHtmlRef.current = normalizedHtmlContent;\n }, [mode, normalizedHtmlContent]);\n\n useEffect(() => {\n const iframe = iframeRef.current;\n if (!iframe) return undefined;\n\n const doc = iframe.contentDocument;\n if (!doc) return undefined;\n\n doc.open();\n doc.write(`<!DOCTYPE html>\n<html${mode === \"blackboard\" ? ' style=\"height: 100%;\"' : \"\"}>\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <style>\n :root { color-scheme: light; }\n html, body, #root { width: 100%; }\n ${mode === \"blackboard\" ? \"html, body, #root { height: 100%; }\" : \"html { height: 100%; overflow: hidden; }\"}\n html, body { margin: 0; padding: 0; overflow: ${mode === \"blackboard\" ? \"auto\" : \"hidden\"}; }\n *, *::before, *::after { box-sizing: border-box; }\n ${mode !== \"blackboard\" ? \".overflow-y-auto, .overflow-auto { scrollbar-width: none !important; } .overflow-y-auto::-webkit-scrollbar, .overflow-auto::-webkit-scrollbar { display: none !important; }\" : \"\"}\n </style>\n </head>\n <body>\n <div id=\"root\"></div>\n </body>\n</html>`);\n doc.close();\n\n // Force iframe theme to stay in light mode regardless of host OS preference.\n doc.documentElement.setAttribute(\"data-theme\", \"light\");\n doc.documentElement.style.colorScheme = \"light\";\n doc.body?.style.setProperty(\"color-scheme\", \"light\");\n\n const shouldBridgeSandboxInteraction =\n isBlackboardMode && type === \"sandbox\";\n const handleSandboxPointerDown = () =>\n emitSandboxInteraction(\"pointerdown\");\n const handleSandboxMouseDown = () => emitSandboxInteraction(\"mousedown\");\n const handleSandboxTouchStart = () => emitSandboxInteraction(\"touchstart\");\n\n if (shouldBridgeSandboxInteraction) {\n doc.addEventListener(\"pointerdown\", handleSandboxPointerDown, true);\n doc.addEventListener(\"mousedown\", handleSandboxMouseDown, true);\n doc.addEventListener(\"touchstart\", handleSandboxTouchStart, true);\n }\n\n const rootEl = doc.getElementById(\"root\");\n if (!rootEl) return undefined;\n\n const root = createRoot(rootEl);\n rootRef.current = root;\n let isDestroyed = false;\n const getHeightInspectionNode = (node: HTMLElement) => ({\n heightAttrValue: node.getAttribute(\"height\"),\n styleAttrValue: node.getAttribute(\"style\"),\n classAttrValue: node.getAttribute(\"class\"),\n });\n const getSingleChildElement = (node: HTMLElement) => {\n const childElements = Array.from(node.children) as HTMLElement[];\n\n return childElements.length === 1 ? childElements[0] : null;\n };\n\n const resolveExplicitHeight = () => {\n if (!shouldMeasureDynamicHeight) return null;\n if (!iframeRef.current || !doc.body) return null;\n const parentViewportHeight =\n iframeRef.current.ownerDocument?.documentElement?.clientHeight ||\n window.innerHeight;\n // Reuse parsed height metadata from the current html snapshot first to\n // avoid re-inspecting the same DOM chain on every height tick.\n const precomputedViewportHeightCss = renderViewportHeightCssRef.current;\n const parsed = precomputedViewportHeightCss\n ? parseExplicitHeight(\n precomputedViewportHeightCss,\n parentViewportHeight\n )\n : null;\n\n if (parsed !== null) {\n return Math.ceil(parsed);\n }\n\n const wrapper = doc.body.querySelector(\n \".sandbox-wrapper\"\n ) as HTMLElement | null;\n const container = wrapper?.firstElementChild as HTMLElement | null;\n if (!container) return null;\n const containerChildren = Array.from(container.children) as HTMLElement[];\n const rootContentElement =\n containerChildren.length === 1 ? containerChildren[0] : null;\n const runtimeHeightMeta = inspectViewportHeightFromNodeChain(\n rootContentElement,\n {\n getNode: getHeightInspectionNode,\n getSingleChild: getSingleChildElement,\n }\n );\n const runtimeViewportHeightCss = runtimeHeightMeta.viewportHeightCss;\n\n if (runtimeViewportHeightCss) {\n const runtimeViewportHeight = parseExplicitHeight(\n runtimeViewportHeightCss,\n parentViewportHeight\n );\n\n if (runtimeViewportHeight !== null) {\n return Math.ceil(runtimeViewportHeight);\n }\n }\n\n const explicitPixelHeight = resolveExplicitHeightFromNodeChain(\n rootContentElement,\n parentViewportHeight,\n {\n getNode: getHeightInspectionNode,\n getSingleChild: getSingleChildElement,\n }\n );\n\n return explicitPixelHeight !== null\n ? Math.ceil(explicitPixelHeight)\n : null;\n };\n\n const updateHeight = () => {\n if (!iframeRef.current || !doc.body) return;\n\n if (!isBlackboardMode) {\n // Guard: prevent re-entrant measurement from ResizeObserver /\n // MutationObserver callbacks triggered by our own height changes.\n if (isMeasuringContentRef.current) return;\n isMeasuringContentRef.current = true;\n\n const sc = doc.querySelector(\n \".sandbox-container\"\n ) as HTMLElement | null;\n const fc = sc?.firstElementChild as HTMLElement | null;\n\n // Detect viewport-filling content (slides using vh-based sizing).\n // Such content cannot be auto-sized because 100vh = iframe viewport\n // height, creating an infinite feedback loop.\n const isViewportFilling =\n fc &&\n /\\b(min-)?h-(screen|dvh|svh|lvh)\\b/.test(fc.className || \"\");\n\n if (!isViewportFilling && sc) {\n // Normal content: sandbox-container has no height:100% in content\n // mode (SandboxApp sets it to undefined), so its scrollHeight\n // reflects the true content height, unaffected by iframe viewport.\n const h = sc.scrollHeight;\n setContentHeight((prev) => {\n const next = Math.max(200, Math.ceil(h));\n return prev === next ? prev : next;\n });\n }\n // For viewport-filling content: contentHeight stays at 0,\n // so contentModeStyle will use the 16:9 minimum.\n\n setTimeout(() => {\n isMeasuringContentRef.current = false;\n }, 50);\n return;\n }\n\n // Blackboard mode: use existing measurement logic\n const bodyScrollH = doc.body.scrollHeight;\n const htmlScrollH = doc.documentElement?.scrollHeight || 0;\n const rootScrollH = rootEl?.scrollHeight || 0;\n const measuredHeight = Math.max(bodyScrollH, htmlScrollH, rootScrollH);\n\n if (shouldMeasureDynamicHeight) {\n const explicitHeight = resolveExplicitHeight();\n const nextHeight = Math.max(\n 200,\n explicitHeight ?? Math.ceil(measuredHeight)\n );\n setHeight((prevHeight) =>\n prevHeight === nextHeight ? prevHeight : nextHeight\n );\n }\n };\n const scheduleHeightUpdate = () => {\n requestAnimationFrame(() => {\n if (isDestroyed) return;\n updateHeight();\n });\n };\n updateHeightRef.current = scheduleHeightUpdate;\n\n updateHeight();\n scheduleHeightUpdate();\n\n if (shouldInjectSandboxVendor) {\n // Inject Tailwind/DaisyUI/GSAP before rendering sandbox content to avoid FOUC.\n loadBlackboardVendor()\n .then((inject) => {\n if (isDestroyed) return;\n inject(doc);\n requestAnimationFrame(() => {\n if (isDestroyed) return;\n scheduleHeightUpdate();\n });\n })\n .catch(() => {\n if (isDestroyed) return;\n scheduleHeightUpdate();\n });\n }\n\n const resizeObserver = new ResizeObserver(() => updateHeight());\n resizeObserver.observe(doc.body);\n if (rootEl) {\n resizeObserver.observe(rootEl);\n }\n\n // MutationObserver: detect DOM changes that ResizeObserver might miss\n // (e.g. content injected by scripts, images loading, dynamic rendering)\n const mutationObserver = new MutationObserver(() => {\n scheduleHeightUpdate();\n });\n mutationObserver.observe(doc.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\"style\", \"class\"],\n });\n\n return () => {\n isDestroyed = true;\n resizeObserver.disconnect();\n mutationObserver.disconnect();\n if (shouldBridgeSandboxInteraction) {\n doc.removeEventListener(\"pointerdown\", handleSandboxPointerDown, true);\n doc.removeEventListener(\"mousedown\", handleSandboxMouseDown, true);\n doc.removeEventListener(\"touchstart\", handleSandboxTouchStart, true);\n }\n // Defer unmount to avoid React warning when parent is mid-render\n setTimeout(() => {\n root.unmount();\n rootRef.current = null;\n updateHeightRef.current = () => {};\n }, 0);\n };\n }, []);\n\n useEffect(() => {\n const onFullscreenChange = () => {\n setIsFullscreen(Boolean(document.fullscreenElement));\n };\n document.addEventListener(\"fullscreenchange\", onFullscreenChange);\n return () =>\n document.removeEventListener(\"fullscreenchange\", onFullscreenChange);\n }, []);\n\n // Track container width for computing min-height in content mode\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n const ro = new ResizeObserver((entries) => {\n setContainerWidth(entries[0]?.contentRect.width ?? el.clientWidth);\n });\n ro.observe(el);\n setContainerWidth(el.clientWidth);\n return () => ro.disconnect();\n }, []);\n\n // Content mode: min 16:9 aspect ratio, grow to fit content (no scrollbar)\n const contentModeStyle = useMemo<React.CSSProperties | undefined>(() => {\n if (isBlackboardMode || containerWidth === 0 || isFullscreen)\n return undefined;\n const minH = Math.round((containerWidth * 9) / 16);\n const h = Math.max(minH, contentHeight);\n return { height: h };\n }, [isBlackboardMode, containerWidth, contentHeight, isFullscreen]);\n\n const toggleFullscreen = () => {\n const target = containerRef.current || iframeRef.current;\n if (!target) return;\n if (document.fullscreenElement) {\n document.exitFullscreen().catch(() => {});\n return;\n }\n if (target.requestFullscreen) {\n target.requestFullscreen().catch(() => {});\n }\n };\n\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n\n root.render(\n <SandboxApp\n html={renderHtmlContent}\n styleLoadingText={styleLoadingText}\n scriptLoadingText={scriptLoadingText}\n resetToken={resetToken}\n hasRootVhHeight={hasRootVhHeight}\n mode={mode}\n stretchRootHeight={shouldStretchRootHeight}\n />\n );\n\n // Schedule multiple measurements to catch async content (scripts, images, styles).\n initialPaintFrameRef.current = window.requestAnimationFrame(() => {\n updateHeightRef.current?.();\n initialPaintFrameRef.current = null;\n });\n const t1 = setTimeout(() => updateHeightRef.current?.(), 100);\n const t2 = setTimeout(() => updateHeightRef.current?.(), 500);\n return () => {\n clearTimeout(t1);\n clearTimeout(t2);\n };\n }, [\n renderHtmlContent,\n styleLoadingText,\n scriptLoadingText,\n resetToken,\n mode,\n ]);\n const containerClassName = [\n \"w-full relative content-render-iframe-sandbox\",\n isBlackboardMode\n ? \"h-full overflow-auto flex flex-col\"\n : contentModeStyle\n ? \"overflow-hidden flex items-center justify-center\"\n : \"aspect-[16/9] overflow-hidden flex items-center justify-center\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div\n ref={containerRef}\n data-root-vh={hasRootVhHeight ? \"true\" : \"false\"}\n className={containerClassName}\n style={\n sandboxViewportHeight\n ? {\n height: sandboxViewportHeight,\n minHeight: sandboxViewportHeight,\n }\n : contentModeStyle\n }\n >\n {!hideFullScreen && (\n <button\n type=\"button\"\n onClick={toggleFullscreen}\n className={\n \"absolute top-2 right-2 z-50 p-1.5 bg-black/75 text-white rounded-md cursor-pointer\"\n }\n >\n {isFullscreen ? \"退出全屏\" : fullScreenButtonText || \"全屏浏览\"}\n </button>\n )}\n {mode === \"blackboard\" && type === \"markdown\" ? (\n <div\n onMouseDown={() => emitSandboxInteraction(\"mousedown\")}\n onPointerDown={() => emitSandboxInteraction(\"pointerdown\")}\n onTouchStart={() => emitSandboxInteraction(\"touchstart\")}\n >\n <ContentRender content={content} />\n </div>\n ) : (\n <iframe\n ref={iframeRef}\n sandbox=\"allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox\"\n allow=\"fullscreen\"\n allowFullScreen\n className={[className, \"w-full h-full mx-auto my-auto block\"]\n .filter(Boolean)\n .join(\" \")}\n style={{\n height: sandboxViewportHeight ?? \"100%\",\n minHeight: sandboxViewportHeight,\n margin: \"auto\",\n }}\n />\n )}\n </div>\n );\n};\n\nexport default IframeSandbox;\n"],"names":["blackboardVendorPromise","loadBlackboardVendor","m","COMPLETE_IMAGE_TAG_PATTERN","POST_IMAGE_STREAM_DEBOUNCE_MS","SANDBOX_INTERACTION_THROTTLE_MS","replaceRootScreenHeightToken","className","token","segments","replaceRootScreenHeightWithFullClass","html","enabled","match","tagStart","attrs","classMatch","nextClassName","IframeSandbox","content","type","styleLoadingText","scriptLoadingText","fullScreenButtonText","hideFullScreen","mode","replaceRootScreenHeightWithFull","containerRef","useRef","iframeRef","rootRef","updateHeightRef","height","setHeight","useState","contentHeight","setContentHeight","containerWidth","setContainerWidth","isMeasuringContentRef","lastSandboxInteractionTimeRef","resetToken","setResetToken","isFullscreen","setIsFullscreen","shouldInjectSandboxVendor","isBlackboardMode","shouldMeasureDynamicHeight","shouldProcessRootScreenHeight","prevHtmlRef","htmlContent","React","normalizedHtmlContent","originalRootHeightMeta","inspectViewportHeightFromHtmlRootString","EMPTY_ROOT_HEIGHT_META","shouldStretchRootHeight","renderHtmlContent","setRenderHtmlContent","prevIncomingHtmlRef","pendingHtmlRef","deferRenderTimerRef","initialPaintFrameRef","renderViewportHeightCssRef","emitSandboxInteraction","useCallback","eventType","now","SANDBOX_INTERACTION_MESSAGE_SOURCE","SANDBOX_INTERACTION_MESSAGE_TYPE","clearDeferredRenderTimer","clearInitialPaintFrames","useEffect","prevIncomingHtml","isAppendOnlyStream","containsCompleteImage","rootViewportHeightCss","hasRootVhHeight","sandboxViewportHeight","prev","iframe","doc","shouldBridgeSandboxInteraction","handleSandboxPointerDown","handleSandboxMouseDown","handleSandboxTouchStart","rootEl","root","createRoot","isDestroyed","getHeightInspectionNode","node","getSingleChildElement","childElements","resolveExplicitHeight","parentViewportHeight","precomputedViewportHeightCss","parsed","parseExplicitHeight","container","containerChildren","rootContentElement","runtimeViewportHeightCss","inspectViewportHeightFromNodeChain","runtimeViewportHeight","explicitPixelHeight","resolveExplicitHeightFromNodeChain","updateHeight","sc","fc","h","next","bodyScrollH","htmlScrollH","rootScrollH","measuredHeight","explicitHeight","nextHeight","prevHeight","scheduleHeightUpdate","inject","resizeObserver","mutationObserver","onFullscreenChange","el","ro","entries","contentModeStyle","useMemo","minH","toggleFullscreen","target","jsx","SandboxApp","t1","t2","containerClassName","jsxs","ContentRender"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"IframeSandbox.es.js","sources":["../../../src/components/ContentRender/IframeSandbox.tsx"],"sourcesContent":["import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { createRoot, Root } from \"react-dom/client\";\nimport SandboxApp from \"./SandboxApp\";\nimport ContentRender from \"./ContentRender\";\nimport {\n EMPTY_ROOT_HEIGHT_META,\n inspectViewportHeightFromHtmlRootString,\n inspectViewportHeightFromNodeChain,\n parseExplicitHeight,\n resolveExplicitHeightFromNodeChain,\n} from \"./utils/iframe-viewport-height\";\nimport {\n SANDBOX_INTERACTION_MESSAGE_SOURCE,\n SANDBOX_INTERACTION_MESSAGE_TYPE,\n} from \"../../lib/sandboxInteraction\";\n\ntype InjectBlackboardLibraries =\n typeof import(\"./blackboard-vendor\").injectBlackboardLibraries;\n\n// Cache the sandbox vendor loader so every iframe reuses the same preload request.\nlet blackboardVendorPromise: Promise<InjectBlackboardLibraries> | null = null;\n\nconst loadBlackboardVendor = () => {\n if (!blackboardVendorPromise) {\n blackboardVendorPromise = import(\"./blackboard-vendor\").then(\n (m) => m.injectBlackboardLibraries\n );\n }\n\n return blackboardVendorPromise;\n};\n\nconst COMPLETE_IMAGE_TAG_PATTERN = /<img\\b[^>]*>/i;\nconst POST_IMAGE_STREAM_DEBOUNCE_MS = 180;\nconst SANDBOX_INTERACTION_THROTTLE_MS = 240;\n\nexport interface IframeSandboxProps {\n content: string;\n className?: string;\n loadingText?: string;\n styleLoadingText?: string;\n scriptLoadingText?: string;\n fullScreenButtonText?: string;\n hideFullScreen?: boolean;\n mode?: \"content\" | \"blackboard\";\n type: \"sandbox\" | \"markdown\";\n replaceRootScreenHeightWithFull?: boolean;\n}\n\nconst replaceRootScreenHeightToken = (className: string) =>\n className\n .split(/\\s+/)\n .filter(Boolean)\n .map((token) => {\n const segments = token.split(\":\");\n if (\n segments[segments.length - 1] !== \"h-screen\" &&\n segments[segments.length - 1] !== \"min-h-screen\"\n ) {\n return token;\n }\n segments[segments.length - 1] = \"h-full\";\n return segments.join(\":\");\n })\n .join(\" \");\n\nconst replaceRootScreenHeightWithFullClass = (\n html: string,\n enabled: boolean\n) => {\n if (!enabled || !html.trim()) {\n return html;\n }\n\n return html.replace(\n /^(\\s*<[a-zA-Z][\\w:-]*)(\\s[^>]*?)?>/,\n (match, tagStart: string, attrs = \"\") => {\n const classMatch = attrs.match(/\\bclass\\s*=\\s*([\"'])([^\"']*)\\1/i);\n\n if (!classMatch) {\n return match;\n }\n\n const nextClassName = replaceRootScreenHeightToken(classMatch[2]);\n\n if (nextClassName === classMatch[2]) {\n return match;\n }\n\n return `${tagStart}${attrs.replace(\n classMatch[0],\n `class=${classMatch[1]}${nextClassName}${classMatch[1]}`\n )}>`;\n }\n );\n};\n\nconst IframeSandbox: React.FC<IframeSandboxProps> = ({\n content,\n type,\n className,\n styleLoadingText,\n scriptLoadingText,\n fullScreenButtonText,\n hideFullScreen = false,\n mode = \"content\",\n replaceRootScreenHeightWithFull = false,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const rootRef = useRef<Root | null>(null);\n const updateHeightRef = useRef<() => void>(() => {});\n const [height, setHeight] = useState(480);\n const [contentHeight, setContentHeight] = useState(0);\n const [containerWidth, setContainerWidth] = useState(0);\n const isMeasuringContentRef = useRef(false);\n const lastSandboxInteractionTimeRef = useRef(0);\n const [resetToken, setResetToken] = useState(0);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const shouldInjectSandboxVendor = type === \"sandbox\";\n\n const isBlackboardMode = mode === \"blackboard\";\n const shouldMeasureDynamicHeight = isBlackboardMode && type === \"sandbox\";\n const shouldProcessRootScreenHeight =\n shouldMeasureDynamicHeight && replaceRootScreenHeightWithFull;\n const prevHtmlRef = useRef<string>(\"\");\n const htmlContent = React.useMemo(\n () => (type === \"sandbox\" ? content : \"\"),\n [content, type]\n );\n const normalizedHtmlContent = React.useMemo(\n () =>\n replaceRootScreenHeightWithFullClass(\n htmlContent,\n shouldProcessRootScreenHeight\n ),\n [htmlContent, shouldProcessRootScreenHeight]\n );\n const originalRootHeightMeta = React.useMemo(\n () =>\n shouldProcessRootScreenHeight\n ? inspectViewportHeightFromHtmlRootString(htmlContent)\n : EMPTY_ROOT_HEIGHT_META,\n [htmlContent, shouldProcessRootScreenHeight]\n );\n const shouldStretchRootHeight = React.useMemo(\n () =>\n shouldProcessRootScreenHeight &&\n originalRootHeightMeta.hasFullViewportHeight,\n [\n originalRootHeightMeta.hasFullViewportHeight,\n shouldProcessRootScreenHeight,\n ]\n );\n const [renderHtmlContent, setRenderHtmlContent] = useState(\n normalizedHtmlContent\n );\n const prevIncomingHtmlRef = useRef(normalizedHtmlContent);\n const pendingHtmlRef = useRef(normalizedHtmlContent);\n const deferRenderTimerRef = useRef<number | null>(null);\n const initialPaintFrameRef = useRef<number | null>(null);\n const renderViewportHeightCssRef = useRef<string | null>(null);\n\n const emitSandboxInteraction = useCallback((eventType: string) => {\n if (typeof window === \"undefined\") {\n return;\n }\n const now = Date.now();\n if (\n now - lastSandboxInteractionTimeRef.current <\n SANDBOX_INTERACTION_THROTTLE_MS\n ) {\n return;\n }\n lastSandboxInteractionTimeRef.current = now;\n window.postMessage(\n {\n source: SANDBOX_INTERACTION_MESSAGE_SOURCE,\n type: SANDBOX_INTERACTION_MESSAGE_TYPE,\n eventType,\n },\n window.location.origin\n );\n }, []);\n\n const clearDeferredRenderTimer = () => {\n if (deferRenderTimerRef.current === null) return;\n window.clearTimeout(deferRenderTimerRef.current);\n deferRenderTimerRef.current = null;\n };\n\n const clearInitialPaintFrames = () => {\n if (initialPaintFrameRef.current !== null) {\n window.cancelAnimationFrame(initialPaintFrameRef.current);\n initialPaintFrameRef.current = null;\n }\n };\n\n useEffect(\n () => () => {\n clearDeferredRenderTimer();\n clearInitialPaintFrames();\n },\n []\n );\n\n useEffect(() => {\n const prevIncomingHtml = prevIncomingHtmlRef.current;\n prevIncomingHtmlRef.current = normalizedHtmlContent;\n\n const isAppendOnlyStream =\n !!prevIncomingHtml &&\n normalizedHtmlContent.length > prevIncomingHtml.length &&\n normalizedHtmlContent.startsWith(prevIncomingHtml);\n const containsCompleteImage = COMPLETE_IMAGE_TAG_PATTERN.test(\n normalizedHtmlContent\n );\n const shouldDeferRender = isAppendOnlyStream && containsCompleteImage;\n\n if (!shouldDeferRender) {\n clearDeferredRenderTimer();\n pendingHtmlRef.current = normalizedHtmlContent;\n setRenderHtmlContent(normalizedHtmlContent);\n return;\n }\n\n pendingHtmlRef.current = normalizedHtmlContent;\n clearDeferredRenderTimer();\n deferRenderTimerRef.current = window.setTimeout(() => {\n setRenderHtmlContent(pendingHtmlRef.current);\n deferRenderTimerRef.current = null;\n }, POST_IMAGE_STREAM_DEBOUNCE_MS);\n }, [normalizedHtmlContent]);\n\n const rootViewportHeightCss = React.useMemo(() => {\n if (!shouldMeasureDynamicHeight) {\n return null;\n }\n\n return inspectViewportHeightFromHtmlRootString(renderHtmlContent)\n .viewportHeightCss;\n }, [renderHtmlContent, shouldMeasureDynamicHeight]);\n\n useEffect(() => {\n renderViewportHeightCssRef.current = rootViewportHeightCss;\n }, [rootViewportHeightCss]);\n\n const hasRootVhHeight = Boolean(rootViewportHeightCss);\n const sandboxViewportHeight =\n isBlackboardMode && type === \"sandbox\"\n ? shouldStretchRootHeight\n ? \"100%\"\n : (rootViewportHeightCss ?? `${height}px`)\n : undefined;\n useEffect(() => {\n if (mode !== \"blackboard\") {\n prevHtmlRef.current = normalizedHtmlContent;\n return;\n }\n const prev = prevHtmlRef.current;\n const isContinuation = prev && normalizedHtmlContent.startsWith(prev);\n if (!isContinuation && prev) {\n setResetToken((token) => token + 1);\n }\n prevHtmlRef.current = normalizedHtmlContent;\n }, [mode, normalizedHtmlContent]);\n\n useEffect(() => {\n const iframe = iframeRef.current;\n if (!iframe) return undefined;\n\n const doc = iframe.contentDocument;\n if (!doc) return undefined;\n\n doc.open();\n doc.write(`<!DOCTYPE html>\n<html${mode === \"blackboard\" ? ' style=\"height: 100%;\"' : \"\"}>\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <style>\n :root { color-scheme: light; }\n html, body, #root { width: 100%; }\n ${mode === \"blackboard\" ? \"html, body, #root { height: 100%; }\" : \"\"}\n html, body { margin: 0; padding: 0; overflow: ${mode === \"blackboard\" ? \"auto\" : \"hidden\"}; }\n *, *::before, *::after { box-sizing: border-box; }\n ${mode !== \"blackboard\" ? `\n .h-screen { height: auto !important; }\n .min-h-screen { min-height: auto !important; }\n .h-dvh, .h-svh, .h-lvh { height: auto !important; }\n .min-h-dvh, .min-h-svh, .min-h-lvh { min-height: auto !important; }\n ` : \"\"}\n </style>\n </head>\n <body>\n <div id=\"root\"></div>\n </body>\n</html>`);\n doc.close();\n\n // Force iframe theme to stay in light mode regardless of host OS preference.\n doc.documentElement.setAttribute(\"data-theme\", \"light\");\n doc.documentElement.style.colorScheme = \"light\";\n doc.body?.style.setProperty(\"color-scheme\", \"light\");\n\n const shouldBridgeSandboxInteraction =\n isBlackboardMode && type === \"sandbox\";\n const handleSandboxPointerDown = () =>\n emitSandboxInteraction(\"pointerdown\");\n const handleSandboxMouseDown = () => emitSandboxInteraction(\"mousedown\");\n const handleSandboxTouchStart = () => emitSandboxInteraction(\"touchstart\");\n\n if (shouldBridgeSandboxInteraction) {\n doc.addEventListener(\"pointerdown\", handleSandboxPointerDown, true);\n doc.addEventListener(\"mousedown\", handleSandboxMouseDown, true);\n doc.addEventListener(\"touchstart\", handleSandboxTouchStart, true);\n }\n\n const rootEl = doc.getElementById(\"root\");\n if (!rootEl) return undefined;\n\n const root = createRoot(rootEl);\n rootRef.current = root;\n let isDestroyed = false;\n const getHeightInspectionNode = (node: HTMLElement) => ({\n heightAttrValue: node.getAttribute(\"height\"),\n styleAttrValue: node.getAttribute(\"style\"),\n classAttrValue: node.getAttribute(\"class\"),\n });\n const getSingleChildElement = (node: HTMLElement) => {\n const childElements = Array.from(node.children) as HTMLElement[];\n\n return childElements.length === 1 ? childElements[0] : null;\n };\n\n const resolveExplicitHeight = () => {\n if (!shouldMeasureDynamicHeight) return null;\n if (!iframeRef.current || !doc.body) return null;\n const parentViewportHeight =\n iframeRef.current.ownerDocument?.documentElement?.clientHeight ||\n window.innerHeight;\n // Reuse parsed height metadata from the current html snapshot first to\n // avoid re-inspecting the same DOM chain on every height tick.\n const precomputedViewportHeightCss = renderViewportHeightCssRef.current;\n const parsed = precomputedViewportHeightCss\n ? parseExplicitHeight(\n precomputedViewportHeightCss,\n parentViewportHeight\n )\n : null;\n\n if (parsed !== null) {\n return Math.ceil(parsed);\n }\n\n const wrapper = doc.body.querySelector(\n \".sandbox-wrapper\"\n ) as HTMLElement | null;\n const container = wrapper?.firstElementChild as HTMLElement | null;\n if (!container) return null;\n const containerChildren = Array.from(container.children) as HTMLElement[];\n const rootContentElement =\n containerChildren.length === 1 ? containerChildren[0] : null;\n const runtimeHeightMeta = inspectViewportHeightFromNodeChain(\n rootContentElement,\n {\n getNode: getHeightInspectionNode,\n getSingleChild: getSingleChildElement,\n }\n );\n const runtimeViewportHeightCss = runtimeHeightMeta.viewportHeightCss;\n\n if (runtimeViewportHeightCss) {\n const runtimeViewportHeight = parseExplicitHeight(\n runtimeViewportHeightCss,\n parentViewportHeight\n );\n\n if (runtimeViewportHeight !== null) {\n return Math.ceil(runtimeViewportHeight);\n }\n }\n\n const explicitPixelHeight = resolveExplicitHeightFromNodeChain(\n rootContentElement,\n parentViewportHeight,\n {\n getNode: getHeightInspectionNode,\n getSingleChild: getSingleChildElement,\n }\n );\n\n return explicitPixelHeight !== null\n ? Math.ceil(explicitPixelHeight)\n : null;\n };\n\n const updateHeight = () => {\n if (!iframeRef.current || !doc.body) return;\n\n if (!isBlackboardMode) {\n // Guard: prevent re-entrant measurement from ResizeObserver /\n // MutationObserver callbacks triggered by our own height changes.\n if (isMeasuringContentRef.current) return;\n isMeasuringContentRef.current = true;\n\n // Content mode height measurement strategy:\n // The iframe CSS overrides .h-screen/.min-h-screen to height:auto,\n // removing viewport-height constraints. But content may still use\n // vmin units (font-size, padding, gap) which depend on\n // min(width, height). To get a stable measurement, temporarily\n // set iframe height >= containerWidth so vmin = width/100 (constant).\n const iframe = iframeRef.current;\n const cw = containerRef.current?.clientWidth || 0;\n const prevH = iframe.style.height;\n\n if (cw > 0) {\n iframe.style.height = cw + \"px\";\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n doc.body.offsetHeight; // force layout\n\n const measuredH = doc.body.scrollHeight;\n\n // Restore iframe to let React control it via contentModeStyle\n iframe.style.height = prevH;\n\n setContentHeight((prev) => {\n const next = Math.max(200, Math.ceil(measuredH));\n return prev === next ? prev : next;\n });\n }\n\n setTimeout(() => {\n isMeasuringContentRef.current = false;\n }, 50);\n return;\n }\n\n // Blackboard mode: use existing measurement logic\n const bodyScrollH = doc.body.scrollHeight;\n const htmlScrollH = doc.documentElement?.scrollHeight || 0;\n const rootScrollH = rootEl?.scrollHeight || 0;\n const measuredHeight = Math.max(bodyScrollH, htmlScrollH, rootScrollH);\n\n if (shouldMeasureDynamicHeight) {\n const explicitHeight = resolveExplicitHeight();\n const nextHeight = Math.max(\n 200,\n explicitHeight ?? Math.ceil(measuredHeight)\n );\n setHeight((prevHeight) =>\n prevHeight === nextHeight ? prevHeight : nextHeight\n );\n }\n };\n const scheduleHeightUpdate = () => {\n requestAnimationFrame(() => {\n if (isDestroyed) return;\n updateHeight();\n });\n };\n updateHeightRef.current = scheduleHeightUpdate;\n\n updateHeight();\n scheduleHeightUpdate();\n\n if (shouldInjectSandboxVendor) {\n // Inject Tailwind/DaisyUI/GSAP before rendering sandbox content to avoid FOUC.\n loadBlackboardVendor()\n .then((inject) => {\n if (isDestroyed) return;\n inject(doc);\n requestAnimationFrame(() => {\n if (isDestroyed) return;\n scheduleHeightUpdate();\n });\n })\n .catch(() => {\n if (isDestroyed) return;\n scheduleHeightUpdate();\n });\n }\n\n const resizeObserver = new ResizeObserver(() => updateHeight());\n resizeObserver.observe(doc.body);\n if (rootEl) {\n resizeObserver.observe(rootEl);\n }\n\n // MutationObserver: detect DOM changes that ResizeObserver might miss\n // (e.g. content injected by scripts, images loading, dynamic rendering)\n const mutationObserver = new MutationObserver(() => {\n scheduleHeightUpdate();\n });\n mutationObserver.observe(doc.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\"style\", \"class\"],\n });\n\n return () => {\n isDestroyed = true;\n resizeObserver.disconnect();\n mutationObserver.disconnect();\n if (shouldBridgeSandboxInteraction) {\n doc.removeEventListener(\"pointerdown\", handleSandboxPointerDown, true);\n doc.removeEventListener(\"mousedown\", handleSandboxMouseDown, true);\n doc.removeEventListener(\"touchstart\", handleSandboxTouchStart, true);\n }\n // Defer unmount to avoid React warning when parent is mid-render\n setTimeout(() => {\n root.unmount();\n rootRef.current = null;\n updateHeightRef.current = () => {};\n }, 0);\n };\n }, []);\n\n useEffect(() => {\n const onFullscreenChange = () => {\n setIsFullscreen(Boolean(document.fullscreenElement));\n };\n document.addEventListener(\"fullscreenchange\", onFullscreenChange);\n return () =>\n document.removeEventListener(\"fullscreenchange\", onFullscreenChange);\n }, []);\n\n // Track container width for computing min-height in content mode\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n const ro = new ResizeObserver((entries) => {\n setContainerWidth(entries[0]?.contentRect.width ?? el.clientWidth);\n });\n ro.observe(el);\n setContainerWidth(el.clientWidth);\n return () => ro.disconnect();\n }, []);\n\n // Content mode: min 16:9 aspect ratio, grow to fit content (no scrollbar)\n const contentModeStyle = useMemo<React.CSSProperties | undefined>(() => {\n if (isBlackboardMode || containerWidth === 0 || isFullscreen)\n return undefined;\n const minH = Math.round((containerWidth * 9) / 16);\n const h = Math.max(minH, contentHeight);\n return { height: h };\n }, [isBlackboardMode, containerWidth, contentHeight, isFullscreen]);\n\n const toggleFullscreen = () => {\n const target = containerRef.current || iframeRef.current;\n if (!target) return;\n if (document.fullscreenElement) {\n document.exitFullscreen().catch(() => {});\n return;\n }\n if (target.requestFullscreen) {\n target.requestFullscreen().catch(() => {});\n }\n };\n\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n\n root.render(\n <SandboxApp\n html={renderHtmlContent}\n styleLoadingText={styleLoadingText}\n scriptLoadingText={scriptLoadingText}\n resetToken={resetToken}\n hasRootVhHeight={hasRootVhHeight}\n mode={mode}\n stretchRootHeight={shouldStretchRootHeight}\n />\n );\n\n // Schedule multiple measurements to catch async content (scripts, images, styles).\n initialPaintFrameRef.current = window.requestAnimationFrame(() => {\n updateHeightRef.current?.();\n initialPaintFrameRef.current = null;\n });\n const t1 = setTimeout(() => updateHeightRef.current?.(), 100);\n const t2 = setTimeout(() => updateHeightRef.current?.(), 500);\n return () => {\n clearTimeout(t1);\n clearTimeout(t2);\n };\n }, [\n renderHtmlContent,\n styleLoadingText,\n scriptLoadingText,\n resetToken,\n mode,\n ]);\n const containerClassName = [\n \"w-full relative content-render-iframe-sandbox\",\n isBlackboardMode\n ? \"h-full overflow-auto flex flex-col\"\n : contentModeStyle\n ? \"overflow-hidden flex items-center justify-center\"\n : \"aspect-[16/9] overflow-hidden flex items-center justify-center\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div\n ref={containerRef}\n data-root-vh={hasRootVhHeight ? \"true\" : \"false\"}\n className={containerClassName}\n style={\n sandboxViewportHeight\n ? {\n height: sandboxViewportHeight,\n minHeight: sandboxViewportHeight,\n }\n : contentModeStyle\n }\n >\n {!hideFullScreen && (\n <button\n type=\"button\"\n onClick={toggleFullscreen}\n className={\n \"absolute top-2 right-2 z-50 p-1.5 bg-black/75 text-white rounded-md cursor-pointer\"\n }\n >\n {isFullscreen ? \"退出全屏\" : fullScreenButtonText || \"全屏浏览\"}\n </button>\n )}\n {mode === \"blackboard\" && type === \"markdown\" ? (\n <div\n onMouseDown={() => emitSandboxInteraction(\"mousedown\")}\n onPointerDown={() => emitSandboxInteraction(\"pointerdown\")}\n onTouchStart={() => emitSandboxInteraction(\"touchstart\")}\n >\n <ContentRender content={content} />\n </div>\n ) : (\n <iframe\n ref={iframeRef}\n sandbox=\"allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox\"\n allow=\"fullscreen\"\n allowFullScreen\n className={[className, \"w-full h-full mx-auto my-auto block\"]\n .filter(Boolean)\n .join(\" \")}\n style={{\n height: sandboxViewportHeight ?? \"100%\",\n minHeight: sandboxViewportHeight,\n margin: \"auto\",\n }}\n />\n )}\n </div>\n );\n};\n\nexport default IframeSandbox;\n"],"names":["blackboardVendorPromise","loadBlackboardVendor","m","COMPLETE_IMAGE_TAG_PATTERN","POST_IMAGE_STREAM_DEBOUNCE_MS","SANDBOX_INTERACTION_THROTTLE_MS","replaceRootScreenHeightToken","className","token","segments","replaceRootScreenHeightWithFullClass","html","enabled","match","tagStart","attrs","classMatch","nextClassName","IframeSandbox","content","type","styleLoadingText","scriptLoadingText","fullScreenButtonText","hideFullScreen","mode","replaceRootScreenHeightWithFull","containerRef","useRef","iframeRef","rootRef","updateHeightRef","height","setHeight","useState","contentHeight","setContentHeight","containerWidth","setContainerWidth","isMeasuringContentRef","lastSandboxInteractionTimeRef","resetToken","setResetToken","isFullscreen","setIsFullscreen","shouldInjectSandboxVendor","isBlackboardMode","shouldMeasureDynamicHeight","shouldProcessRootScreenHeight","prevHtmlRef","htmlContent","React","normalizedHtmlContent","originalRootHeightMeta","inspectViewportHeightFromHtmlRootString","EMPTY_ROOT_HEIGHT_META","shouldStretchRootHeight","renderHtmlContent","setRenderHtmlContent","prevIncomingHtmlRef","pendingHtmlRef","deferRenderTimerRef","initialPaintFrameRef","renderViewportHeightCssRef","emitSandboxInteraction","useCallback","eventType","now","SANDBOX_INTERACTION_MESSAGE_SOURCE","SANDBOX_INTERACTION_MESSAGE_TYPE","clearDeferredRenderTimer","clearInitialPaintFrames","useEffect","prevIncomingHtml","isAppendOnlyStream","containsCompleteImage","rootViewportHeightCss","hasRootVhHeight","sandboxViewportHeight","prev","iframe","doc","shouldBridgeSandboxInteraction","handleSandboxPointerDown","handleSandboxMouseDown","handleSandboxTouchStart","rootEl","root","createRoot","isDestroyed","getHeightInspectionNode","node","getSingleChildElement","childElements","resolveExplicitHeight","parentViewportHeight","precomputedViewportHeightCss","parsed","parseExplicitHeight","container","containerChildren","rootContentElement","runtimeViewportHeightCss","inspectViewportHeightFromNodeChain","runtimeViewportHeight","explicitPixelHeight","resolveExplicitHeightFromNodeChain","updateHeight","cw","prevH","measuredH","next","bodyScrollH","htmlScrollH","rootScrollH","measuredHeight","explicitHeight","nextHeight","prevHeight","scheduleHeightUpdate","inject","resizeObserver","mutationObserver","onFullscreenChange","el","ro","entries","contentModeStyle","useMemo","minH","toggleFullscreen","target","jsx","SandboxApp","t1","t2","containerClassName","jsxs","ContentRender"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("../../../../_virtual/index.
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("../../../../_virtual/index.cjs10.js"),v=require("./constants.cjs.js");var d;function x(){if(d)return c.__exports;d=1,Object.defineProperty(c.__exports,"__esModule",{value:!0}),c.__exports.sanitizeUrl=void 0;var e=v.__require();function m(r){return e.relativeFirstCharacters.indexOf(r[0])>-1}function p(r){var i=r.replace(e.ctrlCharactersRegex,"");return i.replace(e.htmlEntitiesRegex,function(t,a){return String.fromCharCode(a)})}function R(r){return URL.canParse(r)}function l(r){try{return decodeURIComponent(r)}catch{return r}}function f(r){if(!r)return e.BLANK_URL;var i,t=l(r.trim());do t=p(t).replace(e.htmlCtrlEntityRegex,"").replace(e.ctrlCharactersRegex,"").replace(e.whitespaceEscapeCharsRegex,"").trim(),t=l(t),i=t.match(e.ctrlCharactersRegex)||t.match(e.htmlEntitiesRegex)||t.match(e.htmlCtrlEntityRegex)||t.match(e.whitespaceEscapeCharsRegex);while(i&&i.length>0);var a=t;if(!a)return e.BLANK_URL;if(m(a))return a;var u=a.trimStart(),h=u.match(e.urlSchemeRegex);if(!h)return a;var n=h[0].toLowerCase().trim();if(e.invalidProtocolRegex.test(n))return e.BLANK_URL;var s=u.replace(/\\/g,"/");if(n==="mailto:"||n.includes("://"))return s;if(n==="http:"||n==="https:"){if(!R(s))return e.BLANK_URL;var o=new URL(s);return o.protocol=o.protocol.toLowerCase(),o.hostname=o.hostname.toLowerCase(),o.toString()}return s}return c.__exports.sanitizeUrl=f,c.__exports}exports.__require=x;
|
|
2
2
|
//# sourceMappingURL=index.cjs.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R=require("../../@babel/runtime/helpers/esm/typeof.cjs.js"),a=require("react"),i=require("../../../_virtual/index.
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R=require("../../@babel/runtime/helpers/esm/typeof.cjs.js"),a=require("react"),i=require("../../../_virtual/index.cjs11.js"),v=require("./hooks/useMemo.cjs.js"),g=require("./React/isFragment.cjs.js");var y=Number(a.version.split(".")[0]),s=function(e,r){typeof e=="function"?e(r):R.default(e)==="object"&&e&&"current"in e&&(e.current=r)},p=function(){for(var e=arguments.length,r=new Array(e),t=0;t<e;t++)r[t]=arguments[t];var u=r.filter(Boolean);return u.length<=1?u[0]:function(o){r.forEach(function(n){s(n,o)})}},m=function(){for(var e=arguments.length,r=new Array(e),t=0;t<e;t++)r[t]=arguments[t];return v.default(function(){return p.apply(void 0,r)},r,function(u,o){return u.length!==o.length||u.every(function(n,l){return n!==o[l]})})},d=function(e){var r,t;if(!e)return!1;if(c(e)&&y>=19)return!0;var u=i.reactIsExports.isMemo(e)?e.type.type:e.type;return!(typeof u=="function"&&!((r=u.prototype)!==null&&r!==void 0&&r.render)&&u.$$typeof!==i.reactIsExports.ForwardRef||typeof e=="function"&&!((t=e.prototype)!==null&&t!==void 0&&t.render)&&e.$$typeof!==i.reactIsExports.ForwardRef)};function c(f){return a.isValidElement(f)&&!g.default(f)}var E=function(e){if(e&&c(e)){var r=e;return r.props.propertyIsEnumerable("ref")?r.props.ref:r.ref}return null};exports.composeRef=p;exports.fillRef=s;exports.getNodeRef=E;exports.supportRef=d;exports.useComposeRef=m;
|
|
2
2
|
//# sourceMappingURL=ref.cjs.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import s from "../../@babel/runtime/helpers/esm/typeof.es.js";
|
|
2
2
|
import { version as c, isValidElement as l } from "react";
|
|
3
|
-
import { r as n } from "../../../_virtual/index.
|
|
3
|
+
import { r as n } from "../../../_virtual/index.es11.js";
|
|
4
4
|
import m from "./hooks/useMemo.es.js";
|
|
5
5
|
import v from "./React/isFragment.es.js";
|
|
6
6
|
var R = Number(c.split(".")[0]), y = function(r, t) {
|