markdown-flow-ui 0.1.104-alpha.3 → 0.1.104-alpha.5
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.cjs5.js +1 -1
- package/dist/_virtual/index.cjs6.js +1 -1
- package/dist/_virtual/index.cjs9.js +1 -1
- package/dist/_virtual/index.es10.js +2 -2
- package/dist/_virtual/index.es5.js +4 -4
- package/dist/_virtual/index.es6.js +4 -4
- package/dist/_virtual/index.es9.js +2 -2
- package/dist/components/ContentRender/IframeSandbox.cjs.js +8 -4
- package/dist/components/ContentRender/IframeSandbox.cjs.js.map +1 -1
- package/dist/components/ContentRender/IframeSandbox.es.js +165 -154
- 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.cjs.js.map +1 -1
- package/dist/node_modules/@braintree/sanitize-url/dist/index.es.js +1 -1
- package/dist/node_modules/classnames/index.cjs.js +1 -1
- package/dist/node_modules/classnames/index.es.js +1 -1
- package/dist/node_modules/hast-util-to-jsx-runtime/lib/index.cjs.js +1 -1
- package/dist/node_modules/hast-util-to-jsx-runtime/lib/index.es.js +1 -1
- package/dist/node_modules/style-to-object/cjs/index.cjs.js +1 -1
- package/dist/node_modules/style-to-object/cjs/index.es.js +1 -1
- package/dist/node_modules/unified/lib/index.cjs.js +1 -1
- package/dist/node_modules/unified/lib/index.es.js +1 -1
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});var e={
|
|
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.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./_commonjsHelpers.cjs.js"),
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./_commonjsHelpers.cjs.js"),t=require("../node_modules/extend/index.cjs.js");var r=t.__require();const o=e.getDefaultExportFromCjs(r);exports.default=o;
|
|
2
2
|
//# sourceMappingURL=index.cjs5.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./_commonjsHelpers.cjs.js"),
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./_commonjsHelpers.cjs.js"),r=require("../node_modules/style-to-js/cjs/index.cjs.js");var t=r.__require();const o=e.getDefaultExportFromCjs(t);exports.default=o;
|
|
2
2
|
//# sourceMappingURL=index.cjs6.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});var e={};exports.
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});var e={exports:{}};exports.__module=e;
|
|
2
2
|
//# sourceMappingURL=index.cjs9.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { getDefaultExportFromCjs as
|
|
2
|
-
import { __require as
|
|
3
|
-
var t =
|
|
4
|
-
const a = /* @__PURE__ */
|
|
1
|
+
import { getDefaultExportFromCjs as e } from "./_commonjsHelpers.es.js";
|
|
2
|
+
import { __require as r } from "../node_modules/extend/index.es.js";
|
|
3
|
+
var t = r();
|
|
4
|
+
const a = /* @__PURE__ */ e(t);
|
|
5
5
|
export {
|
|
6
6
|
a as default
|
|
7
7
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { getDefaultExportFromCjs as
|
|
2
|
-
import { __require as
|
|
3
|
-
var t =
|
|
4
|
-
const a = /* @__PURE__ */
|
|
1
|
+
import { getDefaultExportFromCjs as r } from "./_commonjsHelpers.es.js";
|
|
2
|
+
import { __require as o } from "../node_modules/style-to-js/cjs/index.es.js";
|
|
3
|
+
var t = o();
|
|
4
|
+
const a = /* @__PURE__ */ r(t);
|
|
5
5
|
export {
|
|
6
6
|
a as default
|
|
7
7
|
};
|
|
@@ -1,18 +1,22 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const
|
|
2
|
-
<html${
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const E=require("../../_virtual/jsx-runtime.cjs.js"),t=require("react"),ye=require("react-dom/client"),Te=require("./SandboxApp.cjs.js"),Ae=require("./ContentRender.cjs.js"),b=require("./utils/iframe-viewport-height.cjs.js"),be=require("../../lib/sandboxInteraction.cjs.js");let Y=null;const je=()=>(Y||(Y=Promise.resolve().then(()=>require("./blackboard-vendor.cjs.js")).then(c=>c.injectBlackboardLibraries)),Y),Fe=/<img\b[^>]*>/i,Ie=180,Ne=240,Oe=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(" "),_e=(c,s)=>!s||!c.trim()?c:c.replace(/^(\s*<[a-zA-Z][\w:-]*)(\s[^>]*?)?>/,(i,I,R="")=>{const h=R.match(/\bclass\s*=\s*(["'])([^"']*)\1/i);if(!h)return i;const N=Oe(h[2]);return N===h[2]?i:`${I}${R.replace(h[0],`class=${h[1]}${N}${h[1]}`)}>`}),Ve=({content:c,type:s,className:i,styleLoadingText:I,scriptLoadingText:R,fullScreenButtonText:h,hideFullScreen:N=!1,mode:d="content",replaceRootScreenHeightWithFull:pe=!1})=>{const k=t.useRef(null),p=t.useRef(null),P=t.useRef(null),S=t.useRef(()=>{}),[we,He]=t.useState(480),[Z,J]=t.useState(0),[q,K]=t.useState(0),Q=t.useRef(0),[ee,xe]=t.useState(0),[B,Ee]=t.useState(!1),Re=s==="sandbox",m=d==="blackboard",v=m&&s==="sandbox",w=v&&pe,L=t.useRef(""),O=t.useMemo(()=>s==="sandbox"?c:"",[c,s]),r=t.useMemo(()=>_e(O,w),[O,w]),te=t.useMemo(()=>w?b.inspectViewportHeightFromHtmlRootString(O):b.EMPTY_ROOT_HEIGHT_META,[O,w]),ne=t.useMemo(()=>w&&te.hasFullViewportHeight,[te.hasFullViewportHeight,w]),[_,re]=t.useState(r),oe=t.useRef(r),$=t.useRef(r),M=t.useRef(null),C=t.useRef(null),se=t.useRef(null),H=t.useCallback(n=>{if(typeof window>"u")return;const e=Date.now();e-Q.current<Ne||(Q.current=e,window.postMessage({source:be.SANDBOX_INTERACTION_MESSAGE_SOURCE,type:be.SANDBOX_INTERACTION_MESSAGE_TYPE,eventType:n},window.location.origin))},[]),z=()=>{M.current!==null&&(window.clearTimeout(M.current),M.current=null)},Se=()=>{C.current!==null&&(window.cancelAnimationFrame(C.current),C.current=null)};t.useEffect(()=>()=>{z(),Se()},[]),t.useEffect(()=>{const n=oe.current;oe.current=r;const e=!!n&&r.length>n.length&&r.startsWith(n),l=Fe.test(r);if(!(e&&l)){z(),$.current=r,re(r);return}$.current=r,z(),M.current=window.setTimeout(()=>{re($.current),M.current=null},Ie)},[r]);const V=t.useMemo(()=>v?b.inspectViewportHeightFromHtmlRootString(_).viewportHeightCss:null,[_,v]);t.useEffect(()=>{se.current=V},[V]);const ie=!!V,y=m&&s==="sandbox"?ne?"100%":V??`${we}px`:void 0;t.useEffect(()=>{if(d!=="blackboard"){L.current=r;return}const n=L.current;!(n&&r.startsWith(n))&&n&&xe(l=>l+1),L.current=r},[d,r]),t.useEffect(()=>{const n=p.current;if(!n)return;const e=n.contentDocument;if(!e)return;e.open(),e.write(`<!DOCTYPE html>
|
|
2
|
+
<html${d==="blackboard"?' style="height: 100%;"':""}>
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<style>
|
|
7
7
|
:root { color-scheme: light; }
|
|
8
8
|
html, body, #root { width: 100%; }
|
|
9
|
-
${
|
|
9
|
+
${d==="blackboard"?"html, body, #root { height: 100%; }":""}
|
|
10
10
|
html, body { margin: 0; padding: 0; overflow: auto; }
|
|
11
11
|
*, *::before, *::after { box-sizing: border-box; }
|
|
12
|
+
html.measuring-height, html.measuring-height body,
|
|
13
|
+
html.measuring-height #root, html.measuring-height .sandbox-wrapper {
|
|
14
|
+
height: auto !important; min-height: 0 !important;
|
|
15
|
+
}
|
|
12
16
|
</style>
|
|
13
17
|
</head>
|
|
14
18
|
<body>
|
|
15
19
|
<div id="root"></div>
|
|
16
20
|
</body>
|
|
17
|
-
</html>`),e.close(),e.documentElement.setAttribute("data-theme","light"),e.documentElement.style.colorScheme="light",e.body?.style.setProperty("color-scheme","light");const l=
|
|
21
|
+
</html>`),e.close(),e.documentElement.setAttribute("data-theme","light"),e.documentElement.style.colorScheme="light",e.body?.style.setProperty("color-scheme","light");const l=m&&s==="sandbox",W=()=>H("pointerdown"),le=()=>H("mousedown"),ue=()=>H("touchstart");l&&(e.addEventListener("pointerdown",W,!0),e.addEventListener("mousedown",le,!0),e.addEventListener("touchstart",ue,!0));const x=e.getElementById("root");if(!x)return;const ae=ye.createRoot(x);P.current=ae;let T=!1;const he=o=>({heightAttrValue:o.getAttribute("height"),styleAttrValue:o.getAttribute("style"),classAttrValue:o.getAttribute("class")}),de=o=>{const f=Array.from(o.children);return f.length===1?f[0]:null},Ce=()=>{if(!v||!p.current||!e.body)return null;const o=p.current.ownerDocument?.documentElement?.clientHeight||window.innerHeight,f=se.current,D=f?b.parseExplicitHeight(f,o):null;if(D!==null)return Math.ceil(D);const a=e.body.querySelector(".sandbox-wrapper")?.firstElementChild;if(!a)return null;const u=Array.from(a.children),g=u.length===1?u[0]:null,j=b.inspectViewportHeightFromNodeChain(g,{getNode:he,getSingleChild:de}).viewportHeightCss;if(j){const ge=b.parseExplicitHeight(j,o);if(ge!==null)return Math.ceil(ge)}const F=b.resolveExplicitHeightFromNodeChain(g,o,{getNode:he,getSingleChild:de});return F!==null?Math.ceil(F):null},G=()=>{if(!p.current||!e.body)return;if(!m){e.documentElement.classList.add("measuring-height");const a=e.body.scrollHeight,u=e.documentElement?.scrollHeight||0,g=x?.scrollHeight||0,fe=Math.max(a,u,g);e.documentElement.classList.remove("measuring-height"),J(j=>{const F=Math.max(200,Math.ceil(fe));return j===F?j:F});return}const o=e.body.scrollHeight,f=e.documentElement?.scrollHeight||0,D=x?.scrollHeight||0,X=Math.max(o,f,D);if(v){const a=Ce(),u=Math.max(200,a??Math.ceil(X));He(g=>g===u?g:u)}J(a=>{const u=Math.max(200,Math.ceil(X));return a===u?a:u})},A=()=>{requestAnimationFrame(()=>{T||G()})};S.current=A,G(),A(),Re&&je().then(o=>{T||(o(e),requestAnimationFrame(()=>{T||A()}))}).catch(()=>{T||A()});const U=new ResizeObserver(()=>G());U.observe(e.body),x&&U.observe(x);const me=new MutationObserver(()=>{A()});return me.observe(e.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["style","class"]}),()=>{T=!0,U.disconnect(),me.disconnect(),l&&(e.removeEventListener("pointerdown",W,!0),e.removeEventListener("mousedown",le,!0),e.removeEventListener("touchstart",ue,!0)),setTimeout(()=>{ae.unmount(),P.current=null,S.current=()=>{}},0)}},[]),t.useEffect(()=>{const n=()=>{Ee(!!document.fullscreenElement)};return document.addEventListener("fullscreenchange",n),()=>document.removeEventListener("fullscreenchange",n)},[]),t.useEffect(()=>{const n=k.current;if(!n)return;const e=new ResizeObserver(l=>{K(l[0]?.contentRect.width??n.clientWidth)});return e.observe(n),K(n.clientWidth),()=>e.disconnect()},[]);const ce=t.useMemo(()=>{if(m||q===0||B)return;const n=Math.round(q*9/16);return{height:Math.max(n,Z)}},[m,q,Z,B]),ve=()=>{const n=k.current||p.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(E.jsxRuntimeExports.jsx(Te.default,{html:_,styleLoadingText:I,scriptLoadingText:R,resetToken:ee,hasRootVhHeight:ie,mode:d,stretchRootHeight:ne})),C.current=window.requestAnimationFrame(()=>{S.current?.(),C.current=null});const e=setTimeout(()=>S.current?.(),100),l=setTimeout(()=>S.current?.(),500);return()=>{clearTimeout(e),clearTimeout(l)}},[_,I,R,ee,d]);const Me=["w-full relative content-render-iframe-sandbox",m?"h-full overflow-auto flex flex-col":ce?"overflow-hidden flex items-center justify-center":"aspect-[16/9] overflow-hidden flex items-center justify-center"].filter(Boolean).join(" ");return E.jsxRuntimeExports.jsxs("div",{ref:k,"data-root-vh":ie?"true":"false",className:Me,style:y?{height:y,minHeight:y}:ce,children:[!N&&E.jsxRuntimeExports.jsx("button",{type:"button",onClick:ve,className:"absolute top-2 right-2 z-50 p-1.5 bg-black/75 text-white rounded-md cursor-pointer",children:B?"退出全屏":h||"全屏浏览"}),d==="blackboard"&&s==="markdown"?E.jsxRuntimeExports.jsx("div",{onMouseDown:()=>H("mousedown"),onPointerDown:()=>H("pointerdown"),onTouchStart:()=>H("touchstart"),children:E.jsxRuntimeExports.jsx(Ae.default,{content:c})}):E.jsxRuntimeExports.jsx("iframe",{ref:p,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:y??"100%",minHeight:y,margin:"auto"}})]})};exports.default=Ve;
|
|
18
22
|
//# 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 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: auto; }\n *, *::before, *::after { box-sizing: border-box; }\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 // For content mode: temporarily shrink iframe to 0 so that\n // elements with height:100% / vh units collapse, revealing\n // the true minimum content height without feedback loops.\n const iframe = iframeRef.current;\n const prevIframeH = iframe.style.height;\n if (!isBlackboardMode) {\n iframe.style.height = \"0px\";\n }\n\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 // Restore iframe height immediately (no paint in between)\n if (!isBlackboardMode) {\n iframe.style.height = prevIframeH;\n }\n\n if (shouldMeasureDynamicHeight) {\n // Blackboard mode: use existing explicit height resolution logic\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 // Always update contentHeight for content mode auto-sizing\n setContentHeight((prev) => {\n const next = Math.max(200, Math.ceil(measuredHeight));\n return prev === next ? prev : next;\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","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","prevIframeH","bodyScrollH","htmlScrollH","rootScrollH","measuredHeight","explicitHeight","nextHeight","prevHeight","next","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 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: auto; }\n *, *::before, *::after { box-sizing: border-box; }\n html.measuring-height, html.measuring-height body,\n html.measuring-height #root, html.measuring-height .sandbox-wrapper {\n height: auto !important; min-height: 0 !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 // Content mode: toggle a CSS class on <html> to neutralize\n // height:100% / min-h-screen on wrapper chain during measurement.\n // Using <html> class avoids triggering MutationObserver (which\n // only observes doc.body and its descendants).\n doc.documentElement.classList.add(\"measuring-height\");\n\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 doc.documentElement.classList.remove(\"measuring-height\");\n\n setContentHeight((prev) => {\n const next = Math.max(200, Math.ceil(measuredHeight));\n return prev === next ? prev : next;\n });\n return;\n }\n\n // Blackboard mode: use existing explicit height resolution 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 setContentHeight((prev) => {\n const next = Math.max(200, Math.ceil(measuredHeight));\n return prev === next ? prev : next;\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","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","bodyScrollH","htmlScrollH","rootScrollH","measuredHeight","next","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,65 +1,65 @@
|
|
|
1
|
-
import { j as
|
|
2
|
-
import
|
|
1
|
+
import { j as E } from "../../_virtual/jsx-runtime.es.js";
|
|
2
|
+
import _, { useRef as l, useState as v, useCallback as Fe, useEffect as m, useMemo as Ie } from "react";
|
|
3
3
|
import { createRoot as Ne } from "react-dom/client";
|
|
4
4
|
import _e from "./SandboxApp.es.js";
|
|
5
5
|
import Oe from "./ContentRender.es.js";
|
|
6
|
-
import { inspectViewportHeightFromHtmlRootString as
|
|
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 ke, SANDBOX_INTERACTION_MESSAGE_SOURCE as Be } from "../../lib/sandboxInteraction.es.js";
|
|
8
|
-
let
|
|
9
|
-
const Pe = () => (
|
|
8
|
+
let J = null;
|
|
9
|
+
const Pe = () => (J || (J = import("./blackboard-vendor.es.js").then(
|
|
10
10
|
(s) => s.injectBlackboardLibraries
|
|
11
|
-
)),
|
|
11
|
+
)), J), Le = /<img\b[^>]*>/i, $e = 180, ze = 240, We = (s) => s.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
14
|
}).join(" "), qe = (s, o) => !o || !s.trim() ? s : s.replace(
|
|
15
15
|
/^(\s*<[a-zA-Z][\w:-]*)(\s[^>]*?)?>/,
|
|
16
|
-
(i,
|
|
17
|
-
const
|
|
18
|
-
if (!
|
|
16
|
+
(i, O, S = "") => {
|
|
17
|
+
const h = S.match(/\bclass\s*=\s*(["'])([^"']*)\1/i);
|
|
18
|
+
if (!h)
|
|
19
19
|
return i;
|
|
20
|
-
const
|
|
21
|
-
return
|
|
22
|
-
|
|
23
|
-
`class=${
|
|
20
|
+
const V = We(h[2]);
|
|
21
|
+
return V === h[2] ? i : `${O}${S.replace(
|
|
22
|
+
h[0],
|
|
23
|
+
`class=${h[1]}${V}${h[1]}`
|
|
24
24
|
)}>`;
|
|
25
25
|
}
|
|
26
26
|
), Qe = ({
|
|
27
27
|
content: s,
|
|
28
28
|
type: o,
|
|
29
29
|
className: i,
|
|
30
|
-
styleLoadingText:
|
|
31
|
-
scriptLoadingText:
|
|
32
|
-
fullScreenButtonText:
|
|
33
|
-
hideFullScreen:
|
|
34
|
-
mode:
|
|
35
|
-
replaceRootScreenHeightWithFull:
|
|
30
|
+
styleLoadingText: O,
|
|
31
|
+
scriptLoadingText: S,
|
|
32
|
+
fullScreenButtonText: h,
|
|
33
|
+
hideFullScreen: V = !1,
|
|
34
|
+
mode: d = "content",
|
|
35
|
+
replaceRootScreenHeightWithFull: xe = !1
|
|
36
36
|
}) => {
|
|
37
|
-
const P = l(null),
|
|
38
|
-
}), [
|
|
37
|
+
const P = l(null), p = l(null), L = l(null), R = l(() => {
|
|
38
|
+
}), [Ee, ve] = v(480), [K, Q] = v(0), [$, ee] = v(0), te = l(0), [ne, Se] = v(0), [z, Re] = v(!1), Me = o === "sandbox", g = d === "blackboard", M = g && o === "sandbox", w = M && xe, W = l(""), D = _.useMemo(
|
|
39
39
|
() => o === "sandbox" ? s : "",
|
|
40
40
|
[s, o]
|
|
41
|
-
), n =
|
|
41
|
+
), n = _.useMemo(
|
|
42
42
|
() => qe(
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
D,
|
|
44
|
+
w
|
|
45
45
|
),
|
|
46
|
-
[
|
|
47
|
-
),
|
|
48
|
-
() =>
|
|
49
|
-
[
|
|
50
|
-
),
|
|
51
|
-
() =>
|
|
46
|
+
[D, w]
|
|
47
|
+
), re = _.useMemo(
|
|
48
|
+
() => w ? we(D) : Ve,
|
|
49
|
+
[D, w]
|
|
50
|
+
), oe = _.useMemo(
|
|
51
|
+
() => w && re.hasFullViewportHeight,
|
|
52
52
|
[
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
re.hasFullViewportHeight,
|
|
54
|
+
w
|
|
55
55
|
]
|
|
56
|
-
), [
|
|
56
|
+
), [j, ie] = v(
|
|
57
57
|
n
|
|
58
|
-
),
|
|
58
|
+
), se = l(n), q = l(n), C = l(null), y = l(null), le = l(null), H = Fe((t) => {
|
|
59
59
|
if (typeof window > "u")
|
|
60
60
|
return;
|
|
61
61
|
const e = Date.now();
|
|
62
|
-
e -
|
|
62
|
+
e - te.current < ze || (te.current = e, window.postMessage(
|
|
63
63
|
{
|
|
64
64
|
source: Be,
|
|
65
65
|
type: ke,
|
|
@@ -68,179 +68,190 @@ const Pe = () => (Z || (Z = import("./blackboard-vendor.es.js").then(
|
|
|
68
68
|
window.location.origin
|
|
69
69
|
));
|
|
70
70
|
}, []), G = () => {
|
|
71
|
-
|
|
72
|
-
},
|
|
73
|
-
|
|
71
|
+
C.current !== null && (window.clearTimeout(C.current), C.current = null);
|
|
72
|
+
}, Ce = () => {
|
|
73
|
+
y.current !== null && (window.cancelAnimationFrame(y.current), y.current = null);
|
|
74
74
|
};
|
|
75
|
-
|
|
75
|
+
m(
|
|
76
76
|
() => () => {
|
|
77
|
-
G(),
|
|
77
|
+
G(), Ce();
|
|
78
78
|
},
|
|
79
79
|
[]
|
|
80
|
-
),
|
|
81
|
-
const t =
|
|
82
|
-
|
|
80
|
+
), m(() => {
|
|
81
|
+
const t = se.current;
|
|
82
|
+
se.current = n;
|
|
83
83
|
const e = !!t && n.length > t.length && n.startsWith(t), c = Le.test(
|
|
84
84
|
n
|
|
85
85
|
);
|
|
86
86
|
if (!(e && c)) {
|
|
87
|
-
G(), q.current = n,
|
|
87
|
+
G(), q.current = n, ie(n);
|
|
88
88
|
return;
|
|
89
89
|
}
|
|
90
|
-
q.current = n, G(),
|
|
91
|
-
|
|
90
|
+
q.current = n, G(), C.current = window.setTimeout(() => {
|
|
91
|
+
ie(q.current), C.current = null;
|
|
92
92
|
}, $e);
|
|
93
93
|
}, [n]);
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}, [
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
if (
|
|
94
|
+
const k = _.useMemo(() => M ? we(j).viewportHeightCss : null, [j, M]);
|
|
95
|
+
m(() => {
|
|
96
|
+
le.current = k;
|
|
97
|
+
}, [k]);
|
|
98
|
+
const ce = !!k, T = g && o === "sandbox" ? oe ? "100%" : k ?? `${Ee}px` : void 0;
|
|
99
|
+
m(() => {
|
|
100
|
+
if (d !== "blackboard") {
|
|
101
101
|
W.current = n;
|
|
102
102
|
return;
|
|
103
103
|
}
|
|
104
104
|
const t = W.current;
|
|
105
|
-
!(t && n.startsWith(t)) && t &&
|
|
106
|
-
}, [
|
|
107
|
-
const t =
|
|
105
|
+
!(t && n.startsWith(t)) && t && Se((c) => c + 1), W.current = n;
|
|
106
|
+
}, [d, n]), m(() => {
|
|
107
|
+
const t = p.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${d === "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
|
-
${
|
|
119
|
+
${d === "blackboard" ? "html, body, #root { height: 100%; }" : ""}
|
|
120
120
|
html, body { margin: 0; padding: 0; overflow: auto; }
|
|
121
121
|
*, *::before, *::after { box-sizing: border-box; }
|
|
122
|
+
html.measuring-height, html.measuring-height body,
|
|
123
|
+
html.measuring-height #root, html.measuring-height .sandbox-wrapper {
|
|
124
|
+
height: auto !important; min-height: 0 !important;
|
|
125
|
+
}
|
|
122
126
|
</style>
|
|
123
127
|
</head>
|
|
124
128
|
<body>
|
|
125
129
|
<div id="root"></div>
|
|
126
130
|
</body>
|
|
127
131
|
</html>`), e.close(), e.documentElement.setAttribute("data-theme", "light"), e.documentElement.style.colorScheme = "light", e.body?.style.setProperty("color-scheme", "light");
|
|
128
|
-
const c =
|
|
129
|
-
c && (e.addEventListener("pointerdown", U, !0), e.addEventListener("mousedown",
|
|
130
|
-
const
|
|
131
|
-
if (!
|
|
132
|
-
const
|
|
133
|
-
L.current =
|
|
134
|
-
let
|
|
135
|
-
const
|
|
132
|
+
const c = g && o === "sandbox", U = () => H("pointerdown"), ae = () => H("mousedown"), he = () => H("touchstart");
|
|
133
|
+
c && (e.addEventListener("pointerdown", U, !0), e.addEventListener("mousedown", ae, !0), e.addEventListener("touchstart", he, !0));
|
|
134
|
+
const x = e.getElementById("root");
|
|
135
|
+
if (!x) return;
|
|
136
|
+
const de = Ne(x);
|
|
137
|
+
L.current = de;
|
|
138
|
+
let A = !1;
|
|
139
|
+
const me = (r) => ({
|
|
136
140
|
heightAttrValue: r.getAttribute("height"),
|
|
137
141
|
styleAttrValue: r.getAttribute("style"),
|
|
138
142
|
classAttrValue: r.getAttribute("class")
|
|
139
|
-
}),
|
|
143
|
+
}), ge = (r) => {
|
|
140
144
|
const f = Array.from(r.children);
|
|
141
145
|
return f.length === 1 ? f[0] : null;
|
|
142
146
|
}, Ae = () => {
|
|
143
|
-
if (!
|
|
144
|
-
const r =
|
|
147
|
+
if (!M || !p.current || !e.body) return null;
|
|
148
|
+
const r = p.current.ownerDocument?.documentElement?.clientHeight || window.innerHeight, f = le.current, B = f ? He(
|
|
145
149
|
f,
|
|
146
150
|
r
|
|
147
151
|
) : null;
|
|
148
|
-
if (
|
|
149
|
-
return Math.ceil(
|
|
150
|
-
const
|
|
152
|
+
if (B !== null)
|
|
153
|
+
return Math.ceil(B);
|
|
154
|
+
const a = e.body.querySelector(
|
|
151
155
|
".sandbox-wrapper"
|
|
152
156
|
)?.firstElementChild;
|
|
153
|
-
if (!
|
|
154
|
-
const
|
|
155
|
-
|
|
157
|
+
if (!a) return null;
|
|
158
|
+
const u = Array.from(a.children), b = u.length === 1 ? u[0] : null, I = De(
|
|
159
|
+
b,
|
|
156
160
|
{
|
|
157
|
-
getNode:
|
|
158
|
-
getSingleChild:
|
|
161
|
+
getNode: me,
|
|
162
|
+
getSingleChild: ge
|
|
159
163
|
}
|
|
160
164
|
).viewportHeightCss;
|
|
161
|
-
if (
|
|
162
|
-
const pe =
|
|
163
|
-
|
|
165
|
+
if (I) {
|
|
166
|
+
const pe = He(
|
|
167
|
+
I,
|
|
164
168
|
r
|
|
165
169
|
);
|
|
166
170
|
if (pe !== null)
|
|
167
171
|
return Math.ceil(pe);
|
|
168
172
|
}
|
|
169
|
-
const
|
|
170
|
-
|
|
173
|
+
const N = je(
|
|
174
|
+
b,
|
|
171
175
|
r,
|
|
172
176
|
{
|
|
173
|
-
getNode:
|
|
174
|
-
getSingleChild:
|
|
177
|
+
getNode: me,
|
|
178
|
+
getSingleChild: ge
|
|
175
179
|
}
|
|
176
180
|
);
|
|
177
|
-
return
|
|
181
|
+
return N !== null ? Math.ceil(N) : null;
|
|
178
182
|
}, X = () => {
|
|
179
|
-
if (!
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
183
|
+
if (!p.current || !e.body) return;
|
|
184
|
+
if (!g) {
|
|
185
|
+
e.documentElement.classList.add("measuring-height");
|
|
186
|
+
const a = e.body.scrollHeight, u = e.documentElement?.scrollHeight || 0, b = x?.scrollHeight || 0, be = Math.max(a, u, b);
|
|
187
|
+
e.documentElement.classList.remove("measuring-height"), Q((I) => {
|
|
188
|
+
const N = Math.max(200, Math.ceil(be));
|
|
189
|
+
return I === N ? I : N;
|
|
190
|
+
});
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const r = e.body.scrollHeight, f = e.documentElement?.scrollHeight || 0, B = x?.scrollHeight || 0, Z = Math.max(r, f, B);
|
|
194
|
+
if (M) {
|
|
195
|
+
const a = Ae(), u = Math.max(
|
|
185
196
|
200,
|
|
186
|
-
|
|
197
|
+
a ?? Math.ceil(Z)
|
|
187
198
|
);
|
|
188
|
-
|
|
189
|
-
(
|
|
199
|
+
ve(
|
|
200
|
+
(b) => b === u ? b : u
|
|
190
201
|
);
|
|
191
202
|
}
|
|
192
|
-
|
|
193
|
-
const
|
|
194
|
-
return
|
|
203
|
+
Q((a) => {
|
|
204
|
+
const u = Math.max(200, Math.ceil(Z));
|
|
205
|
+
return a === u ? a : u;
|
|
195
206
|
});
|
|
196
|
-
},
|
|
207
|
+
}, F = () => {
|
|
197
208
|
requestAnimationFrame(() => {
|
|
198
|
-
|
|
209
|
+
A || X();
|
|
199
210
|
});
|
|
200
211
|
};
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
212
|
+
R.current = F, X(), F(), Me && Pe().then((r) => {
|
|
213
|
+
A || (r(e), requestAnimationFrame(() => {
|
|
214
|
+
A || F();
|
|
204
215
|
}));
|
|
205
216
|
}).catch(() => {
|
|
206
|
-
|
|
217
|
+
A || F();
|
|
207
218
|
});
|
|
208
219
|
const Y = new ResizeObserver(() => X());
|
|
209
|
-
Y.observe(e.body),
|
|
210
|
-
const
|
|
211
|
-
|
|
220
|
+
Y.observe(e.body), x && Y.observe(x);
|
|
221
|
+
const fe = new MutationObserver(() => {
|
|
222
|
+
F();
|
|
212
223
|
});
|
|
213
|
-
return
|
|
224
|
+
return fe.observe(e.body, {
|
|
214
225
|
childList: !0,
|
|
215
226
|
subtree: !0,
|
|
216
227
|
attributes: !0,
|
|
217
228
|
attributeFilter: ["style", "class"]
|
|
218
229
|
}), () => {
|
|
219
|
-
|
|
220
|
-
|
|
230
|
+
A = !0, Y.disconnect(), fe.disconnect(), c && (e.removeEventListener("pointerdown", U, !0), e.removeEventListener("mousedown", ae, !0), e.removeEventListener("touchstart", he, !0)), setTimeout(() => {
|
|
231
|
+
de.unmount(), L.current = null, R.current = () => {
|
|
221
232
|
};
|
|
222
233
|
}, 0);
|
|
223
234
|
};
|
|
224
|
-
}, []),
|
|
235
|
+
}, []), m(() => {
|
|
225
236
|
const t = () => {
|
|
226
|
-
|
|
237
|
+
Re(!!document.fullscreenElement);
|
|
227
238
|
};
|
|
228
239
|
return document.addEventListener("fullscreenchange", t), () => document.removeEventListener("fullscreenchange", t);
|
|
229
|
-
}, []),
|
|
240
|
+
}, []), m(() => {
|
|
230
241
|
const t = P.current;
|
|
231
242
|
if (!t) return;
|
|
232
243
|
const e = new ResizeObserver((c) => {
|
|
233
|
-
|
|
244
|
+
ee(c[0]?.contentRect.width ?? t.clientWidth);
|
|
234
245
|
});
|
|
235
|
-
return e.observe(t),
|
|
246
|
+
return e.observe(t), ee(t.clientWidth), () => e.disconnect();
|
|
236
247
|
}, []);
|
|
237
|
-
const
|
|
238
|
-
if (
|
|
248
|
+
const ue = Ie(() => {
|
|
249
|
+
if (g || $ === 0 || z)
|
|
239
250
|
return;
|
|
240
251
|
const t = Math.round($ * 9 / 16);
|
|
241
|
-
return { height: Math.max(t,
|
|
242
|
-
}, [
|
|
243
|
-
const t = P.current ||
|
|
252
|
+
return { height: Math.max(t, K) };
|
|
253
|
+
}, [g, $, K, z]), ye = () => {
|
|
254
|
+
const t = P.current || p.current;
|
|
244
255
|
if (t) {
|
|
245
256
|
if (document.fullscreenElement) {
|
|
246
257
|
document.exitFullscreen().catch(() => {
|
|
@@ -251,79 +262,79 @@ const Pe = () => (Z || (Z = import("./blackboard-vendor.es.js").then(
|
|
|
251
262
|
});
|
|
252
263
|
}
|
|
253
264
|
};
|
|
254
|
-
|
|
265
|
+
m(() => {
|
|
255
266
|
const t = L.current;
|
|
256
267
|
if (!t) return;
|
|
257
268
|
t.render(
|
|
258
|
-
/* @__PURE__ */
|
|
269
|
+
/* @__PURE__ */ E.jsx(
|
|
259
270
|
_e,
|
|
260
271
|
{
|
|
261
|
-
html:
|
|
262
|
-
styleLoadingText:
|
|
263
|
-
scriptLoadingText:
|
|
264
|
-
resetToken:
|
|
265
|
-
hasRootVhHeight:
|
|
266
|
-
mode:
|
|
267
|
-
stretchRootHeight:
|
|
272
|
+
html: j,
|
|
273
|
+
styleLoadingText: O,
|
|
274
|
+
scriptLoadingText: S,
|
|
275
|
+
resetToken: ne,
|
|
276
|
+
hasRootVhHeight: ce,
|
|
277
|
+
mode: d,
|
|
278
|
+
stretchRootHeight: oe
|
|
268
279
|
}
|
|
269
280
|
)
|
|
270
|
-
),
|
|
271
|
-
|
|
281
|
+
), y.current = window.requestAnimationFrame(() => {
|
|
282
|
+
R.current?.(), y.current = null;
|
|
272
283
|
});
|
|
273
|
-
const e = setTimeout(() =>
|
|
284
|
+
const e = setTimeout(() => R.current?.(), 100), c = setTimeout(() => R.current?.(), 500);
|
|
274
285
|
return () => {
|
|
275
286
|
clearTimeout(e), clearTimeout(c);
|
|
276
287
|
};
|
|
277
288
|
}, [
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
289
|
+
j,
|
|
290
|
+
O,
|
|
291
|
+
S,
|
|
292
|
+
ne,
|
|
293
|
+
d
|
|
283
294
|
]);
|
|
284
295
|
const Te = [
|
|
285
296
|
"w-full relative content-render-iframe-sandbox",
|
|
286
|
-
|
|
297
|
+
g ? "h-full overflow-auto flex flex-col" : ue ? "overflow-hidden flex items-center justify-center" : "aspect-[16/9] overflow-hidden flex items-center justify-center"
|
|
287
298
|
].filter(Boolean).join(" ");
|
|
288
|
-
return /* @__PURE__ */
|
|
299
|
+
return /* @__PURE__ */ E.jsxs(
|
|
289
300
|
"div",
|
|
290
301
|
{
|
|
291
302
|
ref: P,
|
|
292
|
-
"data-root-vh":
|
|
303
|
+
"data-root-vh": ce ? "true" : "false",
|
|
293
304
|
className: Te,
|
|
294
|
-
style:
|
|
295
|
-
height:
|
|
296
|
-
minHeight:
|
|
297
|
-
} :
|
|
305
|
+
style: T ? {
|
|
306
|
+
height: T,
|
|
307
|
+
minHeight: T
|
|
308
|
+
} : ue,
|
|
298
309
|
children: [
|
|
299
|
-
!
|
|
310
|
+
!V && /* @__PURE__ */ E.jsx(
|
|
300
311
|
"button",
|
|
301
312
|
{
|
|
302
313
|
type: "button",
|
|
303
314
|
onClick: ye,
|
|
304
315
|
className: "absolute top-2 right-2 z-50 p-1.5 bg-black/75 text-white rounded-md cursor-pointer",
|
|
305
|
-
children: z ? "退出全屏" :
|
|
316
|
+
children: z ? "退出全屏" : h || "全屏浏览"
|
|
306
317
|
}
|
|
307
318
|
),
|
|
308
|
-
|
|
319
|
+
d === "blackboard" && o === "markdown" ? /* @__PURE__ */ E.jsx(
|
|
309
320
|
"div",
|
|
310
321
|
{
|
|
311
|
-
onMouseDown: () =>
|
|
312
|
-
onPointerDown: () =>
|
|
313
|
-
onTouchStart: () =>
|
|
314
|
-
children: /* @__PURE__ */
|
|
322
|
+
onMouseDown: () => H("mousedown"),
|
|
323
|
+
onPointerDown: () => H("pointerdown"),
|
|
324
|
+
onTouchStart: () => H("touchstart"),
|
|
325
|
+
children: /* @__PURE__ */ E.jsx(Oe, { content: s })
|
|
315
326
|
}
|
|
316
|
-
) : /* @__PURE__ */
|
|
327
|
+
) : /* @__PURE__ */ E.jsx(
|
|
317
328
|
"iframe",
|
|
318
329
|
{
|
|
319
|
-
ref:
|
|
330
|
+
ref: p,
|
|
320
331
|
sandbox: "allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox",
|
|
321
332
|
allow: "fullscreen",
|
|
322
333
|
allowFullScreen: !0,
|
|
323
334
|
className: [i, "w-full h-full mx-auto my-auto block"].filter(Boolean).join(" "),
|
|
324
335
|
style: {
|
|
325
|
-
height:
|
|
326
|
-
minHeight:
|
|
336
|
+
height: T ?? "100%",
|
|
337
|
+
minHeight: T,
|
|
327
338
|
margin: "auto"
|
|
328
339
|
}
|
|
329
340
|
}
|
|
@@ -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 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: auto; }\n *, *::before, *::after { box-sizing: border-box; }\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 // For content mode: temporarily shrink iframe to 0 so that\n // elements with height:100% / vh units collapse, revealing\n // the true minimum content height without feedback loops.\n const iframe = iframeRef.current;\n const prevIframeH = iframe.style.height;\n if (!isBlackboardMode) {\n iframe.style.height = \"0px\";\n }\n\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 // Restore iframe height immediately (no paint in between)\n if (!isBlackboardMode) {\n iframe.style.height = prevIframeH;\n }\n\n if (shouldMeasureDynamicHeight) {\n // Blackboard mode: use existing explicit height resolution logic\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 // Always update contentHeight for content mode auto-sizing\n setContentHeight((prev) => {\n const next = Math.max(200, Math.ceil(measuredHeight));\n return prev === next ? prev : next;\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","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","prevIframeH","bodyScrollH","htmlScrollH","rootScrollH","measuredHeight","explicitHeight","nextHeight","prevHeight","next","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 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: auto; }\n *, *::before, *::after { box-sizing: border-box; }\n html.measuring-height, html.measuring-height body,\n html.measuring-height #root, html.measuring-height .sandbox-wrapper {\n height: auto !important; min-height: 0 !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 // Content mode: toggle a CSS class on <html> to neutralize\n // height:100% / min-h-screen on wrapper chain during measurement.\n // Using <html> class avoids triggering MutationObserver (which\n // only observes doc.body and its descendants).\n doc.documentElement.classList.add(\"measuring-height\");\n\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 doc.documentElement.classList.remove(\"measuring-height\");\n\n setContentHeight((prev) => {\n const next = Math.max(200, Math.ceil(measuredHeight));\n return prev === next ? prev : next;\n });\n return;\n }\n\n // Blackboard mode: use existing explicit height resolution 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 setContentHeight((prev) => {\n const next = Math.max(200, Math.ceil(measuredHeight));\n return prev === next ? prev : next;\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","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","bodyScrollH","htmlScrollH","rootScrollH","measuredHeight","next","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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../../../../../node_modules/@braintree/sanitize-url/dist/index.js"],"sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.sanitizeUrl = void 0;\nvar constants_1 = require(\"./constants\");\nfunction isRelativeUrlWithoutProtocol(url) {\n return constants_1.relativeFirstCharacters.indexOf(url[0]) > -1;\n}\nfunction decodeHtmlCharacters(str) {\n var removedNullByte = str.replace(constants_1.ctrlCharactersRegex, \"\");\n return removedNullByte.replace(constants_1.htmlEntitiesRegex, function (match, dec) {\n return String.fromCharCode(dec);\n });\n}\nfunction isValidUrl(url) {\n return URL.canParse(url);\n}\nfunction decodeURI(uri) {\n try {\n return decodeURIComponent(uri);\n }\n catch (e) {\n // Ignoring error\n // It is possible that the URI contains a `%` not associated\n // with URI/URL-encoding.\n return uri;\n }\n}\nfunction sanitizeUrl(url) {\n if (!url) {\n return constants_1.BLANK_URL;\n }\n var charsToDecode;\n var decodedUrl = decodeURI(url.trim());\n do {\n decodedUrl = decodeHtmlCharacters(decodedUrl)\n .replace(constants_1.htmlCtrlEntityRegex, \"\")\n .replace(constants_1.ctrlCharactersRegex, \"\")\n .replace(constants_1.whitespaceEscapeCharsRegex, \"\")\n .trim();\n decodedUrl = decodeURI(decodedUrl);\n charsToDecode =\n decodedUrl.match(constants_1.ctrlCharactersRegex) ||\n decodedUrl.match(constants_1.htmlEntitiesRegex) ||\n decodedUrl.match(constants_1.htmlCtrlEntityRegex) ||\n decodedUrl.match(constants_1.whitespaceEscapeCharsRegex);\n } while (charsToDecode && charsToDecode.length > 0);\n var sanitizedUrl = decodedUrl;\n if (!sanitizedUrl) {\n return constants_1.BLANK_URL;\n }\n if (isRelativeUrlWithoutProtocol(sanitizedUrl)) {\n return sanitizedUrl;\n }\n // Remove any leading whitespace before checking the URL scheme\n var trimmedUrl = sanitizedUrl.trimStart();\n var urlSchemeParseResults = trimmedUrl.match(constants_1.urlSchemeRegex);\n if (!urlSchemeParseResults) {\n return sanitizedUrl;\n }\n var urlScheme = urlSchemeParseResults[0].toLowerCase().trim();\n if (constants_1.invalidProtocolRegex.test(urlScheme)) {\n return constants_1.BLANK_URL;\n }\n var backSanitized = trimmedUrl.replace(/\\\\/g, \"/\");\n // Handle special cases for mailto: and custom deep-link protocols\n if (urlScheme === \"mailto:\" || urlScheme.includes(\"://\")) {\n return backSanitized;\n }\n // For http and https URLs, perform additional validation\n if (urlScheme === \"http:\" || urlScheme === \"https:\") {\n if (!isValidUrl(backSanitized)) {\n return constants_1.BLANK_URL;\n }\n var url_1 = new URL(backSanitized);\n url_1.protocol = url_1.protocol.toLowerCase();\n url_1.hostname = url_1.hostname.toLowerCase();\n return url_1.toString();\n }\n return backSanitized;\n}\nexports.sanitizeUrl = sanitizeUrl;\n"],"names":["dist","constants_1","require$$0","isRelativeUrlWithoutProtocol","url","decodeHtmlCharacters","str","removedNullByte","match","dec","isValidUrl","decodeURI","uri","sanitizeUrl","charsToDecode","decodedUrl","sanitizedUrl","trimmedUrl","urlSchemeParseResults","urlScheme","backSanitized","url_1"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../../../../../node_modules/@braintree/sanitize-url/dist/index.js"],"sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.sanitizeUrl = void 0;\nvar constants_1 = require(\"./constants\");\nfunction isRelativeUrlWithoutProtocol(url) {\n return constants_1.relativeFirstCharacters.indexOf(url[0]) > -1;\n}\nfunction decodeHtmlCharacters(str) {\n var removedNullByte = str.replace(constants_1.ctrlCharactersRegex, \"\");\n return removedNullByte.replace(constants_1.htmlEntitiesRegex, function (match, dec) {\n return String.fromCharCode(dec);\n });\n}\nfunction isValidUrl(url) {\n return URL.canParse(url);\n}\nfunction decodeURI(uri) {\n try {\n return decodeURIComponent(uri);\n }\n catch (e) {\n // Ignoring error\n // It is possible that the URI contains a `%` not associated\n // with URI/URL-encoding.\n return uri;\n }\n}\nfunction sanitizeUrl(url) {\n if (!url) {\n return constants_1.BLANK_URL;\n }\n var charsToDecode;\n var decodedUrl = decodeURI(url.trim());\n do {\n decodedUrl = decodeHtmlCharacters(decodedUrl)\n .replace(constants_1.htmlCtrlEntityRegex, \"\")\n .replace(constants_1.ctrlCharactersRegex, \"\")\n .replace(constants_1.whitespaceEscapeCharsRegex, \"\")\n .trim();\n decodedUrl = decodeURI(decodedUrl);\n charsToDecode =\n decodedUrl.match(constants_1.ctrlCharactersRegex) ||\n decodedUrl.match(constants_1.htmlEntitiesRegex) ||\n decodedUrl.match(constants_1.htmlCtrlEntityRegex) ||\n decodedUrl.match(constants_1.whitespaceEscapeCharsRegex);\n } while (charsToDecode && charsToDecode.length > 0);\n var sanitizedUrl = decodedUrl;\n if (!sanitizedUrl) {\n return constants_1.BLANK_URL;\n }\n if (isRelativeUrlWithoutProtocol(sanitizedUrl)) {\n return sanitizedUrl;\n }\n // Remove any leading whitespace before checking the URL scheme\n var trimmedUrl = sanitizedUrl.trimStart();\n var urlSchemeParseResults = trimmedUrl.match(constants_1.urlSchemeRegex);\n if (!urlSchemeParseResults) {\n return sanitizedUrl;\n }\n var urlScheme = urlSchemeParseResults[0].toLowerCase().trim();\n if (constants_1.invalidProtocolRegex.test(urlScheme)) {\n return constants_1.BLANK_URL;\n }\n var backSanitized = trimmedUrl.replace(/\\\\/g, \"/\");\n // Handle special cases for mailto: and custom deep-link protocols\n if (urlScheme === \"mailto:\" || urlScheme.includes(\"://\")) {\n return backSanitized;\n }\n // For http and https URLs, perform additional validation\n if (urlScheme === \"http:\" || urlScheme === \"https:\") {\n if (!isValidUrl(backSanitized)) {\n return constants_1.BLANK_URL;\n }\n var url_1 = new URL(backSanitized);\n url_1.protocol = url_1.protocol.toLowerCase();\n url_1.hostname = url_1.hostname.toLowerCase();\n return url_1.toString();\n }\n return backSanitized;\n}\nexports.sanitizeUrl = sanitizeUrl;\n"],"names":["dist","constants_1","require$$0","isRelativeUrlWithoutProtocol","url","decodeHtmlCharacters","str","removedNullByte","match","dec","isValidUrl","decodeURI","uri","sanitizeUrl","charsToDecode","decodedUrl","sanitizedUrl","trimmedUrl","urlSchemeParseResults","urlScheme","backSanitized","url_1"],"mappings":"sNACA,OAAO,eAAeA,EAAAA,UAAS,aAAc,CAAE,MAAO,GAAM,EAC5DA,EAAAA,UAAA,YAAsB,OACtB,IAAIC,EAAcC,EAAAA,UAAA,EAClB,SAASC,EAA6BC,EAAK,CACvC,OAAOH,EAAY,wBAAwB,QAAQG,EAAI,CAAC,CAAC,EAAI,EACjE,CACA,SAASC,EAAqBC,EAAK,CAC/B,IAAIC,EAAkBD,EAAI,QAAQL,EAAY,oBAAqB,EAAE,EACrE,OAAOM,EAAgB,QAAQN,EAAY,kBAAmB,SAAUO,EAAOC,EAAK,CAChF,OAAO,OAAO,aAAaA,CAAG,CACtC,CAAK,CACL,CACA,SAASC,EAAWN,EAAK,CACrB,OAAO,IAAI,SAASA,CAAG,CAC3B,CACA,SAASO,EAAUC,EAAK,CACpB,GAAI,CACA,OAAO,mBAAmBA,CAAG,CACrC,MACc,CAIN,OAAOA,CACf,CACA,CACA,SAASC,EAAYT,EAAK,CACtB,GAAI,CAACA,EACD,OAAOH,EAAY,UAEvB,IAAIa,EACAC,EAAaJ,EAAUP,EAAI,KAAI,CAAE,EACrC,GACIW,EAAaV,EAAqBU,CAAU,EACvC,QAAQd,EAAY,oBAAqB,EAAE,EAC3C,QAAQA,EAAY,oBAAqB,EAAE,EAC3C,QAAQA,EAAY,2BAA4B,EAAE,EAClD,KAAI,EACTc,EAAaJ,EAAUI,CAAU,EACjCD,EACIC,EAAW,MAAMd,EAAY,mBAAmB,GAC5Cc,EAAW,MAAMd,EAAY,iBAAiB,GAC9Cc,EAAW,MAAMd,EAAY,mBAAmB,GAChDc,EAAW,MAAMd,EAAY,0BAA0B,QAC1Da,GAAiBA,EAAc,OAAS,GACjD,IAAIE,EAAeD,EACnB,GAAI,CAACC,EACD,OAAOf,EAAY,UAEvB,GAAIE,EAA6Ba,CAAY,EACzC,OAAOA,EAGX,IAAIC,EAAaD,EAAa,UAAS,EACnCE,EAAwBD,EAAW,MAAMhB,EAAY,cAAc,EACvE,GAAI,CAACiB,EACD,OAAOF,EAEX,IAAIG,EAAYD,EAAsB,CAAC,EAAE,YAAW,EAAG,KAAI,EAC3D,GAAIjB,EAAY,qBAAqB,KAAKkB,CAAS,EAC/C,OAAOlB,EAAY,UAEvB,IAAImB,EAAgBH,EAAW,QAAQ,MAAO,GAAG,EAEjD,GAAIE,IAAc,WAAaA,EAAU,SAAS,KAAK,EACnD,OAAOC,EAGX,GAAID,IAAc,SAAWA,IAAc,SAAU,CACjD,GAAI,CAACT,EAAWU,CAAa,EACzB,OAAOnB,EAAY,UAEvB,IAAIoB,EAAQ,IAAI,IAAID,CAAa,EACjC,OAAAC,EAAM,SAAWA,EAAM,SAAS,YAAW,EAC3CA,EAAM,SAAWA,EAAM,SAAS,YAAW,EACpCA,EAAM,SAAQ,CAC7B,CACI,OAAOD,CACX,CACApB,OAAAA,EAAAA,UAAA,YAAsBa","x_google_ignoreList":[0]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("../../_virtual/index.
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("../../_virtual/index.cjs9.js");/*!
|
|
2
2
|
Copyright (c) 2018 Jed Watson.
|
|
3
3
|
Licensed under the MIT License (MIT), see
|
|
4
4
|
http://jedwatson.github.io/classnames
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w=require("../../comma-separated-tokens/index.cjs.js"),u=require("../../devlop/lib/default.cjs.js"),f=require("../../property-information/index.cjs.js"),C=require("../../space-separated-tokens/index.cjs.js"),S=require("../../../_virtual/index.
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w=require("../../comma-separated-tokens/index.cjs.js"),u=require("../../devlop/lib/default.cjs.js"),f=require("../../property-information/index.cjs.js"),C=require("../../space-separated-tokens/index.cjs.js"),S=require("../../../_virtual/index.cjs6.js"),N=require("../../hast-util-whitespace/lib/index.cjs.js"),x=require("../../estree-util-is-identifier-name/lib/index.cjs.js"),h=require("../../vfile-message/lib/index.cjs.js"),j=require("../../property-information/lib/find.cjs.js"),A=require("../../property-information/lib/hast-to-react.cjs.js"),T=require("../../unist-util-position/lib/index.cjs.js"),m={}.hasOwnProperty,F=new Map,P=/[A-Z]/g,q=new Set(["table","tbody","thead","tfoot","tr"]),J=new Set(["td","th"]),g="https://github.com/syntax-tree/hast-util-to-jsx-runtime";function M(t,e){if(!e||e.Fragment===void 0)throw new TypeError("Expected `Fragment` in options");const r=e.filePath||void 0;let n;if(e.development){if(typeof e.jsxDEV!="function")throw new TypeError("Expected `jsxDEV` in options when `development: true`");n=K(r,e.jsxDEV)}else{if(typeof e.jsx!="function")throw new TypeError("Expected `jsx` in production options");if(typeof e.jsxs!="function")throw new TypeError("Expected `jsxs` in production options");n=k(r,e.jsx,e.jsxs)}const s={Fragment:e.Fragment,ancestors:[],components:e.components||{},create:n,elementAttributeNameCase:e.elementAttributeNameCase||"react",evaluater:e.createEvaluater?e.createEvaluater():void 0,filePath:r,ignoreInvalidStyle:e.ignoreInvalidStyle||!1,passKeys:e.passKeys!==!1,passNode:e.passNode||!1,schema:e.space==="svg"?f.svg:f.html,stylePropertyNameCase:e.stylePropertyNameCase||"dom",tableCellAlignToStyle:e.tableCellAlignToStyle!==!1},i=E(s,t,void 0);return i&&typeof i!="string"?i:s.create(t,s.Fragment,{children:i||void 0},void 0)}function E(t,e,r){if(e.type==="element")return I(t,e,r);if(e.type==="mdxFlowExpression"||e.type==="mdxTextExpression")return L(t,e);if(e.type==="mdxJsxFlowElement"||e.type==="mdxJsxTextElement")return V(t,e,r);if(e.type==="mdxjsEsm")return $(t,e);if(e.type==="root")return D(t,e,r);if(e.type==="text")return O(t,e)}function I(t,e,r){const n=t.schema;let s=n;e.tagName.toLowerCase()==="svg"&&n.space==="html"&&(s=f.svg,t.schema=s),t.ancestors.push(e);const i=b(t,e.tagName,!1),a=R(t,e);let o=d(t,e);return q.has(e.tagName)&&(o=o.filter(function(l){return typeof l=="string"?!N.whitespace(l):!0})),v(t,a,i,e),y(a,o),t.ancestors.pop(),t.schema=n,t.create(e,i,a,r)}function L(t,e){if(e.data&&e.data.estree&&t.evaluater){const n=e.data.estree.body[0];return u.ok(n.type==="ExpressionStatement"),t.evaluater.evaluateExpression(n.expression)}p(t,e.position)}function $(t,e){if(e.data&&e.data.estree&&t.evaluater)return t.evaluater.evaluateProgram(e.data.estree);p(t,e.position)}function V(t,e,r){const n=t.schema;let s=n;e.name==="svg"&&n.space==="html"&&(s=f.svg,t.schema=s),t.ancestors.push(e);const i=e.name===null?t.Fragment:b(t,e.name,!0),a=_(t,e),o=d(t,e);return v(t,a,i,e),y(a,o),t.ancestors.pop(),t.schema=n,t.create(e,i,a,r)}function D(t,e,r){const n={};return y(n,d(t,e)),t.create(e,t.Fragment,n,r)}function O(t,e){return e.value}function v(t,e,r,n){typeof r!="string"&&r!==t.Fragment&&t.passNode&&(e.node=n)}function y(t,e){if(e.length>0){const r=e.length>1?e:e[0];r&&(t.children=r)}}function k(t,e,r){return n;function n(s,i,a,o){const c=Array.isArray(a.children)?r:e;return o?c(i,a,o):c(i,a)}}function K(t,e){return r;function r(n,s,i,a){const o=Array.isArray(i.children),l=T.pointStart(n);return e(s,i,a,o,{columnNumber:l?l.column-1:void 0,fileName:t,lineNumber:l?l.line:void 0},void 0)}}function R(t,e){const r={};let n,s;for(s in e.properties)if(s!=="children"&&m.call(e.properties,s)){const i=B(t,s,e.properties[s]);if(i){const[a,o]=i;t.tableCellAlignToStyle&&a==="align"&&typeof o=="string"&&J.has(e.tagName)?n=o:r[a]=o}}if(n){const i=r.style||(r.style={});i[t.stylePropertyNameCase==="css"?"text-align":"textAlign"]=n}return r}function _(t,e){const r={};for(const n of e.attributes)if(n.type==="mdxJsxExpressionAttribute")if(n.data&&n.data.estree&&t.evaluater){const i=n.data.estree.body[0];u.ok(i.type==="ExpressionStatement");const a=i.expression;u.ok(a.type==="ObjectExpression");const o=a.properties[0];u.ok(o.type==="SpreadElement"),Object.assign(r,t.evaluater.evaluateExpression(o.argument))}else p(t,e.position);else{const s=n.name;let i;if(n.value&&typeof n.value=="object")if(n.value.data&&n.value.data.estree&&t.evaluater){const o=n.value.data.estree.body[0];u.ok(o.type==="ExpressionStatement"),i=t.evaluater.evaluateExpression(o.expression)}else p(t,e.position);else i=n.value===null?!0:n.value;r[s]=i}return r}function d(t,e){const r=[];let n=-1;const s=t.passKeys?new Map:F;for(;++n<e.children.length;){const i=e.children[n];let a;if(t.passKeys){const l=i.type==="element"?i.tagName:i.type==="mdxJsxFlowElement"||i.type==="mdxJsxTextElement"?i.name:void 0;if(l){const c=s.get(l)||0;a=l+"-"+c,s.set(l,c+1)}}const o=E(t,i,a);o!==void 0&&r.push(o)}return r}function B(t,e,r){const n=j.find(t.schema,e);if(!(r==null||typeof r=="number"&&Number.isNaN(r))){if(Array.isArray(r)&&(r=n.commaSeparated?w.stringify(r):C.stringify(r)),n.property==="style"){let s=typeof r=="object"?r:z(t,String(r));return t.stylePropertyNameCase==="css"&&(s=X(s)),["style",s]}return[t.elementAttributeNameCase==="react"&&n.space?A.hastToReact[n.property]||n.property:n.attribute,r]}}function z(t,e){try{return S.default(e,{reactCompat:!0})}catch(r){if(t.ignoreInvalidStyle)return{};const n=r,s=new h.VFileMessage("Cannot parse `style` attribute",{ancestors:t.ancestors,cause:n,ruleId:"style",source:"hast-util-to-jsx-runtime"});throw s.file=t.filePath||void 0,s.url=g+"#cannot-parse-style-attribute",s}}function b(t,e,r){let n;if(!r)n={type:"Literal",value:e};else if(e.includes(".")){const s=e.split(".");let i=-1,a;for(;++i<s.length;){const o=x.name(s[i])?{type:"Identifier",name:s[i]}:{type:"Literal",value:s[i]};a=a?{type:"MemberExpression",object:a,property:o,computed:!!(i&&o.type==="Literal"),optional:!1}:o}n=a}else n=x.name(e)&&!/^[a-z]/.test(e)?{type:"Identifier",name:e}:{type:"Literal",value:e};if(n.type==="Literal"){const s=n.value;return m.call(t.components,s)?t.components[s]:s}if(t.evaluater)return t.evaluater.evaluateExpression(n);p(t)}function p(t,e){const r=new h.VFileMessage("Cannot handle MDX estrees without `createEvaluater`",{ancestors:t.ancestors,place:e,ruleId:"mdx-estree",source:"hast-util-to-jsx-runtime"});throw r.file=t.filePath||void 0,r.url=g+"#cannot-handle-mdx-estrees-without-createevaluater",r}function X(t){const e={};let r;for(r in t)m.call(t,r)&&(e[Z(r)]=t[r]);return e}function Z(t){let e=t.replace(P,G);return e.slice(0,3)==="ms-"&&(e="-"+e),e}function G(t){return"-"+t.toLowerCase()}exports.toJsxRuntime=M;
|
|
2
2
|
//# sourceMappingURL=index.cjs.js.map
|
|
@@ -2,7 +2,7 @@ import { stringify as w } from "../../comma-separated-tokens/index.es.js";
|
|
|
2
2
|
import { ok as u } from "../../devlop/lib/default.es.js";
|
|
3
3
|
import { svg as m, html as C } from "../../property-information/index.es.js";
|
|
4
4
|
import { stringify as N } from "../../space-separated-tokens/index.es.js";
|
|
5
|
-
import S from "../../../_virtual/index.
|
|
5
|
+
import S from "../../../_virtual/index.es6.js";
|
|
6
6
|
import { whitespace as j } from "../../hast-util-whitespace/lib/index.es.js";
|
|
7
7
|
import { name as x } from "../../estree-util-is-identifier-name/lib/index.es.js";
|
|
8
8
|
import { VFileMessage as h } from "../../vfile-message/lib/index.es.js";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("../../../_virtual/index.
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("../../../_virtual/index.cjs8.js"),c=require("../../inline-style-parser/index.cjs.js");var o;function v(){if(o)return r.__exports;o=1;var f=r.__exports&&r.__exports.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(r.__exports,"__esModule",{value:!0}),r.__exports.default=a;var s=f(c.__require());function a(e,n){var t=null;if(!e||typeof e!="string")return t;var p=(0,s.default)(e),l=typeof n=="function";return p.forEach(function(u){if(u.type==="declaration"){var i=u.property,_=u.value;l?n(i,_,u):_&&(t=t||{},t[i]=_)}}),t}return r.__exports}exports.__require=v;
|
|
2
2
|
//# sourceMappingURL=index.cjs.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const P=require("../../bail/index.cjs.js"),w=require("../../../_virtual/index.
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const P=require("../../bail/index.cjs.js"),w=require("../../../_virtual/index.cjs5.js"),z=require("../../is-plain-obj/index.cjs.js"),C=require("./callable-instance.cjs.js"),S=require("../../trough/lib/index.cjs.js"),A=require("../../vfile/lib/index.cjs.js"),F={}.hasOwnProperty;class m extends C.CallableInstance{constructor(){super("copy"),this.Compiler=void 0,this.Parser=void 0,this.attachers=[],this.compiler=void 0,this.freezeIndex=-1,this.frozen=void 0,this.namespace={},this.parser=void 0,this.transformers=S.trough()}copy(){const e=new m;let n=-1;for(;++n<this.attachers.length;){const t=this.attachers[n];e.use(...t)}return e.data(w.default(!0,{},this.namespace)),e}data(e,n){return typeof e=="string"?arguments.length===2?(x("data",this.frozen),this.namespace[e]=n,this):F.call(this.namespace,e)&&this.namespace[e]||void 0:e?(x("data",this.frozen),this.namespace=e,this):this.namespace}freeze(){if(this.frozen)return this;const e=this;for(;++this.freezeIndex<this.attachers.length;){const[n,...t]=this.attachers[this.freezeIndex];if(t[0]===!1)continue;t[0]===!0&&(t[0]=void 0);const i=n.call(e,...t);typeof i=="function"&&this.transformers.use(i)}return this.frozen=!0,this.freezeIndex=Number.POSITIVE_INFINITY,this}parse(e){this.freeze();const n=y(e),t=this.parser||this.Parser;return g("parse",t),t(String(n),n)}process(e,n){const t=this;return this.freeze(),g("process",this.parser||this.Parser),b("process",this.compiler||this.Compiler),n?i(void 0,n):new Promise(i);function i(a,h){const u=y(e),l=t.parse(u);t.run(l,u,function(o,c,f){if(o||!c||!f)return s(o);const p=c,d=t.stringify(p,f);D(d)?f.value=d:f.result=d,s(o,f)});function s(o,c){o||!c?h(o):a?a(c):n(void 0,c)}}}processSync(e){let n=!1,t;return this.freeze(),g("processSync",this.parser||this.Parser),b("processSync",this.compiler||this.Compiler),this.process(e,i),T("processSync","process",n),t;function i(a,h){n=!0,P.bail(a),t=h}}run(e,n,t){I(e),this.freeze();const i=this.transformers;return!t&&typeof n=="function"&&(t=n,n=void 0),t?a(void 0,t):new Promise(a);function a(h,u){const l=y(n);i.run(e,l,s);function s(o,c,f){const p=c||e;o?u(o):h?h(p):t(void 0,p,f)}}}runSync(e,n){let t=!1,i;return this.run(e,n,a),T("runSync","run",t),i;function a(h,u){P.bail(h),i=u,t=!0}}stringify(e,n){this.freeze();const t=y(n),i=this.compiler||this.Compiler;return b("stringify",i),I(e),i(e,t)}use(e,...n){const t=this.attachers,i=this.namespace;if(x("use",this.frozen),e!=null)if(typeof e=="function")l(e,n);else if(typeof e=="object")Array.isArray(e)?u(e):h(e);else throw new TypeError("Expected usable value, not `"+e+"`");return this;function a(s){if(typeof s=="function")l(s,[]);else if(typeof s=="object")if(Array.isArray(s)){const[o,...c]=s;l(o,c)}else h(s);else throw new TypeError("Expected usable value, not `"+s+"`")}function h(s){if(!("plugins"in s)&&!("settings"in s))throw new Error("Expected usable value but received an empty preset, which is probably a mistake: presets typically come with `plugins` and sometimes with `settings`, but this has neither");u(s.plugins),s.settings&&(i.settings=w.default(!0,i.settings,s.settings))}function u(s){let o=-1;if(s!=null)if(Array.isArray(s))for(;++o<s.length;){const c=s[o];a(c)}else throw new TypeError("Expected a list of plugins, not `"+s+"`")}function l(s,o){let c=-1,f=-1;for(;++c<t.length;)if(t[c][0]===s){f=c;break}if(f===-1)t.push([s,...o]);else if(o.length>0){let[p,...d]=o;const E=t[f][1];z.default(E)&&z.default(p)&&(p=w.default(!0,E,p)),t[f]=[s,p,...d]}}}}const q=new m().freeze();function g(r,e){if(typeof e!="function")throw new TypeError("Cannot `"+r+"` without `parser`")}function b(r,e){if(typeof e!="function")throw new TypeError("Cannot `"+r+"` without `compiler`")}function x(r,e){if(e)throw new Error("Cannot call `"+r+"` on a frozen processor.\nCreate a new processor first, by calling it: use `processor()` instead of `processor`.")}function I(r){if(!z.default(r)||typeof r.type!="string")throw new TypeError("Expected node, got `"+r+"`")}function T(r,e,n){if(!n)throw new Error("`"+r+"` finished async. Use `"+e+"` instead")}function y(r){return j(r)?r:new A.VFile(r)}function j(r){return!!(r&&typeof r=="object"&&"message"in r&&"messages"in r)}function D(r){return typeof r=="string"||L(r)}function L(r){return!!(r&&typeof r=="object"&&"byteLength"in r&&"byteOffset"in r)}exports.Processor=m;exports.unified=q;
|
|
2
2
|
//# sourceMappingURL=index.cjs.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { bail as P } from "../../bail/index.es.js";
|
|
2
|
-
import y from "../../../_virtual/index.
|
|
2
|
+
import y from "../../../_virtual/index.es5.js";
|
|
3
3
|
import z from "../../is-plain-obj/index.es.js";
|
|
4
4
|
import { CallableInstance as C } from "./callable-instance.es.js";
|
|
5
5
|
import { trough as A } from "../../trough/lib/index.es.js";
|