markdown-flow-ui 0.1.98 → 0.1.99-beta.1

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.
Files changed (69) hide show
  1. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/@braintree_sanitize-url@7.1.1/node_modules/@braintree/sanitize-url/dist/index.cjs.js +1 -1
  2. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/@braintree_sanitize-url@7.1.1/node_modules/@braintree/sanitize-url/dist/index.cjs.js.map +1 -1
  3. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/@braintree_sanitize-url@7.1.1/node_modules/@braintree/sanitize-url/dist/index.es.js +1 -1
  4. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/classnames@2.5.1/node_modules/classnames/index.cjs.js +1 -1
  5. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/classnames@2.5.1/node_modules/classnames/index.es.js +1 -1
  6. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/c4Diagram-YG6GDRKO.cjs.js +1 -1
  7. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/c4Diagram-YG6GDRKO.cjs.js.map +1 -1
  8. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/c4Diagram-YG6GDRKO.es.js +1 -1
  9. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/chunk-S3R3BYOJ.cjs.js +1 -1
  10. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/chunk-S3R3BYOJ.cjs.js.map +1 -1
  11. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/chunk-S3R3BYOJ.es.js +1 -1
  12. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/chunk-TZMSLE5B.cjs.js +1 -1
  13. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/chunk-TZMSLE5B.cjs.js.map +1 -1
  14. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/chunk-TZMSLE5B.es.js +1 -1
  15. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/ganttDiagram-LVOFAZNH.cjs.js +1 -1
  16. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/ganttDiagram-LVOFAZNH.cjs.js.map +1 -1
  17. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/ganttDiagram-LVOFAZNH.es.js +1 -1
  18. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/sequenceDiagram-WL72ISMW.cjs.js +1 -1
  19. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/sequenceDiagram-WL72ISMW.cjs.js.map +1 -1
  20. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/sequenceDiagram-WL72ISMW.es.js +1 -1
  21. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-input@1.8.0_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-input/es/BaseInput.cjs.js +1 -1
  22. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-input@1.8.0_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-input/es/BaseInput.es.js +1 -1
  23. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-textarea@1.10.2_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-textarea/es/ResizableTextArea.cjs.js +1 -1
  24. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-textarea@1.10.2_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-textarea/es/ResizableTextArea.es.js +1 -1
  25. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-textarea@1.10.2_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-textarea/es/TextArea.cjs.js +1 -1
  26. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-textarea@1.10.2_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-textarea/es/TextArea.es.js +1 -1
  27. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-textarea@1.10.2_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-textarea/es/index.cjs.js +1 -1
  28. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-textarea@1.10.2_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-textarea/es/index.es.js +1 -1
  29. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-util@5.44.4_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-util/es/ref.cjs.js +1 -1
  30. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-util@5.44.4_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-util/es/ref.cjs.js.map +1 -1
  31. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-util@5.44.4_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-util/es/ref.es.js +1 -1
  32. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/react-is@18.3.1/node_modules/react-is/index.cjs.js +1 -1
  33. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/react-is@18.3.1/node_modules/react-is/index.es.js +1 -1
  34. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-flow@0.1.6/node_modules/remark-flow/dist/remark-custom-variable.cjs.js +1 -1
  35. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-flow@0.1.6/node_modules/remark-flow/dist/remark-custom-variable.es.js +1 -1
  36. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-flow@0.1.6/node_modules/remark-flow/dist/remark-interaction.cjs.js +1 -1
  37. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-flow@0.1.6/node_modules/remark-flow/dist/remark-interaction.es.js +1 -1
  38. package/dist/_virtual/index.cjs10.js +1 -1
  39. package/dist/_virtual/index.cjs11.js +1 -1
  40. package/dist/_virtual/index.cjs12.js +1 -1
  41. package/dist/_virtual/index.cjs3.js +1 -1
  42. package/dist/_virtual/index.cjs4.js +1 -1
  43. package/dist/_virtual/index.cjs8.js +1 -1
  44. package/dist/_virtual/index.cjs9.js +1 -1
  45. package/dist/_virtual/index.es10.js +3 -2
  46. package/dist/_virtual/index.es10.js.map +1 -1
  47. package/dist/_virtual/index.es11.js +2 -3
  48. package/dist/_virtual/index.es11.js.map +1 -1
  49. package/dist/_virtual/index.es12.js +2 -2
  50. package/dist/_virtual/index.es3.js +5 -4
  51. package/dist/_virtual/index.es3.js.map +1 -1
  52. package/dist/_virtual/index.es4.js +4 -5
  53. package/dist/_virtual/index.es4.js.map +1 -1
  54. package/dist/_virtual/index.es8.js +2 -3
  55. package/dist/_virtual/index.es8.js.map +1 -1
  56. package/dist/_virtual/index.es9.js +3 -2
  57. package/dist/_virtual/index.es9.js.map +1 -1
  58. package/dist/components/ContentRender/IframeSandbox.cjs.js +4 -4
  59. package/dist/components/ContentRender/IframeSandbox.cjs.js.map +1 -1
  60. package/dist/components/ContentRender/IframeSandbox.es.js +153 -138
  61. package/dist/components/ContentRender/IframeSandbox.es.js.map +1 -1
  62. package/dist/components/ContentRender/SandboxApp.cjs.js +4 -5
  63. package/dist/components/ContentRender/SandboxApp.cjs.js.map +1 -1
  64. package/dist/components/ContentRender/SandboxApp.es.js +46 -47
  65. package/dist/components/ContentRender/SandboxApp.es.js.map +1 -1
  66. package/dist/components/ui/inputGroup/textarea.cjs.js +1 -1
  67. package/dist/components/ui/inputGroup/textarea.es.js +1 -1
  68. package/dist/markdown-flow-ui-lib.css +1 -1
  69. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"IframeSandbox.cjs.js","sources":["../../../src/components/ContentRender/IframeSandbox.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport { createRoot, Root } from \"react-dom/client\";\nimport SandboxApp from \"./SandboxApp\";\nimport { splitContentSegments } from \"./utils/split-content\";\nimport ContentRender from \"./ContentRender\";\n// Lazy-load iframe vendor libraries and inject them into the sandbox document.\nconst loadBlackboardVendor = () =>\n import(\"./blackboard-vendor\").then((m) => m.injectBlackboardLibraries);\n\nconst COMPLETE_IMAGE_TAG_PATTERN = /<img\\b[^>]*>/i;\nconst POST_IMAGE_STREAM_DEBOUNCE_MS = 180;\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}\n\nconst normalizeTailwindHeightTokens = (className: string) =>\n className\n .split(/\\s+/)\n .filter(Boolean)\n .map((token) => token.split(\":\").pop() || token);\n\nconst parseViewportHeightCss = (value: string) => {\n const normalized = value.trim().toLowerCase();\n if (!normalized) return null;\n const matched = normalized.match(/^([0-9.]+)(vh|dvh|svh|lvh)$/i);\n if (!matched) return null;\n return `${matched[1]}${matched[2].toLowerCase()}`;\n};\n\nconst extractViewportHeightFromTailwindClass = (className: string) => {\n if (!className.trim()) return null;\n const normalizedTokens = normalizeTailwindHeightTokens(className);\n if (\n normalizedTokens.includes(\"h-screen\") ||\n normalizedTokens.includes(\"h-dvh\")\n ) {\n return \"100dvh\";\n }\n if (normalizedTokens.includes(\"h-svh\")) {\n return \"100svh\";\n }\n if (normalizedTokens.includes(\"h-lvh\")) {\n return \"100lvh\";\n }\n const arbitraryToken = normalizedTokens.find((token) =>\n /^h-\\[[0-9.]+(vh|dvh|svh|lvh)\\]$/i.test(token)\n );\n if (!arbitraryToken) return null;\n const matched = arbitraryToken.match(/^h-\\[([0-9.]+)(vh|dvh|svh|lvh)\\]$/i);\n if (!matched) return null;\n return `${matched[1]}${matched[2].toLowerCase()}`;\n};\n\nconst IframeSandbox: React.FC<IframeSandboxProps> = ({\n content,\n type,\n className,\n loadingText,\n styleLoadingText,\n scriptLoadingText,\n fullScreenButtonText,\n hideFullScreen = false,\n mode = \"content\",\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const rootRef = useRef<Root | null>(null);\n const docRef = useRef<Document | null>(null);\n const updateHeightRef = useRef<() => void>(() => {});\n const [, setHeight] = useState(480);\n const [resetToken, setResetToken] = useState(0);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const isBlackboardMode = mode === \"blackboard\";\n const prevHtmlRef = useRef<string>(\"\");\n const htmlContent = React.useMemo(() => {\n const segments = splitContentSegments(content);\n // console.log('segments=====', segments);\n const sandboxSegments = segments.filter((seg) => seg.type === \"sandbox\");\n const sandboxContent =\n mode === \"blackboard\"\n ? sandboxSegments[sandboxSegments.length - 1]?.value || \"\"\n : sandboxSegments.map((seg) => seg.value).join(\"\\n\");\n return sandboxContent || \"\";\n }, [content, mode]);\n const [renderHtmlContent, setRenderHtmlContent] = useState(htmlContent);\n const prevIncomingHtmlRef = useRef(htmlContent);\n const pendingHtmlRef = useRef(htmlContent);\n const deferRenderTimerRef = useRef<number | null>(null);\n\n const clearDeferredRenderTimer = () => {\n if (deferRenderTimerRef.current === null) return;\n window.clearTimeout(deferRenderTimerRef.current);\n deferRenderTimerRef.current = null;\n };\n\n useEffect(\n () => () => {\n clearDeferredRenderTimer();\n },\n []\n );\n\n useEffect(() => {\n const prevIncomingHtml = prevIncomingHtmlRef.current;\n prevIncomingHtmlRef.current = htmlContent;\n\n const isAppendOnlyStream =\n !!prevIncomingHtml &&\n htmlContent.length > prevIncomingHtml.length &&\n htmlContent.startsWith(prevIncomingHtml);\n const containsCompleteImage = COMPLETE_IMAGE_TAG_PATTERN.test(htmlContent);\n const shouldDeferRender = isAppendOnlyStream && containsCompleteImage;\n\n if (!shouldDeferRender) {\n clearDeferredRenderTimer();\n pendingHtmlRef.current = htmlContent;\n setRenderHtmlContent(htmlContent);\n return;\n }\n\n pendingHtmlRef.current = htmlContent;\n clearDeferredRenderTimer();\n deferRenderTimerRef.current = window.setTimeout(() => {\n setRenderHtmlContent(pendingHtmlRef.current);\n deferRenderTimerRef.current = null;\n }, POST_IMAGE_STREAM_DEBOUNCE_MS);\n }, [htmlContent]);\n\n const rootViewportHeightCss = React.useMemo(() => {\n const normalized = renderHtmlContent.trim();\n if (!normalized) return null;\n const rootMatch = normalized.match(/^<([a-zA-Z][\\w:-]*)(\\s[^>]*?)?>/);\n if (!rootMatch) return null;\n const attrs = rootMatch[2] || \"\";\n const heightAttrMatch = attrs.match(/\\bheight\\s*=\\s*[\"']([^\"']+)[\"']/i);\n if (heightAttrMatch) {\n const explicitHeightCss = parseViewportHeightCss(heightAttrMatch[1]);\n if (explicitHeightCss) return explicitHeightCss;\n }\n const styleAttrMatch = attrs.match(/\\bstyle\\s*=\\s*[\"']([^\"']+)[\"']/i)?.[1];\n const styleHeightMatch = styleAttrMatch?.match(\n /\\bheight\\s*:\\s*([^;]+)/i\n )?.[1];\n if (styleHeightMatch) {\n const styleHeightCss = parseViewportHeightCss(styleHeightMatch);\n if (styleHeightCss) return styleHeightCss;\n }\n const classAttrMatch = attrs.match(/\\bclass\\s*=\\s*[\"']([^\"']+)[\"']/i)?.[1];\n if (!classAttrMatch) return null;\n return extractViewportHeightFromTailwindClass(classAttrMatch);\n }, [renderHtmlContent]);\n const hasRootVhHeight = Boolean(rootViewportHeightCss);\n useEffect(() => {\n if (mode !== \"blackboard\") {\n prevHtmlRef.current = htmlContent;\n return;\n }\n const prev = prevHtmlRef.current;\n const isContinuation = prev && htmlContent.startsWith(prev);\n if (!isContinuation && prev) {\n setResetToken((token) => token + 1);\n }\n prevHtmlRef.current = htmlContent;\n }, [htmlContent, mode]);\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 html, body, #root { width: 100%; 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 docRef.current = doc;\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\n const parseExplicitHeight = (\n value: string,\n parentViewportHeight: number\n ) => {\n const normalized = value.trim().toLowerCase();\n if (!normalized) return null;\n const numeric = Number.parseFloat(normalized);\n if (Number.isNaN(numeric)) return null;\n if (/(dvh|svh|lvh|vh)$/i.test(normalized)) {\n return (numeric / 100) * parentViewportHeight;\n }\n if (normalized.endsWith(\"px\") || /^[0-9.]+$/.test(normalized)) {\n return numeric;\n }\n return null;\n };\n const parseTailwindHeightClass = (\n className: string,\n parentViewportHeight: number\n ) => {\n if (!className.trim()) return null;\n const viewportHeightCss =\n extractViewportHeightFromTailwindClass(className);\n if (viewportHeightCss) {\n return parseExplicitHeight(viewportHeightCss, parentViewportHeight);\n }\n const normalizedTokens = normalizeTailwindHeightTokens(className);\n const arbitraryToken = normalizedTokens.find((token) =>\n /^h-\\[[0-9.]+px\\]$/i.test(token)\n );\n if (!arbitraryToken) return null;\n const matched = arbitraryToken.match(/^h-\\[([0-9.]+)px\\]$/i);\n if (!matched) return null;\n const numeric = Number.parseFloat(matched[1]);\n if (Number.isNaN(numeric)) return null;\n return numeric;\n };\n\n const resolveExplicitHeight = () => {\n if (!iframeRef.current || !doc.body) return null;\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 elements = Array.from(container.children) as HTMLElement[];\n if (elements.length !== 1) return null;\n const target = elements[0];\n const heightValue = target.style.height || target.getAttribute(\"height\");\n const parentViewportHeight =\n iframeRef.current.ownerDocument?.documentElement?.clientHeight ||\n window.innerHeight;\n const parsed = heightValue\n ? parseExplicitHeight(heightValue, parentViewportHeight)\n : null;\n if (parsed !== null) {\n return Math.ceil(parsed);\n }\n const classHeight = parseTailwindHeightClass(\n target.getAttribute(\"class\") || \"\",\n parentViewportHeight\n );\n return classHeight !== null ? Math.ceil(classHeight) : null;\n };\n\n const updateHeight = () => {\n if (!iframeRef.current || !doc.body) return;\n const bodyRect = doc.body.getBoundingClientRect();\n const htmlRect = doc.documentElement?.getBoundingClientRect();\n const bodyHeight = bodyRect.height;\n const htmlHeight = htmlRect?.height || 0;\n const contentHeight = Math.max(bodyHeight, htmlHeight);\n const explicitHeight = resolveExplicitHeight();\n const nextHeight = Math.max(\n 200,\n explicitHeight ?? Math.ceil(contentHeight)\n );\n setHeight(nextHeight);\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 // Inject Tailwind/DaisyUI/GSAP into iframe for all sandbox modes.\n // Dynamic import keeps ~3.3 MB of vendor libs out of the main bundle.\n // Tailwind's MutationObserver ensures styles apply even if content renders first.\n loadBlackboardVendor()\n .then((inject) => {\n if (isDestroyed) return;\n inject(doc);\n scheduleHeightUpdate();\n })\n .catch(() => {\n if (isDestroyed) return;\n scheduleHeightUpdate();\n });\n\n const resizeObserver = new ResizeObserver(() => updateHeight());\n resizeObserver.observe(doc.body);\n if (rootEl) {\n resizeObserver.observe(rootEl);\n }\n\n return () => {\n isDestroyed = true;\n resizeObserver.disconnect();\n // Defer unmount to avoid React warning when parent is mid-render\n setTimeout(() => {\n root.unmount();\n rootRef.current = null;\n docRef.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 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 loadingText={loadingText}\n styleLoadingText={styleLoadingText}\n scriptLoadingText={scriptLoadingText}\n fullScreenButtonText={fullScreenButtonText}\n hideFullScreen={hideFullScreen}\n resetToken={resetToken}\n hasRootVhHeight={hasRootVhHeight}\n mode={mode}\n />\n );\n requestAnimationFrame(() => updateHeightRef.current?.());\n }, [\n renderHtmlContent,\n loadingText,\n styleLoadingText,\n scriptLoadingText,\n fullScreenButtonText,\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 : \"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 >\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 <ContentRender content={content} />\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: \"100%\",\n margin: \"auto\",\n }}\n />\n )}\n </div>\n );\n};\n\nexport default IframeSandbox;\n"],"names":["loadBlackboardVendor","m","COMPLETE_IMAGE_TAG_PATTERN","POST_IMAGE_STREAM_DEBOUNCE_MS","normalizeTailwindHeightTokens","className","token","parseViewportHeightCss","value","normalized","matched","extractViewportHeightFromTailwindClass","normalizedTokens","arbitraryToken","IframeSandbox","content","type","loadingText","styleLoadingText","scriptLoadingText","fullScreenButtonText","hideFullScreen","mode","containerRef","useRef","iframeRef","rootRef","docRef","updateHeightRef","setHeight","useState","resetToken","setResetToken","isFullscreen","setIsFullscreen","isBlackboardMode","prevHtmlRef","htmlContent","React","sandboxSegments","splitContentSegments","seg","renderHtmlContent","setRenderHtmlContent","prevIncomingHtmlRef","pendingHtmlRef","deferRenderTimerRef","clearDeferredRenderTimer","useEffect","prevIncomingHtml","isAppendOnlyStream","containsCompleteImage","hasRootVhHeight","rootMatch","attrs","heightAttrMatch","explicitHeightCss","styleHeightMatch","styleHeightCss","classAttrMatch","prev","iframe","doc","rootEl","root","createRoot","isDestroyed","parseExplicitHeight","parentViewportHeight","numeric","parseTailwindHeightClass","viewportHeightCss","resolveExplicitHeight","container","elements","target","heightValue","parsed","classHeight","updateHeight","bodyRect","htmlRect","bodyHeight","htmlHeight","contentHeight","explicitHeight","nextHeight","scheduleHeightUpdate","inject","resizeObserver","onFullscreenChange","toggleFullscreen","jsx","SandboxApp","containerClassName","jsxs","ContentRender"],"mappings":"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"}
1
+ {"version":3,"file":"IframeSandbox.cjs.js","sources":["../../../src/components/ContentRender/IframeSandbox.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport { createRoot, Root } from \"react-dom/client\";\nimport SandboxApp from \"./SandboxApp\";\nimport { splitContentSegments } from \"./utils/split-content\";\nimport ContentRender from \"./ContentRender\";\n// Lazy-load iframe vendor libraries and inject them into the sandbox document.\nconst loadBlackboardVendor = () =>\n import(\"./blackboard-vendor\").then((m) => m.injectBlackboardLibraries);\n\nconst COMPLETE_IMAGE_TAG_PATTERN = /<img\\b[^>]*>/i;\nconst POST_IMAGE_STREAM_DEBOUNCE_MS = 180;\nconst SANDBOX_INTERACTION_MESSAGE_SOURCE = \"markdown-flow-ui:sandbox\";\nconst SANDBOX_INTERACTION_MESSAGE_TYPE = \"interaction\";\nconst SANDBOX_INTERACTION_THROTTLE_MS = 240;\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}\n\nconst normalizeTailwindHeightTokens = (className: string) =>\n className\n .split(/\\s+/)\n .filter(Boolean)\n .map((token) => token.split(\":\").pop() || token);\n\nconst parseViewportHeightCss = (value: string) => {\n const normalized = value.trim().toLowerCase();\n if (!normalized) return null;\n const matched = normalized.match(/^([0-9.]+)(vh|dvh|svh|lvh)$/i);\n if (!matched) return null;\n return `${matched[1]}${matched[2].toLowerCase()}`;\n};\n\nconst extractViewportHeightFromTailwindClass = (className: string) => {\n if (!className.trim()) return null;\n const normalizedTokens = normalizeTailwindHeightTokens(className);\n if (\n normalizedTokens.includes(\"h-screen\") ||\n normalizedTokens.includes(\"h-dvh\")\n ) {\n return \"100dvh\";\n }\n if (normalizedTokens.includes(\"h-svh\")) {\n return \"100svh\";\n }\n if (normalizedTokens.includes(\"h-lvh\")) {\n return \"100lvh\";\n }\n const arbitraryToken = normalizedTokens.find((token) =>\n /^h-\\[[0-9.]+(vh|dvh|svh|lvh)\\]$/i.test(token)\n );\n if (!arbitraryToken) return null;\n const matched = arbitraryToken.match(/^h-\\[([0-9.]+)(vh|dvh|svh|lvh)\\]$/i);\n if (!matched) return null;\n return `${matched[1]}${matched[2].toLowerCase()}`;\n};\n\nconst IframeSandbox: React.FC<IframeSandboxProps> = ({\n content,\n type,\n className,\n loadingText,\n styleLoadingText,\n scriptLoadingText,\n fullScreenButtonText,\n hideFullScreen = false,\n mode = \"content\",\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const rootRef = useRef<Root | null>(null);\n const docRef = useRef<Document | null>(null);\n const updateHeightRef = useRef<() => void>(() => {});\n const [, setHeight] = useState(480);\n const [resetToken, setResetToken] = useState(0);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const isBlackboardMode = mode === \"blackboard\";\n const prevHtmlRef = useRef<string>(\"\");\n const htmlContent = React.useMemo(() => {\n const segments = splitContentSegments(content);\n // console.log('segments=====', segments);\n const sandboxSegments = segments.filter((seg) => seg.type === \"sandbox\");\n const sandboxContent =\n mode === \"blackboard\"\n ? sandboxSegments[sandboxSegments.length - 1]?.value || \"\"\n : sandboxSegments.map((seg) => seg.value).join(\"\\n\");\n return sandboxContent || \"\";\n }, [content, mode]);\n const [renderHtmlContent, setRenderHtmlContent] = useState(htmlContent);\n const prevIncomingHtmlRef = useRef(htmlContent);\n const pendingHtmlRef = useRef(htmlContent);\n const deferRenderTimerRef = useRef<number | null>(null);\n\n const clearDeferredRenderTimer = () => {\n if (deferRenderTimerRef.current === null) return;\n window.clearTimeout(deferRenderTimerRef.current);\n deferRenderTimerRef.current = null;\n };\n\n useEffect(\n () => () => {\n clearDeferredRenderTimer();\n },\n []\n );\n\n useEffect(() => {\n const prevIncomingHtml = prevIncomingHtmlRef.current;\n prevIncomingHtmlRef.current = htmlContent;\n\n const isAppendOnlyStream =\n !!prevIncomingHtml &&\n htmlContent.length > prevIncomingHtml.length &&\n htmlContent.startsWith(prevIncomingHtml);\n const containsCompleteImage = COMPLETE_IMAGE_TAG_PATTERN.test(htmlContent);\n const shouldDeferRender = isAppendOnlyStream && containsCompleteImage;\n\n if (!shouldDeferRender) {\n clearDeferredRenderTimer();\n pendingHtmlRef.current = htmlContent;\n setRenderHtmlContent(htmlContent);\n return;\n }\n\n pendingHtmlRef.current = htmlContent;\n clearDeferredRenderTimer();\n deferRenderTimerRef.current = window.setTimeout(() => {\n setRenderHtmlContent(pendingHtmlRef.current);\n deferRenderTimerRef.current = null;\n }, POST_IMAGE_STREAM_DEBOUNCE_MS);\n }, [htmlContent]);\n\n const rootViewportHeightCss = React.useMemo(() => {\n const normalized = renderHtmlContent.trim();\n if (!normalized) return null;\n const rootMatch = normalized.match(/^<([a-zA-Z][\\w:-]*)(\\s[^>]*?)?>/);\n if (!rootMatch) return null;\n const attrs = rootMatch[2] || \"\";\n const heightAttrMatch = attrs.match(/\\bheight\\s*=\\s*[\"']([^\"']+)[\"']/i);\n if (heightAttrMatch) {\n const explicitHeightCss = parseViewportHeightCss(heightAttrMatch[1]);\n if (explicitHeightCss) return explicitHeightCss;\n }\n const styleAttrMatch = attrs.match(/\\bstyle\\s*=\\s*[\"']([^\"']+)[\"']/i)?.[1];\n const styleHeightMatch = styleAttrMatch?.match(\n /\\bheight\\s*:\\s*([^;]+)/i\n )?.[1];\n if (styleHeightMatch) {\n const styleHeightCss = parseViewportHeightCss(styleHeightMatch);\n if (styleHeightCss) return styleHeightCss;\n }\n const classAttrMatch = attrs.match(/\\bclass\\s*=\\s*[\"']([^\"']+)[\"']/i)?.[1];\n if (!classAttrMatch) return null;\n return extractViewportHeightFromTailwindClass(classAttrMatch);\n }, [renderHtmlContent]);\n const hasRootVhHeight = Boolean(rootViewportHeightCss);\n useEffect(() => {\n if (mode !== \"blackboard\") {\n prevHtmlRef.current = htmlContent;\n return;\n }\n const prev = prevHtmlRef.current;\n const isContinuation = prev && htmlContent.startsWith(prev);\n if (!isContinuation && prev) {\n setResetToken((token) => token + 1);\n }\n prevHtmlRef.current = htmlContent;\n }, [htmlContent, mode]);\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 html, body, #root { width: 100%; 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 docRef.current = doc;\n\n let lastSandboxInteractionTime = 0;\n const notifySandboxInteraction = (eventType: string) => {\n if (typeof window === \"undefined\") {\n return;\n }\n const now = Date.now();\n if (\n eventType === SANDBOX_INTERACTION_MESSAGE_TYPE &&\n now - lastSandboxInteractionTime < SANDBOX_INTERACTION_THROTTLE_MS\n ) {\n return;\n }\n if (\n eventType === \"wheel\" &&\n now - lastSandboxInteractionTime < SANDBOX_INTERACTION_THROTTLE_MS\n ) {\n return;\n }\n lastSandboxInteractionTime = 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 sandboxWindow = iframe.contentWindow;\n const shouldBridgeSandboxInteraction = isBlackboardMode && type === \"sandbox\";\n const handleSandboxPointerDown = () => notifySandboxInteraction(\"pointerdown\");\n const handleSandboxTouchStart = () => notifySandboxInteraction(\"touchstart\");\n const handleSandboxWheel = () => notifySandboxInteraction(\"wheel\");\n const handleSandboxKeydown = () => notifySandboxInteraction(\"keydown\");\n\n if (shouldBridgeSandboxInteraction && sandboxWindow) {\n doc.addEventListener(\"pointerdown\", handleSandboxPointerDown, true);\n doc.addEventListener(\"touchstart\", handleSandboxTouchStart, true);\n doc.addEventListener(\"wheel\", handleSandboxWheel, { passive: true });\n sandboxWindow.addEventListener(\"keydown\", handleSandboxKeydown, 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\n const parseExplicitHeight = (\n value: string,\n parentViewportHeight: number\n ) => {\n const normalized = value.trim().toLowerCase();\n if (!normalized) return null;\n const numeric = Number.parseFloat(normalized);\n if (Number.isNaN(numeric)) return null;\n if (/(dvh|svh|lvh|vh)$/i.test(normalized)) {\n return (numeric / 100) * parentViewportHeight;\n }\n if (normalized.endsWith(\"px\") || /^[0-9.]+$/.test(normalized)) {\n return numeric;\n }\n return null;\n };\n const parseTailwindHeightClass = (\n className: string,\n parentViewportHeight: number\n ) => {\n if (!className.trim()) return null;\n const viewportHeightCss =\n extractViewportHeightFromTailwindClass(className);\n if (viewportHeightCss) {\n return parseExplicitHeight(viewportHeightCss, parentViewportHeight);\n }\n const normalizedTokens = normalizeTailwindHeightTokens(className);\n const arbitraryToken = normalizedTokens.find((token) =>\n /^h-\\[[0-9.]+px\\]$/i.test(token)\n );\n if (!arbitraryToken) return null;\n const matched = arbitraryToken.match(/^h-\\[([0-9.]+)px\\]$/i);\n if (!matched) return null;\n const numeric = Number.parseFloat(matched[1]);\n if (Number.isNaN(numeric)) return null;\n return numeric;\n };\n\n const resolveExplicitHeight = () => {\n if (!iframeRef.current || !doc.body) return null;\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 elements = Array.from(container.children) as HTMLElement[];\n if (elements.length !== 1) return null;\n const target = elements[0];\n const heightValue = target.style.height || target.getAttribute(\"height\");\n const parentViewportHeight =\n iframeRef.current.ownerDocument?.documentElement?.clientHeight ||\n window.innerHeight;\n const parsed = heightValue\n ? parseExplicitHeight(heightValue, parentViewportHeight)\n : null;\n if (parsed !== null) {\n return Math.ceil(parsed);\n }\n const classHeight = parseTailwindHeightClass(\n target.getAttribute(\"class\") || \"\",\n parentViewportHeight\n );\n return classHeight !== null ? Math.ceil(classHeight) : null;\n };\n\n const updateHeight = () => {\n if (!iframeRef.current || !doc.body) return;\n const bodyRect = doc.body.getBoundingClientRect();\n const htmlRect = doc.documentElement?.getBoundingClientRect();\n const bodyHeight = bodyRect.height;\n const htmlHeight = htmlRect?.height || 0;\n const contentHeight = Math.max(bodyHeight, htmlHeight);\n const explicitHeight = resolveExplicitHeight();\n const nextHeight = Math.max(\n 200,\n explicitHeight ?? Math.ceil(contentHeight)\n );\n setHeight(nextHeight);\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 // Inject Tailwind/DaisyUI/GSAP into iframe for all sandbox modes.\n // Dynamic import keeps ~3.3 MB of vendor libs out of the main bundle.\n // Tailwind's MutationObserver ensures styles apply even if content renders first.\n loadBlackboardVendor()\n .then((inject) => {\n if (isDestroyed) return;\n inject(doc);\n scheduleHeightUpdate();\n })\n .catch(() => {\n if (isDestroyed) return;\n scheduleHeightUpdate();\n });\n\n const resizeObserver = new ResizeObserver(() => updateHeight());\n resizeObserver.observe(doc.body);\n if (rootEl) {\n resizeObserver.observe(rootEl);\n }\n\n return () => {\n isDestroyed = true;\n resizeObserver.disconnect();\n if (shouldBridgeSandboxInteraction && sandboxWindow) {\n doc.removeEventListener(\"pointerdown\", handleSandboxPointerDown, true);\n doc.removeEventListener(\"touchstart\", handleSandboxTouchStart, true);\n doc.removeEventListener(\"wheel\", handleSandboxWheel);\n sandboxWindow.removeEventListener(\"keydown\", handleSandboxKeydown, true);\n }\n // Defer unmount to avoid React warning when parent is mid-render\n setTimeout(() => {\n root.unmount();\n rootRef.current = null;\n docRef.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 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 loadingText={loadingText}\n styleLoadingText={styleLoadingText}\n scriptLoadingText={scriptLoadingText}\n fullScreenButtonText={fullScreenButtonText}\n hideFullScreen={hideFullScreen}\n resetToken={resetToken}\n hasRootVhHeight={hasRootVhHeight}\n mode={mode}\n />\n );\n requestAnimationFrame(() => updateHeightRef.current?.());\n }, [\n renderHtmlContent,\n loadingText,\n styleLoadingText,\n scriptLoadingText,\n fullScreenButtonText,\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 : \"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 >\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 <ContentRender content={content} />\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: \"100%\",\n margin: \"auto\",\n }}\n />\n )}\n </div>\n );\n};\n\nexport default IframeSandbox;\n"],"names":["loadBlackboardVendor","m","COMPLETE_IMAGE_TAG_PATTERN","POST_IMAGE_STREAM_DEBOUNCE_MS","SANDBOX_INTERACTION_MESSAGE_SOURCE","SANDBOX_INTERACTION_MESSAGE_TYPE","SANDBOX_INTERACTION_THROTTLE_MS","normalizeTailwindHeightTokens","className","token","parseViewportHeightCss","value","normalized","matched","extractViewportHeightFromTailwindClass","normalizedTokens","arbitraryToken","IframeSandbox","content","type","loadingText","styleLoadingText","scriptLoadingText","fullScreenButtonText","hideFullScreen","mode","containerRef","useRef","iframeRef","rootRef","docRef","updateHeightRef","setHeight","useState","resetToken","setResetToken","isFullscreen","setIsFullscreen","isBlackboardMode","prevHtmlRef","htmlContent","React","sandboxSegments","splitContentSegments","seg","renderHtmlContent","setRenderHtmlContent","prevIncomingHtmlRef","pendingHtmlRef","deferRenderTimerRef","clearDeferredRenderTimer","useEffect","prevIncomingHtml","isAppendOnlyStream","containsCompleteImage","hasRootVhHeight","rootMatch","attrs","heightAttrMatch","explicitHeightCss","styleHeightMatch","styleHeightCss","classAttrMatch","prev","iframe","doc","lastSandboxInteractionTime","notifySandboxInteraction","eventType","now","sandboxWindow","shouldBridgeSandboxInteraction","handleSandboxPointerDown","handleSandboxTouchStart","handleSandboxWheel","handleSandboxKeydown","rootEl","root","createRoot","isDestroyed","parseExplicitHeight","parentViewportHeight","numeric","parseTailwindHeightClass","viewportHeightCss","resolveExplicitHeight","container","elements","target","heightValue","parsed","classHeight","updateHeight","bodyRect","htmlRect","bodyHeight","htmlHeight","contentHeight","explicitHeight","nextHeight","scheduleHeightUpdate","inject","resizeObserver","onFullscreenChange","toggleFullscreen","jsx","SandboxApp","containerClassName","jsxs","ContentRender"],"mappings":"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"}
@@ -1,99 +1,99 @@
1
1
  import { j as R } from "../../_virtual/jsx-runtime.es.js";
2
- import U, { useRef as h, useState as j, useEffect as x } from "react";
3
- import { createRoot as ot } from "react-dom/client";
4
- import st from "./SandboxApp.es.js";
5
- import { splitContentSegments as it } from "./utils/split-content.es.js";
6
- import lt from "./ContentRender.es.js";
7
- const ct = () => import("./blackboard-vendor.es.js").then((i) => i.injectBlackboardLibraries), ut = /<img\b[^>]*>/i, at = 180, J = (i) => i.split(/\s+/).filter(Boolean).map((r) => r.split(":").pop() || r), Y = (i) => {
2
+ import tt, { useRef as d, useState as _, useEffect as x } from "react";
3
+ import { createRoot as ft } from "react-dom/client";
4
+ import pt from "./SandboxApp.es.js";
5
+ import { splitContentSegments as bt } from "./utils/split-content.es.js";
6
+ import gt from "./ContentRender.es.js";
7
+ const wt = () => import("./blackboard-vendor.es.js").then((i) => i.injectBlackboardLibraries), vt = /<img\b[^>]*>/i, xt = 180, Et = "markdown-flow-ui:sandbox", et = "interaction", nt = 240, st = (i) => i.split(/\s+/).filter(Boolean).map((r) => r.split(":").pop() || r), rt = (i) => {
8
8
  const r = i.trim().toLowerCase();
9
9
  if (!r) return null;
10
- const d = r.match(/^([0-9.]+)(vh|dvh|svh|lvh)$/i);
11
- return d ? `${d[1]}${d[2].toLowerCase()}` : null;
12
- }, Z = (i) => {
10
+ const m = r.match(/^([0-9.]+)(vh|dvh|svh|lvh)$/i);
11
+ return m ? `${m[1]}${m[2].toLowerCase()}` : null;
12
+ }, ot = (i) => {
13
13
  if (!i.trim()) return null;
14
- const r = J(i);
14
+ const r = st(i);
15
15
  if (r.includes("h-screen") || r.includes("h-dvh"))
16
16
  return "100dvh";
17
17
  if (r.includes("h-svh"))
18
18
  return "100svh";
19
19
  if (r.includes("h-lvh"))
20
20
  return "100lvh";
21
- const d = r.find(
22
- (E) => /^h-\[[0-9.]+(vh|dvh|svh|lvh)\]$/i.test(E)
21
+ const m = r.find(
22
+ (T) => /^h-\[[0-9.]+(vh|dvh|svh|lvh)\]$/i.test(T)
23
23
  );
24
- if (!d) return null;
25
- const v = d.match(/^h-\[([0-9.]+)(vh|dvh|svh|lvh)\]$/i);
26
- return v ? `${v[1]}${v[2].toLowerCase()}` : null;
27
- }, vt = ({
24
+ if (!m) return null;
25
+ const w = m.match(/^h-\[([0-9.]+)(vh|dvh|svh|lvh)\]$/i);
26
+ return w ? `${w[1]}${w[2].toLowerCase()}` : null;
27
+ }, kt = ({
28
28
  content: i,
29
29
  type: r,
30
- className: d,
31
- loadingText: v,
32
- styleLoadingText: E,
33
- scriptLoadingText: S,
34
- fullScreenButtonText: z,
30
+ className: m,
31
+ loadingText: w,
32
+ styleLoadingText: T,
33
+ scriptLoadingText: $,
34
+ fullScreenButtonText: I,
35
35
  hideFullScreen: V = !1,
36
- mode: a = "content"
36
+ mode: h = "content"
37
37
  }) => {
38
- const O = h(null), w = h(null), F = h(null), L = h(null), $ = h(() => {
39
- }), [, K] = j(480), [q, Q] = j(0), [X, tt] = j(!1), et = a === "blackboard", N = h(""), n = U.useMemo(() => {
40
- const e = it(i).filter((l) => l.type === "sandbox");
41
- return (a === "blackboard" ? e[e.length - 1]?.value || "" : e.map((l) => l.value).join(`
38
+ const P = d(null), v = d(null), L = d(null), W = d(null), O = d(() => {
39
+ }), [, it] = _(480), [q, lt] = _(0), [ct, at] = _(!1), G = h === "blackboard", B = d(""), n = tt.useMemo(() => {
40
+ const t = bt(i).filter((c) => c.type === "sandbox");
41
+ return (h === "blackboard" ? t[t.length - 1]?.value || "" : t.map((c) => c.value).join(`
42
42
  `)) || "";
43
- }, [i, a]), [k, P] = j(n), G = h(n), B = h(n), H = h(null), _ = () => {
44
- H.current !== null && (window.clearTimeout(H.current), H.current = null);
43
+ }, [i, h]), [A, U] = _(n), X = d(n), D = d(n), E = d(null), j = () => {
44
+ E.current !== null && (window.clearTimeout(E.current), E.current = null);
45
45
  };
46
46
  x(
47
47
  () => () => {
48
- _();
48
+ j();
49
49
  },
50
50
  []
51
51
  ), x(() => {
52
- const t = G.current;
53
- G.current = n;
54
- const e = !!t && n.length > t.length && n.startsWith(t), o = ut.test(n);
55
- if (!(e && o)) {
56
- _(), B.current = n, P(n);
52
+ const e = X.current;
53
+ X.current = n;
54
+ const t = !!e && n.length > e.length && n.startsWith(e), l = vt.test(n);
55
+ if (!(t && l)) {
56
+ j(), D.current = n, U(n);
57
57
  return;
58
58
  }
59
- B.current = n, _(), H.current = window.setTimeout(() => {
60
- P(B.current), H.current = null;
61
- }, at);
59
+ D.current = n, j(), E.current = window.setTimeout(() => {
60
+ U(D.current), E.current = null;
61
+ }, xt);
62
62
  }, [n]);
63
- const W = !!U.useMemo(() => {
64
- const t = k.trim();
65
- if (!t) return null;
66
- const e = t.match(/^<([a-zA-Z][\w:-]*)(\s[^>]*?)?>/);
63
+ const Y = !!tt.useMemo(() => {
64
+ const e = A.trim();
67
65
  if (!e) return null;
68
- const o = e[2] || "", l = o.match(/\bheight\s*=\s*["']([^"']+)["']/i);
69
- if (l) {
70
- const f = Y(l[1]);
66
+ const t = e.match(/^<([a-zA-Z][\w:-]*)(\s[^>]*?)?>/);
67
+ if (!t) return null;
68
+ const l = t[2] || "", c = l.match(/\bheight\s*=\s*["']([^"']+)["']/i);
69
+ if (c) {
70
+ const f = rt(c[1]);
71
71
  if (f) return f;
72
72
  }
73
- const C = o.match(/\bstyle\s*=\s*["']([^"']+)["']/i)?.[1]?.match(
73
+ const C = l.match(/\bstyle\s*=\s*["']([^"']+)["']/i)?.[1]?.match(
74
74
  /\bheight\s*:\s*([^;]+)/i
75
75
  )?.[1];
76
76
  if (C) {
77
- const f = Y(C);
77
+ const f = rt(C);
78
78
  if (f) return f;
79
79
  }
80
- const M = o.match(/\bclass\s*=\s*["']([^"']+)["']/i)?.[1];
81
- return M ? Z(M) : null;
82
- }, [k]);
80
+ const H = l.match(/\bclass\s*=\s*["']([^"']+)["']/i)?.[1];
81
+ return H ? ot(H) : null;
82
+ }, [A]);
83
83
  x(() => {
84
- if (a !== "blackboard") {
85
- N.current = n;
84
+ if (h !== "blackboard") {
85
+ B.current = n;
86
86
  return;
87
87
  }
88
- const t = N.current;
89
- !(t && n.startsWith(t)) && t && Q((o) => o + 1), N.current = n;
90
- }, [n, a]), x(() => {
91
- const t = w.current;
92
- if (!t) return;
93
- const e = t.contentDocument;
88
+ const e = B.current;
89
+ !(e && n.startsWith(e)) && e && lt((l) => l + 1), B.current = n;
90
+ }, [n, h]), x(() => {
91
+ const e = v.current;
94
92
  if (!e) return;
95
- e.open(), e.write(`<!DOCTYPE html>
96
- <html${a === "blackboard" ? ' style="height: 100%;"' : ""}>
93
+ const t = e.contentDocument;
94
+ if (!t) return;
95
+ t.open(), t.write(`<!DOCTYPE html>
96
+ <html${h === "blackboard" ? ' style="height: 100%;"' : ""}>
97
97
  <head>
98
98
  <meta charset="utf-8" />
99
99
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
@@ -106,143 +106,158 @@ const ct = () => import("./blackboard-vendor.es.js").then((i) => i.injectBlackbo
106
106
  <body>
107
107
  <div id="root"></div>
108
108
  </body>
109
- </html>`), e.close(), L.current = e;
110
- const o = e.getElementById("root");
111
- if (!o) return;
112
- const l = ot(o);
113
- F.current = l;
114
- let y = !1;
115
- const C = (c, m) => {
116
- const s = c.trim().toLowerCase();
109
+ </html>`), t.close(), W.current = t;
110
+ let l = 0;
111
+ const c = (o) => {
112
+ if (typeof window > "u")
113
+ return;
114
+ const a = Date.now();
115
+ o === et && a - l < nt || o === "wheel" && a - l < nt || (l = a, window.postMessage(
116
+ {
117
+ source: Et,
118
+ type: et,
119
+ eventType: o
120
+ },
121
+ window.location.origin
122
+ ));
123
+ }, y = e.contentWindow, C = G && r === "sandbox", H = () => c("pointerdown"), f = () => c("touchstart"), K = () => c("wheel"), Z = () => c("keydown");
124
+ C && y && (t.addEventListener("pointerdown", H, !0), t.addEventListener("touchstart", f, !0), t.addEventListener("wheel", K, { passive: !0 }), y.addEventListener("keydown", Z, !0));
125
+ const S = t.getElementById("root");
126
+ if (!S) return;
127
+ const J = ft(S);
128
+ L.current = J;
129
+ let k = !1;
130
+ const Q = (o, a) => {
131
+ const s = o.trim().toLowerCase();
117
132
  if (!s) return null;
118
133
  const u = Number.parseFloat(s);
119
- return Number.isNaN(u) ? null : /(dvh|svh|lvh|vh)$/i.test(s) ? u / 100 * m : s.endsWith("px") || /^[0-9.]+$/.test(s) ? u : null;
120
- }, M = (c, m) => {
121
- if (!c.trim()) return null;
122
- const s = Z(c);
134
+ return Number.isNaN(u) ? null : /(dvh|svh|lvh|vh)$/i.test(s) ? u / 100 * a : s.endsWith("px") || /^[0-9.]+$/.test(s) ? u : null;
135
+ }, dt = (o, a) => {
136
+ if (!o.trim()) return null;
137
+ const s = ot(o);
123
138
  if (s)
124
- return C(s, m);
125
- const p = J(c).find(
126
- (A) => /^h-\[[0-9.]+px\]$/i.test(A)
139
+ return Q(s, a);
140
+ const p = st(o).find(
141
+ (N) => /^h-\[[0-9.]+px\]$/i.test(N)
127
142
  );
128
143
  if (!p) return null;
129
- const g = p.match(/^h-\[([0-9.]+)px\]$/i);
130
- if (!g) return null;
131
- const b = Number.parseFloat(g[1]);
132
- return Number.isNaN(b) ? null : b;
133
- }, f = () => {
134
- if (!w.current || !e.body) return null;
135
- const m = e.body.querySelector(
144
+ const b = p.match(/^h-\[([0-9.]+)px\]$/i);
145
+ if (!b) return null;
146
+ const g = Number.parseFloat(b[1]);
147
+ return Number.isNaN(g) ? null : g;
148
+ }, mt = () => {
149
+ if (!v.current || !t.body) return null;
150
+ const a = t.body.querySelector(
136
151
  ".sandbox-wrapper"
137
152
  )?.firstElementChild;
138
- if (!m) return null;
139
- const s = Array.from(m.children);
153
+ if (!a) return null;
154
+ const s = Array.from(a.children);
140
155
  if (s.length !== 1) return null;
141
- const u = s[0], p = u.style.height || u.getAttribute("height"), g = w.current.ownerDocument?.documentElement?.clientHeight || window.innerHeight, b = p ? C(p, g) : null;
142
- if (b !== null)
143
- return Math.ceil(b);
144
- const A = M(
156
+ const u = s[0], p = u.style.height || u.getAttribute("height"), b = v.current.ownerDocument?.documentElement?.clientHeight || window.innerHeight, g = p ? Q(p, b) : null;
157
+ if (g !== null)
158
+ return Math.ceil(g);
159
+ const N = dt(
145
160
  u.getAttribute("class") || "",
146
- g
161
+ b
147
162
  );
148
- return A !== null ? Math.ceil(A) : null;
149
- }, D = () => {
150
- if (!w.current || !e.body) return;
151
- const c = e.body.getBoundingClientRect(), m = e.documentElement?.getBoundingClientRect(), s = c.height, u = m?.height || 0, p = Math.max(s, u), g = f(), b = Math.max(
163
+ return N !== null ? Math.ceil(N) : null;
164
+ }, z = () => {
165
+ if (!v.current || !t.body) return;
166
+ const o = t.body.getBoundingClientRect(), a = t.documentElement?.getBoundingClientRect(), s = o.height, u = a?.height || 0, p = Math.max(s, u), b = mt(), g = Math.max(
152
167
  200,
153
- g ?? Math.ceil(p)
168
+ b ?? Math.ceil(p)
154
169
  );
155
- K(b);
156
- }, T = () => {
170
+ it(g);
171
+ }, M = () => {
157
172
  requestAnimationFrame(() => {
158
- y || D();
173
+ k || z();
159
174
  });
160
175
  };
161
- $.current = T, D(), T(), ct().then((c) => {
162
- y || (c(e), T());
176
+ O.current = M, z(), M(), wt().then((o) => {
177
+ k || (o(t), M());
163
178
  }).catch(() => {
164
- y || T();
179
+ k || M();
165
180
  });
166
- const I = new ResizeObserver(() => D());
167
- return I.observe(e.body), o && I.observe(o), () => {
168
- y = !0, I.disconnect(), setTimeout(() => {
169
- l.unmount(), F.current = null, L.current = null, $.current = () => {
181
+ const F = new ResizeObserver(() => z());
182
+ return F.observe(t.body), S && F.observe(S), () => {
183
+ k = !0, F.disconnect(), C && y && (t.removeEventListener("pointerdown", H, !0), t.removeEventListener("touchstart", f, !0), t.removeEventListener("wheel", K), y.removeEventListener("keydown", Z, !0)), setTimeout(() => {
184
+ J.unmount(), L.current = null, W.current = null, O.current = () => {
170
185
  };
171
186
  }, 0);
172
187
  };
173
188
  }, []), x(() => {
174
- const t = () => {
175
- tt(!!document.fullscreenElement);
189
+ const e = () => {
190
+ at(!!document.fullscreenElement);
176
191
  };
177
- return document.addEventListener("fullscreenchange", t), () => document.removeEventListener("fullscreenchange", t);
192
+ return document.addEventListener("fullscreenchange", e), () => document.removeEventListener("fullscreenchange", e);
178
193
  }, []);
179
- const nt = () => {
180
- const t = O.current || w.current;
181
- if (t) {
194
+ const ut = () => {
195
+ const e = P.current || v.current;
196
+ if (e) {
182
197
  if (document.fullscreenElement) {
183
198
  document.exitFullscreen().catch(() => {
184
199
  });
185
200
  return;
186
201
  }
187
- t.requestFullscreen && t.requestFullscreen().catch(() => {
202
+ e.requestFullscreen && e.requestFullscreen().catch(() => {
188
203
  });
189
204
  }
190
205
  };
191
206
  x(() => {
192
- const t = F.current;
193
- t && (t.render(
207
+ const e = L.current;
208
+ e && (e.render(
194
209
  /* @__PURE__ */ R.jsx(
195
- st,
210
+ pt,
196
211
  {
197
- html: k,
198
- loadingText: v,
199
- styleLoadingText: E,
200
- scriptLoadingText: S,
201
- fullScreenButtonText: z,
212
+ html: A,
213
+ loadingText: w,
214
+ styleLoadingText: T,
215
+ scriptLoadingText: $,
216
+ fullScreenButtonText: I,
202
217
  hideFullScreen: V,
203
218
  resetToken: q,
204
- hasRootVhHeight: W,
205
- mode: a
219
+ hasRootVhHeight: Y,
220
+ mode: h
206
221
  }
207
222
  )
208
- ), requestAnimationFrame(() => $.current?.()));
223
+ ), requestAnimationFrame(() => O.current?.()));
209
224
  }, [
210
- k,
211
- v,
212
- E,
213
- S,
214
- z,
225
+ A,
226
+ w,
227
+ T,
228
+ $,
229
+ I,
215
230
  q,
216
- a
231
+ h
217
232
  ]);
218
- const rt = [
233
+ const ht = [
219
234
  "w-full relative content-render-iframe-sandbox",
220
- et ? "h-full overflow-auto flex flex-col" : "aspect-[16/9] overflow-hidden flex items-center justify-center"
235
+ G ? "h-full overflow-auto flex flex-col" : "aspect-[16/9] overflow-hidden flex items-center justify-center"
221
236
  ].filter(Boolean).join(" ");
222
237
  return /* @__PURE__ */ R.jsxs(
223
238
  "div",
224
239
  {
225
- ref: O,
226
- "data-root-vh": W ? "true" : "false",
227
- className: rt,
240
+ ref: P,
241
+ "data-root-vh": Y ? "true" : "false",
242
+ className: ht,
228
243
  children: [
229
244
  !V && /* @__PURE__ */ R.jsx(
230
245
  "button",
231
246
  {
232
247
  type: "button",
233
- onClick: nt,
248
+ onClick: ut,
234
249
  className: "absolute top-2 right-2 z-50 p-1.5 bg-black/75 text-white rounded-md cursor-pointer",
235
- children: X ? "退出全屏" : z || "全屏浏览"
250
+ children: ct ? "退出全屏" : I || "全屏浏览"
236
251
  }
237
252
  ),
238
- a === "blackboard" && r === "markdown" ? /* @__PURE__ */ R.jsx(lt, { content: i }) : /* @__PURE__ */ R.jsx(
253
+ h === "blackboard" && r === "markdown" ? /* @__PURE__ */ R.jsx(gt, { content: i }) : /* @__PURE__ */ R.jsx(
239
254
  "iframe",
240
255
  {
241
- ref: w,
256
+ ref: v,
242
257
  sandbox: "allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox",
243
258
  allow: "fullscreen",
244
259
  allowFullScreen: !0,
245
- className: [d, "w-full h-full mx-auto my-auto block"].filter(Boolean).join(" "),
260
+ className: [m, "w-full h-full mx-auto my-auto block"].filter(Boolean).join(" "),
246
261
  style: {
247
262
  height: "100%",
248
263
  margin: "auto"
@@ -254,6 +269,6 @@ const ct = () => import("./blackboard-vendor.es.js").then((i) => i.injectBlackbo
254
269
  );
255
270
  };
256
271
  export {
257
- vt as default
272
+ kt as default
258
273
  };
259
274
  //# sourceMappingURL=IframeSandbox.es.js.map