markdown-flow-ui 0.1.100 → 0.1.101

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 (163) hide show
  1. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/hast-util-to-jsx-runtime@2.3.6/node_modules/hast-util-to-jsx-runtime/lib/index.cjs.js +1 -1
  2. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/hast-util-to-jsx-runtime@2.3.6/node_modules/hast-util-to-jsx-runtime/lib/index.es.js +1 -1
  3. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/ellipsis-vertical.cjs.js +7 -0
  4. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/ellipsis-vertical.cjs.js.map +1 -0
  5. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/ellipsis-vertical.es.js +17 -0
  6. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/ellipsis-vertical.es.js.map +1 -0
  7. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/file-pen-line.cjs.js +7 -0
  8. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/file-pen-line.cjs.js.map +1 -0
  9. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/file-pen-line.es.js +29 -0
  10. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/file-pen-line.es.js.map +1 -0
  11. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/maximize.cjs.js +7 -0
  12. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/maximize.cjs.js.map +1 -0
  13. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/maximize.es.js +18 -0
  14. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/maximize.es.js.map +1 -0
  15. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/rotate-ccw.cjs.js +7 -0
  16. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/rotate-ccw.cjs.js.map +1 -0
  17. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/rotate-ccw.es.js +16 -0
  18. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/rotate-ccw.es.js.map +1 -0
  19. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/rotate-cw.cjs.js +7 -0
  20. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/rotate-cw.cjs.js.map +1 -0
  21. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/rotate-cw.es.js +16 -0
  22. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/rotate-cw.es.js.map +1 -0
  23. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/volume-2.cjs.js +7 -0
  24. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/volume-2.cjs.js.map +1 -0
  25. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/volume-2.es.js +23 -0
  26. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/volume-2.es.js.map +1 -0
  27. 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
  28. 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
  29. 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
  30. 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
  31. 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
  32. 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
  33. 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
  34. 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
  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.cjs.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-custom-variable.es.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.cjs.js +1 -1
  38. 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
  39. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/unified@11.0.5/node_modules/unified/lib/index.cjs.js +1 -1
  40. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/unified@11.0.5/node_modules/unified/lib/index.es.js +1 -1
  41. package/dist/_virtual/index.cjs.js +1 -1
  42. package/dist/_virtual/index.cjs3.js +1 -1
  43. package/dist/_virtual/index.cjs4.js +1 -1
  44. package/dist/_virtual/index.cjs5.js +1 -1
  45. package/dist/_virtual/index.cjs6.js +1 -1
  46. package/dist/_virtual/index.es.js +1 -0
  47. package/dist/_virtual/index.es3.js +4 -5
  48. package/dist/_virtual/index.es3.js.map +1 -1
  49. package/dist/_virtual/index.es4.js +5 -4
  50. package/dist/_virtual/index.es4.js.map +1 -1
  51. package/dist/_virtual/index.es5.js +4 -4
  52. package/dist/_virtual/index.es6.js +5 -5
  53. package/dist/assets/markdown-flow-ui.css +1 -1
  54. package/dist/components/ContentRender/ContentRender.cjs.js +2 -2
  55. package/dist/components/ContentRender/ContentRender.cjs.js.map +1 -1
  56. package/dist/components/ContentRender/ContentRender.d.ts +13 -10
  57. package/dist/components/ContentRender/ContentRender.es.js +172 -155
  58. package/dist/components/ContentRender/ContentRender.es.js.map +1 -1
  59. package/dist/components/ContentRender/ContentRender.stories.d.ts +1 -0
  60. package/dist/components/ContentRender/IframeSandbox.cjs.js +4 -4
  61. package/dist/components/ContentRender/IframeSandbox.cjs.js.map +1 -1
  62. package/dist/components/ContentRender/IframeSandbox.d.ts +1 -0
  63. package/dist/components/ContentRender/IframeSandbox.es.js +214 -192
  64. package/dist/components/ContentRender/IframeSandbox.es.js.map +1 -1
  65. package/dist/components/ContentRender/SandboxApp.cjs.js +3 -3
  66. package/dist/components/ContentRender/SandboxApp.cjs.js.map +1 -1
  67. package/dist/components/ContentRender/SandboxApp.d.ts +1 -0
  68. package/dist/components/ContentRender/SandboxApp.es.js +90 -90
  69. package/dist/components/ContentRender/SandboxApp.es.js.map +1 -1
  70. package/dist/components/ContentRender/plugins/CustomVariable.cjs.js +1 -1
  71. package/dist/components/ContentRender/plugins/CustomVariable.cjs.js.map +1 -1
  72. package/dist/components/ContentRender/plugins/CustomVariable.es.js +94 -86
  73. package/dist/components/ContentRender/plugins/CustomVariable.es.js.map +1 -1
  74. package/dist/components/ContentRender/utils/iframe-viewport-height.cjs.js +2 -0
  75. package/dist/components/ContentRender/utils/iframe-viewport-height.cjs.js.map +1 -0
  76. package/dist/components/ContentRender/utils/iframe-viewport-height.d.ts +24 -0
  77. package/dist/components/ContentRender/utils/iframe-viewport-height.es.js +127 -0
  78. package/dist/components/ContentRender/utils/iframe-viewport-height.es.js.map +1 -0
  79. package/dist/components/ContentRender/utils/iframe-viewport-height.test.d.ts +1 -0
  80. package/dist/components/MarkdownFlow/MarkdownFlow.cjs.js +1 -1
  81. package/dist/components/MarkdownFlow/MarkdownFlow.cjs.js.map +1 -1
  82. package/dist/components/MarkdownFlow/MarkdownFlow.d.ts +3 -0
  83. package/dist/components/MarkdownFlow/MarkdownFlow.es.js +19 -16
  84. package/dist/components/MarkdownFlow/MarkdownFlow.es.js.map +1 -1
  85. package/dist/components/Slide/Player.cjs.js +2 -0
  86. package/dist/components/Slide/Player.cjs.js.map +1 -0
  87. package/dist/components/Slide/Player.d.ts +21 -0
  88. package/dist/components/Slide/Player.es.js +386 -0
  89. package/dist/components/Slide/Player.es.js.map +1 -0
  90. package/dist/components/Slide/Slide.cjs.js +2 -0
  91. package/dist/components/Slide/Slide.cjs.js.map +1 -0
  92. package/dist/components/Slide/Slide.d.ts +27 -0
  93. package/dist/components/Slide/Slide.es.js +583 -0
  94. package/dist/components/Slide/Slide.es.js.map +1 -0
  95. package/dist/components/Slide/Slide.stories.d.ts +79 -0
  96. package/dist/components/Slide/diff-utils.cjs.js +5 -0
  97. package/dist/components/Slide/diff-utils.cjs.js.map +1 -0
  98. package/dist/components/Slide/diff-utils.d.ts +18 -0
  99. package/dist/components/Slide/diff-utils.es.js +113 -0
  100. package/dist/components/Slide/diff-utils.es.js.map +1 -0
  101. package/dist/components/Slide/index.cjs.js +2 -0
  102. package/dist/components/Slide/index.cjs.js.map +1 -0
  103. package/dist/components/Slide/index.d.ts +12 -0
  104. package/dist/components/Slide/index.es.js +12 -0
  105. package/dist/components/Slide/index.es.js.map +1 -0
  106. package/dist/components/Slide/types.d.ts +24 -0
  107. package/dist/components/Slide/useSlide.cjs.js +2 -0
  108. package/dist/components/Slide/useSlide.cjs.js.map +1 -0
  109. package/dist/components/Slide/useSlide.d.ts +24 -0
  110. package/dist/components/Slide/useSlide.es.js +144 -0
  111. package/dist/components/Slide/useSlide.es.js.map +1 -0
  112. package/dist/components/Slide/useWakePlayerFromIframe.cjs.js +2 -0
  113. package/dist/components/Slide/useWakePlayerFromIframe.cjs.js.map +1 -0
  114. package/dist/components/Slide/useWakePlayerFromIframe.d.ts +7 -0
  115. package/dist/components/Slide/useWakePlayerFromIframe.es.js +89 -0
  116. package/dist/components/Slide/useWakePlayerFromIframe.es.js.map +1 -0
  117. package/dist/components/Slide/utils/interactionPlayback.cjs.js +2 -0
  118. package/dist/components/Slide/utils/interactionPlayback.cjs.js.map +1 -0
  119. package/dist/components/Slide/utils/interactionPlayback.d.ts +9 -0
  120. package/dist/components/Slide/utils/interactionPlayback.es.js +11 -0
  121. package/dist/components/Slide/utils/interactionPlayback.es.js.map +1 -0
  122. package/dist/components/Slide/utils/interactionPlayback.test.d.ts +1 -0
  123. package/dist/components/Slide/utils/listenModeElementList.d.ts +81 -0
  124. package/dist/components/Slide/utils/listenModeElementList.test.d.ts +1 -0
  125. package/dist/components/Slide/utils/playbackSequence.cjs.js +2 -0
  126. package/dist/components/Slide/utils/playbackSequence.cjs.js.map +1 -0
  127. package/dist/components/Slide/utils/playbackSequence.d.ts +11 -0
  128. package/dist/components/Slide/utils/playbackSequence.es.js +16 -0
  129. package/dist/components/Slide/utils/playbackSequence.es.js.map +1 -0
  130. package/dist/components/Slide/utils/playbackSequence.test.d.ts +1 -0
  131. package/dist/components/Slide/utils/playerCustomActions.cjs.js +2 -0
  132. package/dist/components/Slide/utils/playerCustomActions.cjs.js.map +1 -0
  133. package/dist/components/Slide/utils/playerCustomActions.d.ts +3 -0
  134. package/dist/components/Slide/utils/playerCustomActions.es.js +7 -0
  135. package/dist/components/Slide/utils/playerCustomActions.es.js.map +1 -0
  136. package/dist/components/index.d.ts +7 -0
  137. package/dist/components/ui/inputGroup/textarea.cjs.js +1 -1
  138. package/dist/components/ui/inputGroup/textarea.es.js +1 -1
  139. package/dist/index.cjs.js +1 -1
  140. package/dist/index.es.js +13 -10
  141. package/dist/index.es.js.map +1 -1
  142. package/dist/lib/browserUserActivation.d.ts +5 -0
  143. package/dist/lib/interaction-defaults.cjs.js +2 -0
  144. package/dist/lib/interaction-defaults.cjs.js.map +1 -0
  145. package/dist/lib/interaction-defaults.d.ts +23 -0
  146. package/dist/lib/interaction-defaults.es.js +145 -0
  147. package/dist/lib/interaction-defaults.es.js.map +1 -0
  148. package/dist/lib/sandboxInteraction.cjs.js +2 -0
  149. package/dist/lib/sandboxInteraction.cjs.js.map +1 -0
  150. package/dist/lib/sandboxInteraction.d.ts +8 -0
  151. package/dist/lib/sandboxInteraction.es.js +12 -0
  152. package/dist/lib/sandboxInteraction.es.js.map +1 -0
  153. package/dist/markdown-flow-ui-lib.css +1 -1
  154. package/dist/renderer.cjs.js +1 -1
  155. package/dist/renderer.d.ts +3 -1
  156. package/dist/renderer.es.js +9 -6
  157. package/dist/renderer.es.js.map +1 -1
  158. package/dist/slide.cjs.js +2 -0
  159. package/dist/slide.cjs.js.map +1 -0
  160. package/dist/slide.d.ts +2 -0
  161. package/dist/slide.es.js +18 -0
  162. package/dist/slide.es.js.map +1 -0
  163. package/package.json +25 -2
@@ -1 +1 @@
1
- {"version":3,"file":"IframeSandbox.es.js","sources":["../../../src/components/ContentRender/IframeSandbox.tsx"],"sourcesContent":["import React, { useCallback, 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 lastSandboxInteractionTimeRef = useRef(0);\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 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 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 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\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) {\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 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 <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: \"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","lastSandboxInteractionTimeRef","setHeight","useState","resetToken","setResetToken","isFullscreen","setIsFullscreen","isBlackboardMode","prevHtmlRef","htmlContent","React","sandboxSegments","splitContentSegments","seg","renderHtmlContent","setRenderHtmlContent","prevIncomingHtmlRef","pendingHtmlRef","deferRenderTimerRef","emitSandboxInteraction","useCallback","eventType","now","clearDeferredRenderTimer","useEffect","prevIncomingHtml","isAppendOnlyStream","containsCompleteImage","hasRootVhHeight","rootMatch","attrs","heightAttrMatch","explicitHeightCss","styleHeightMatch","styleHeightCss","classAttrMatch","prev","iframe","doc","shouldBridgeSandboxInteraction","handleSandboxPointerDown","handleSandboxMouseDown","handleSandboxTouchStart","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.es.js","sources":["../../../src/components/ContentRender/IframeSandbox.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } 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 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%; 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 (!shouldMeasureDynamicHeight) return;\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((prevHeight) =>\n prevHeight === nextHeight ? prevHeight : nextHeight\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 return () => {\n isDestroyed = true;\n resizeObserver.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 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 initialPaintFrameRef.current = window.requestAnimationFrame(() => {\n updateHeightRef.current?.();\n initialPaintFrameRef.current = null;\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 : \"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 : undefined\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 visibility: \"visible\",\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","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","bodyRect","htmlRect","bodyHeight","htmlHeight","contentHeight","explicitHeight","nextHeight","prevHeight","scheduleHeightUpdate","inject","resizeObserver","onFullscreenChange","toggleFullscreen","target","jsx","SandboxApp","containerClassName","jsxs","ContentRender"],"mappings":"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"}
@@ -1,11 +1,11 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const v=require("../../_virtual/jsx-runtime.cjs.js"),t=require("react"),J=require("../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/loader-circle.cjs.js"),X=["src","srcset","sizes","alt","class","width","height","style","loading","decoding","crossorigin","referrerpolicy"],F=a=>X.map(r=>`${r}:${a.getAttribute(r)||""}`).join("|"),Y=a=>{const r=new Map;return a.querySelectorAll("img").forEach(l=>{const c=l,n=F(c),f=r.get(n)||[];f.push(c),r.set(n,f)}),r},Z=(a,r)=>{const l=Array.from(a.attributes),c=new Set(l.map(n=>n.name));Array.from(r.attributes).forEach(n=>{c.has(n.name)||r.removeAttribute(n.name)}),l.forEach(n=>{r.setAttribute(n.name,n.value)})},ee=(a,r)=>{r.size&&a.querySelectorAll("img").forEach(l=>{const c=l,n=F(c),f=r.get(n),h=f?.shift();h&&(Z(c,h),c.replaceWith(h),f&&f.length===0&&r.delete(n))})},te=({html:a,styleLoadingText:r,scriptLoadingText:l,resetToken:c=0,mode:n="content",hasRootVhHeight:f=!1})=>{const h=t.useRef(null),w=t.useRef(null),[,k]=t.useState(!0),[H,A]=t.useState(!1),[O,C]=t.useState(!1),I=t.useRef([]),j=t.useRef([]),q=t.useRef(0),L=t.useRef(0),g=t.useRef(null),x=t.useRef(null),b=t.useRef(!1),R=t.useRef(!1),N=t.useRef(!1),_=t.useRef(c),U=200,d=s=>{s.current&&(clearTimeout(s.current),s.current=null)},B=(s,i,u,T)=>{const S=performance.now()-u.current,p=Math.max(0,U-S);d(i),i.current=window.setTimeout(()=>{s(!1),T?.(),i.current=null},p)};t.useEffect(()=>{const s=w.current?.ownerDocument;if(!s)return;const i="sandbox-spinner-style";let u=s.getElementById(i);u||(u=s.createElement("style"),u.id=i,s.head?.appendChild(u)),u.textContent=`
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const A=require("../../_virtual/jsx-runtime.cjs.js"),r=require("react"),P=require("../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/loader-circle.cjs.js"),Q=["src","srcset","sizes","alt","class","width","height","style","loading","decoding","crossorigin","referrerpolicy","fetchpriority"],D=a=>Q.map(t=>`${t}:${a.getAttribute(t)||""}`).join("|"),J=a=>{const t=new Map;return a.querySelectorAll("img").forEach(l=>{const c=l,s=D(c),f=t.get(s)||[];f.push(c),t.set(s,f)}),t},X=(a,t)=>{const l=Array.from(a.attributes),c=new Set(l.map(s=>s.name));Array.from(t.attributes).forEach(s=>{c.has(s.name)||t.removeAttribute(s.name)}),l.forEach(s=>{t.setAttribute(s.name,s.value)})},Y=(a,t)=>{t.size&&a.querySelectorAll("img").forEach(l=>{const c=l,s=D(c),f=t.get(s),h=f?.shift();h&&(X(c,h),c.replaceWith(h),f&&f.length===0&&t.delete(s))})},Z=({html:a,styleLoadingText:t,scriptLoadingText:l,resetToken:c=0,mode:s="content",hasRootVhHeight:f=!1,stretchRootHeight:h=!1})=>{const C=r.useRef(null),[F,w]=r.useState(!1),[W,j]=r.useState(!1),I=r.useRef([]),N=r.useRef([]),k=r.useRef(0),q=r.useRef(0),g=r.useRef(null),x=r.useRef(null),b=r.useRef(!1),E=r.useRef(!1),_=r.useRef(!1),G=r.useRef(c),H=200,d=n=>{n.current&&(clearTimeout(n.current),n.current=null)},L=(n,i,u,T)=>{const m=performance.now()-u.current,v=Math.max(0,H-m);d(i),i.current=window.setTimeout(()=>{n(!1),T?.(),i.current=null},v)};r.useEffect(()=>{const n=C.current?.ownerDocument;if(!n)return;const i="sandbox-spinner-style";let u=n.getElementById(i);u||(u=n.createElement("style"),u.id=i,n.head?.appendChild(u)),u.textContent=`
2
2
  @keyframes sandbox-spin { from { transform: rotate(0deg);} to { transform: rotate(360deg);} }
3
3
  .sandbox-wrapper { align-items: center; }
4
- .sandbox-container { width: 100%; }
4
+ .sandbox-container { position: relative; width: 100%; }
5
5
  .sandbox-container svg,
6
6
  .sandbox-container img { display: block; margin-left: auto; margin-right: auto; }
7
7
  .justify-\\[safe_center\\]{
8
8
  justify-content: safe center;
9
9
  }
10
- `},[]),t.useEffect(()=>{c!==_.current&&(N.current=!1,_.current=c),d(g),d(x),b.current=!1,R.current=!1;const s=w.current;if(!s)return;const i=s.ownerDocument,u=i?.body;if(!u)return;const T=Y(s);I.current.forEach(e=>e.remove()),I.current=[],j.current.forEach(e=>e.remove()),j.current=[];const S=N.current;k(!S),A(!1),C(!1);const p=i.createElement("div");p.innerHTML=a;const D=(a.match(/<script[\s>]/gi)||[]).length,K=(a.match(/<\/script>/gi)||[]).length,P=D>0&&D===K,y=[];Array.from(p.querySelectorAll("style, script")).forEach(e=>{if(e.tagName.toLowerCase()==="style"){const o=i.createElement("style");o.textContent=e.textContent||"",Array.from(e.attributes).forEach(m=>{o.setAttribute(m.name,m.value)}),y.push(o)}else{const o=i.createElement("script");Array.from(e.attributes).forEach(m=>{o.setAttribute(m.name,m.value)}),o.textContent=e.textContent||"",y.push(o)}e.remove()}),ee(p,T);const G=y.some(e=>e.tagName.toLowerCase()==="style"),z=y.some(e=>e.tagName.toLowerCase()==="script");G&&(b.current=!0,q.current=performance.now(),d(g),A(!0)),z&&(R.current=!0,L.current=performance.now(),d(x),C(!0));const W=!!p.firstElementChild;k(!W&&!S),W&&(N.current=!0),s.innerHTML="";const Q=Array.from(p.childNodes);s.append(...Q),y.forEach(e=>{if(e.tagName.toLowerCase()==="style"){i.head?.appendChild(e),I.current.push(e);return}if(P){const o=e,m=o.textContent||"";if(!o.src)try{new Function(m)}catch{o.remove();return}try{u.appendChild(o),j.current.push(o)}catch{o.remove()}}else e.remove()}),requestAnimationFrame(()=>{G&&B(A,g,q,()=>{b.current=!1}),z&&B(C,x,L,()=>{R.current=!1})})},[a,c]),t.useEffect(()=>()=>{d(g),d(x)},[]);const E=O||R.current?l||"Building scripts cache...":H||b.current?r||"Building styles...":null,M=n==="blackboard",V={position:"relative",width:"100%",height:M?"100vh":"100%",display:"flex",flexDirection:"column",justifyContent:M?"space-around":"flex-start"},$={pointerEvents:E?"none":void 0,margin:M?void 0:"auto 0",width:"100%"};return v.jsxRuntimeExports.jsxs("div",{ref:h,"data-root-vh":f?"true":"false",className:"sandbox-wrapper",style:V,"aria-busy":!!E,children:[v.jsxRuntimeExports.jsx("div",{ref:w,className:"sandbox-container",style:$}),E&&v.jsxRuntimeExports.jsxs("div",{style:{position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(51, 51, 51, 0.80)",color:"#ffffff",fontSize:16,fontWeight:700,gap:10,pointerEvents:"auto",zIndex:20},children:[v.jsxRuntimeExports.jsx(J.default,{"aria-hidden":!0,size:20,style:{animation:"sandbox-spin 1s linear infinite"}}),E]})]})};exports.default=te;
10
+ `},[]),r.useEffect(()=>{c!==G.current&&(_.current=!1,G.current=c),d(g),d(x),b.current=!1,E.current=!1;const n=C.current;if(!n)return;const i=n.ownerDocument,u=i?.body;if(!u)return;const T=J(n);I.current.forEach(e=>e.remove()),I.current=[],N.current.forEach(e=>e.remove()),N.current=[],w(!1),j(!1);const m=i.createElement("div");m.innerHTML=a;const v=(a.match(/<script[\s>]/gi)||[]).length,V=(a.match(/<\/script>/gi)||[]).length,$=v>0&&v===V,y=[];Array.from(m.querySelectorAll("style, script")).forEach(e=>{if(e.tagName.toLowerCase()==="style"){const o=i.createElement("style");o.textContent=e.textContent||"",Array.from(e.attributes).forEach(p=>{o.setAttribute(p.name,p.value)}),y.push(o)}else{const o=i.createElement("script");Array.from(e.attributes).forEach(p=>{o.setAttribute(p.name,p.value)}),o.textContent=e.textContent||"",y.push(o)}e.remove()}),Y(m,T);const z=y.some(e=>e.tagName.toLowerCase()==="style"),B=y.some(e=>e.tagName.toLowerCase()==="script");z&&(b.current=!0,k.current=performance.now(),d(g),w(!0)),B&&(E.current=!0,q.current=performance.now(),d(x),j(!0)),!!m.firstElementChild&&(_.current=!0);const K=Array.from(m.childNodes);n.replaceChildren(...K),y.forEach(e=>{if(e.tagName.toLowerCase()==="style"){i.head?.appendChild(e),I.current.push(e);return}if($){const o=e,p=o.textContent||"";if(!o.src)try{new Function(p)}catch{o.remove();return}try{u.appendChild(o),N.current.push(o)}catch{o.remove()}}else e.remove()}),requestAnimationFrame(()=>{z&&L(w,g,k,()=>{b.current=!1}),B&&L(j,x,q,()=>{E.current=!1})})},[a,c]),r.useEffect(()=>()=>{d(g),d(x)},[]);const R=W||E.current?l||"Building scripts cache...":F||b.current?t||"Building styles...":null,M=s==="blackboard",S=M&&h,O={position:"relative",width:"100%",height:"100%",display:"flex",flexDirection:"column",justifyContent:S?"flex-start":M?"space-around":"flex-start"},U={pointerEvents:R?"none":void 0,margin:M?void 0:"auto 0",width:"100%",height:S?"100%":void 0,minHeight:S?0:void 0,flex:S?"1 1 auto":void 0};return A.jsxRuntimeExports.jsxs("div",{"data-root-vh":f?"true":"false",className:"sandbox-wrapper",style:O,"aria-busy":!!R,children:[A.jsxRuntimeExports.jsx("div",{ref:C,className:"sandbox-container",style:U}),R&&A.jsxRuntimeExports.jsxs("div",{style:{position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(51, 51, 51, 0.80)",color:"#ffffff",fontSize:16,fontWeight:700,gap:10,pointerEvents:"auto",zIndex:20},children:[A.jsxRuntimeExports.jsx(P.default,{"aria-hidden":!0,size:20,style:{animation:"sandbox-spin 1s linear infinite"}}),R]})]})};exports.default=Z;
11
11
  //# sourceMappingURL=SandboxApp.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SandboxApp.cjs.js","sources":["../../../src/components/ContentRender/SandboxApp.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport { Loader2 } from \"lucide-react\";\n\nexport interface SandboxAppProps {\n html: string;\n styleLoadingText?: string;\n scriptLoadingText?: string;\n resetToken?: number;\n mode?: \"content\" | \"blackboard\";\n hasRootVhHeight?: boolean;\n}\n\nconst IMAGE_REUSE_ATTRIBUTES = [\n \"src\",\n \"srcset\",\n \"sizes\",\n \"alt\",\n \"class\",\n \"width\",\n \"height\",\n \"style\",\n \"loading\",\n \"decoding\",\n \"crossorigin\",\n \"referrerpolicy\",\n];\n\nconst getImageReuseKey = (image: HTMLImageElement) =>\n IMAGE_REUSE_ATTRIBUTES.map(\n (attribute) => `${attribute}:${image.getAttribute(attribute) || \"\"}`\n ).join(\"|\");\n\nconst collectReusableImages = (root: ParentNode) => {\n const imageMap = new Map<string, HTMLImageElement[]>();\n root.querySelectorAll(\"img\").forEach((node) => {\n const image = node as HTMLImageElement;\n const key = getImageReuseKey(image);\n const bucket = imageMap.get(key) || [];\n bucket.push(image);\n imageMap.set(key, bucket);\n });\n return imageMap;\n};\n\nconst syncImageAttributes = (\n sourceImage: HTMLImageElement,\n targetImage: HTMLImageElement\n) => {\n const sourceAttributes = Array.from(sourceImage.attributes);\n const sourceAttributeNames = new Set(\n sourceAttributes.map((attribute) => attribute.name)\n );\n\n Array.from(targetImage.attributes).forEach((attribute) => {\n if (!sourceAttributeNames.has(attribute.name)) {\n targetImage.removeAttribute(attribute.name);\n }\n });\n\n sourceAttributes.forEach((attribute) => {\n targetImage.setAttribute(attribute.name, attribute.value);\n });\n};\n\nconst reuseRenderedImages = (\n root: ParentNode,\n imageMap: Map<string, HTMLImageElement[]>\n) => {\n if (!imageMap.size) return;\n\n root.querySelectorAll(\"img\").forEach((node) => {\n const nextImage = node as HTMLImageElement;\n const key = getImageReuseKey(nextImage);\n const bucket = imageMap.get(key);\n const preservedImage = bucket?.shift();\n if (!preservedImage) return;\n\n syncImageAttributes(nextImage, preservedImage);\n nextImage.replaceWith(preservedImage);\n\n if (bucket && bucket.length === 0) {\n imageMap.delete(key);\n }\n });\n};\n\nconst SandboxApp: React.FC<SandboxAppProps> = ({\n html,\n styleLoadingText,\n scriptLoadingText,\n resetToken = 0,\n mode = \"content\",\n hasRootVhHeight = false,\n}) => {\n const wrapperRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const [, setIsWaitingFirstDiv] = useState(true);\n const [isGeneratingStyles, setIsGeneratingStyles] = useState(false);\n const [isGeneratingScripts, setIsGeneratingScripts] = useState(false);\n const appendedStylesRef = useRef<HTMLStyleElement[]>([]);\n const appendedScriptsRef = useRef<HTMLScriptElement[]>([]);\n const styleStartRef = useRef(0);\n const scriptStartRef = useRef(0);\n const styleTimerRef = useRef<number | null>(null);\n const scriptTimerRef = useRef<number | null>(null);\n const hasStylesRef = useRef(false);\n const hasScriptsRef = useRef(false);\n const hasRenderedContentRef = useRef(false);\n const prevResetTokenRef = useRef(resetToken);\n const MIN_LOADING_MS = 200;\n\n const clearTimer = (timerRef: React.MutableRefObject<number | null>) => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n\n const settleStateWithMinimumDelay = (\n setter: React.Dispatch<React.SetStateAction<boolean>>,\n timerRef: React.MutableRefObject<number | null>,\n startRef: React.MutableRefObject<number>,\n onDone?: () => void\n ) => {\n const elapsed = performance.now() - startRef.current;\n const delay = Math.max(0, MIN_LOADING_MS - elapsed);\n clearTimer(timerRef);\n timerRef.current = window.setTimeout(() => {\n setter(false);\n onDone?.();\n timerRef.current = null;\n }, delay);\n };\n\n useEffect(() => {\n const doc = containerRef.current?.ownerDocument;\n if (!doc) return;\n const styleId = \"sandbox-spinner-style\";\n let styleEl = doc.getElementById(styleId) as HTMLStyleElement | null;\n if (!styleEl) {\n styleEl = doc.createElement(\"style\");\n styleEl.id = styleId;\n doc.head?.appendChild(styleEl);\n }\n styleEl.textContent = `\n @keyframes sandbox-spin { from { transform: rotate(0deg);} to { transform: rotate(360deg);} }\n .sandbox-wrapper { align-items: center; }\n .sandbox-container { width: 100%; }\n .sandbox-container svg,\n .sandbox-container img { display: block; margin-left: auto; margin-right: auto; }\n .justify-\\\\[safe_center\\\\]{\n justify-content: safe center;\n }\n `;\n }, []);\n\n useEffect(() => {\n if (resetToken !== prevResetTokenRef.current) {\n hasRenderedContentRef.current = false;\n prevResetTokenRef.current = resetToken;\n }\n clearTimer(styleTimerRef);\n clearTimer(scriptTimerRef);\n hasStylesRef.current = false;\n hasScriptsRef.current = false;\n\n const container = containerRef.current;\n if (!container) return;\n const doc = container.ownerDocument;\n const body = doc?.body;\n if (!body) return;\n const reusableImages = collectReusableImages(container);\n\n appendedStylesRef.current.forEach((node) => node.remove());\n appendedStylesRef.current = [];\n appendedScriptsRef.current.forEach((node) => node.remove());\n appendedScriptsRef.current = [];\n\n const hasRenderedBefore = hasRenderedContentRef.current;\n setIsWaitingFirstDiv(!hasRenderedBefore);\n setIsGeneratingStyles(false);\n setIsGeneratingScripts(false);\n const wrapper = doc.createElement(\"div\");\n wrapper.innerHTML = html;\n\n const openScriptCount = (html.match(/<script[\\s>]/gi) || []).length;\n const closeScriptCount = (html.match(/<\\/script>/gi) || []).length;\n const shouldExecuteScripts =\n openScriptCount > 0 && openScriptCount === closeScriptCount;\n\n const resourceQueue: HTMLElement[] = [];\n\n Array.from(wrapper.querySelectorAll(\"style, script\")).forEach((node) => {\n if (node.tagName.toLowerCase() === \"style\") {\n const cloned = doc.createElement(\"style\");\n cloned.textContent = node.textContent || \"\";\n Array.from(node.attributes).forEach((attr) => {\n cloned.setAttribute(attr.name, attr.value);\n });\n resourceQueue.push(cloned);\n } else {\n const replacement = doc.createElement(\"script\");\n Array.from(node.attributes).forEach((attr) => {\n replacement.setAttribute(attr.name, attr.value);\n });\n replacement.textContent = node.textContent || \"\";\n resourceQueue.push(replacement);\n }\n node.remove();\n });\n reuseRenderedImages(wrapper, reusableImages);\n\n const hasStyles = resourceQueue.some(\n (node) => node.tagName.toLowerCase() === \"style\"\n );\n const hasScripts = resourceQueue.some(\n (node) => node.tagName.toLowerCase() === \"script\"\n );\n if (hasStyles) {\n hasStylesRef.current = true;\n styleStartRef.current = performance.now();\n clearTimer(styleTimerRef);\n setIsGeneratingStyles(true);\n }\n if (hasScripts) {\n hasScriptsRef.current = true;\n scriptStartRef.current = performance.now();\n clearTimer(scriptTimerRef);\n setIsGeneratingScripts(true);\n }\n\n const hasFirstElement = !!wrapper.firstElementChild;\n setIsWaitingFirstDiv(!hasFirstElement && !hasRenderedBefore);\n if (hasFirstElement) {\n hasRenderedContentRef.current = true;\n }\n\n container.innerHTML = \"\";\n const contentNodes = Array.from(wrapper.childNodes);\n container.append(...contentNodes);\n\n resourceQueue.forEach((node) => {\n if (node.tagName.toLowerCase() === \"style\") {\n doc.head?.appendChild(node);\n appendedStylesRef.current.push(node as HTMLStyleElement);\n return;\n }\n\n if (shouldExecuteScripts) {\n const scriptNode = node as HTMLScriptElement;\n const scriptText = scriptNode.textContent || \"\";\n const shouldValidate = !scriptNode.src;\n\n if (shouldValidate) {\n try {\n // Validate script is syntactically complete before executing\n\n new Function(scriptText);\n } catch {\n scriptNode.remove();\n return;\n }\n }\n\n try {\n body.appendChild(scriptNode);\n appendedScriptsRef.current.push(scriptNode);\n } catch {\n scriptNode.remove();\n }\n } else {\n // Defer execution until all script tags are fully received\n node.remove();\n }\n });\n requestAnimationFrame(() => {\n if (hasStyles) {\n settleStateWithMinimumDelay(\n setIsGeneratingStyles,\n styleTimerRef,\n styleStartRef,\n () => {\n hasStylesRef.current = false;\n }\n );\n }\n if (hasScripts) {\n settleStateWithMinimumDelay(\n setIsGeneratingScripts,\n scriptTimerRef,\n scriptStartRef,\n () => {\n hasScriptsRef.current = false;\n }\n );\n }\n });\n }, [html, resetToken]);\n\n useEffect(\n () => () => {\n clearTimer(styleTimerRef);\n clearTimer(scriptTimerRef);\n },\n []\n );\n\n const overlayMessage = (() => {\n if (isGeneratingScripts || hasScriptsRef.current)\n return scriptLoadingText || \"Building scripts cache...\";\n if (isGeneratingStyles || hasStylesRef.current)\n return styleLoadingText || \"Building styles...\";\n return null;\n })();\n\n const isBlackboard = mode === \"blackboard\";\n const sandboxWrapperStyle: React.CSSProperties = {\n position: \"relative\",\n width: \"100%\",\n height: isBlackboard ? \"100vh\" : \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n // Keep blackboard scroll behavior while centering content in non-blackboard mode\n justifyContent: isBlackboard ? \"space-around\" : \"flex-start\",\n };\n const sandboxContainerStyle: React.CSSProperties = {\n pointerEvents: overlayMessage ? \"none\" : undefined,\n margin: isBlackboard ? undefined : \"auto 0\",\n width: \"100%\",\n };\n\n return (\n <div\n ref={wrapperRef}\n data-root-vh={hasRootVhHeight ? \"true\" : \"false\"}\n className=\"sandbox-wrapper\"\n style={sandboxWrapperStyle}\n aria-busy={!!overlayMessage}\n >\n <div\n ref={containerRef}\n className=\"sandbox-container\"\n style={sandboxContainerStyle}\n />\n {overlayMessage && (\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: \"rgba(51, 51, 51, 0.80)\",\n color: \"#ffffff\",\n fontSize: 16,\n fontWeight: 700,\n gap: 10,\n pointerEvents: \"auto\",\n zIndex: 20,\n }}\n >\n <Loader2\n aria-hidden\n size={20}\n style={{ animation: \"sandbox-spin 1s linear infinite\" }}\n />\n {overlayMessage}\n </div>\n )}\n </div>\n );\n};\n\nexport default SandboxApp;\n"],"names":["IMAGE_REUSE_ATTRIBUTES","getImageReuseKey","image","attribute","collectReusableImages","root","imageMap","node","key","bucket","syncImageAttributes","sourceImage","targetImage","sourceAttributes","sourceAttributeNames","reuseRenderedImages","nextImage","preservedImage","SandboxApp","html","styleLoadingText","scriptLoadingText","resetToken","mode","hasRootVhHeight","wrapperRef","useRef","containerRef","setIsWaitingFirstDiv","useState","isGeneratingStyles","setIsGeneratingStyles","isGeneratingScripts","setIsGeneratingScripts","appendedStylesRef","appendedScriptsRef","styleStartRef","scriptStartRef","styleTimerRef","scriptTimerRef","hasStylesRef","hasScriptsRef","hasRenderedContentRef","prevResetTokenRef","MIN_LOADING_MS","clearTimer","timerRef","settleStateWithMinimumDelay","setter","startRef","onDone","elapsed","delay","useEffect","doc","styleId","styleEl","container","body","reusableImages","hasRenderedBefore","wrapper","openScriptCount","closeScriptCount","shouldExecuteScripts","resourceQueue","cloned","attr","replacement","hasStyles","hasScripts","hasFirstElement","contentNodes","scriptNode","scriptText","overlayMessage","isBlackboard","sandboxWrapperStyle","sandboxContainerStyle","jsxs","jsx","Loader2"],"mappings":"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"}
1
+ {"version":3,"file":"SandboxApp.cjs.js","sources":["../../../src/components/ContentRender/SandboxApp.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport { Loader2 } from \"lucide-react\";\n\nexport interface SandboxAppProps {\n html: string;\n styleLoadingText?: string;\n scriptLoadingText?: string;\n resetToken?: number;\n mode?: \"content\" | \"blackboard\";\n hasRootVhHeight?: boolean;\n stretchRootHeight?: boolean;\n}\n\nconst IMAGE_REUSE_ATTRIBUTES = [\n \"src\",\n \"srcset\",\n \"sizes\",\n \"alt\",\n \"class\",\n \"width\",\n \"height\",\n \"style\",\n \"loading\",\n \"decoding\",\n \"crossorigin\",\n \"referrerpolicy\",\n \"fetchpriority\",\n];\n\nconst getImageReuseKey = (image: HTMLImageElement) =>\n IMAGE_REUSE_ATTRIBUTES.map(\n (attribute) => `${attribute}:${image.getAttribute(attribute) || \"\"}`\n ).join(\"|\");\n\nconst collectReusableImages = (root: ParentNode) => {\n const imageMap = new Map<string, HTMLImageElement[]>();\n root.querySelectorAll(\"img\").forEach((node) => {\n const image = node as HTMLImageElement;\n const key = getImageReuseKey(image);\n const bucket = imageMap.get(key) || [];\n bucket.push(image);\n imageMap.set(key, bucket);\n });\n return imageMap;\n};\n\nconst syncImageAttributes = (\n sourceImage: HTMLImageElement,\n targetImage: HTMLImageElement\n) => {\n const sourceAttributes = Array.from(sourceImage.attributes);\n const sourceAttributeNames = new Set(\n sourceAttributes.map((attribute) => attribute.name)\n );\n\n Array.from(targetImage.attributes).forEach((attribute) => {\n if (!sourceAttributeNames.has(attribute.name)) {\n targetImage.removeAttribute(attribute.name);\n }\n });\n\n sourceAttributes.forEach((attribute) => {\n targetImage.setAttribute(attribute.name, attribute.value);\n });\n};\n\nconst reuseRenderedImages = (\n root: ParentNode,\n imageMap: Map<string, HTMLImageElement[]>\n) => {\n if (!imageMap.size) return;\n\n root.querySelectorAll(\"img\").forEach((node) => {\n const nextImage = node as HTMLImageElement;\n const key = getImageReuseKey(nextImage);\n const bucket = imageMap.get(key);\n const preservedImage = bucket?.shift();\n if (!preservedImage) return;\n\n syncImageAttributes(nextImage, preservedImage);\n nextImage.replaceWith(preservedImage);\n\n if (bucket && bucket.length === 0) {\n imageMap.delete(key);\n }\n });\n};\n\nconst SandboxApp: React.FC<SandboxAppProps> = ({\n html,\n styleLoadingText,\n scriptLoadingText,\n resetToken = 0,\n mode = \"content\",\n hasRootVhHeight = false,\n stretchRootHeight = false,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const [isGeneratingStyles, setIsGeneratingStyles] = useState(false);\n const [isGeneratingScripts, setIsGeneratingScripts] = useState(false);\n const appendedStylesRef = useRef<HTMLStyleElement[]>([]);\n const appendedScriptsRef = useRef<HTMLScriptElement[]>([]);\n const styleStartRef = useRef(0);\n const scriptStartRef = useRef(0);\n const styleTimerRef = useRef<number | null>(null);\n const scriptTimerRef = useRef<number | null>(null);\n const hasStylesRef = useRef(false);\n const hasScriptsRef = useRef(false);\n const hasRenderedContentRef = useRef(false);\n const prevResetTokenRef = useRef(resetToken);\n const MIN_LOADING_MS = 200;\n\n const clearTimer = (timerRef: React.MutableRefObject<number | null>) => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n\n const settleStateWithMinimumDelay = (\n setter: React.Dispatch<React.SetStateAction<boolean>>,\n timerRef: React.MutableRefObject<number | null>,\n startRef: React.MutableRefObject<number>,\n onDone?: () => void\n ) => {\n const elapsed = performance.now() - startRef.current;\n const delay = Math.max(0, MIN_LOADING_MS - elapsed);\n clearTimer(timerRef);\n timerRef.current = window.setTimeout(() => {\n setter(false);\n onDone?.();\n timerRef.current = null;\n }, delay);\n };\n\n useEffect(() => {\n const doc = containerRef.current?.ownerDocument;\n if (!doc) return;\n const styleId = \"sandbox-spinner-style\";\n let styleEl = doc.getElementById(styleId) as HTMLStyleElement | null;\n if (!styleEl) {\n styleEl = doc.createElement(\"style\");\n styleEl.id = styleId;\n doc.head?.appendChild(styleEl);\n }\n styleEl.textContent = `\n @keyframes sandbox-spin { from { transform: rotate(0deg);} to { transform: rotate(360deg);} }\n .sandbox-wrapper { align-items: center; }\n .sandbox-container { position: relative; width: 100%; }\n .sandbox-container svg,\n .sandbox-container img { display: block; margin-left: auto; margin-right: auto; }\n .justify-\\\\[safe_center\\\\]{\n justify-content: safe center;\n }\n `;\n }, []);\n\n useEffect(() => {\n if (resetToken !== prevResetTokenRef.current) {\n hasRenderedContentRef.current = false;\n prevResetTokenRef.current = resetToken;\n }\n clearTimer(styleTimerRef);\n clearTimer(scriptTimerRef);\n hasStylesRef.current = false;\n hasScriptsRef.current = false;\n\n const container = containerRef.current;\n if (!container) return;\n const doc = container.ownerDocument;\n const body = doc?.body;\n if (!body) return;\n const reusableImages = collectReusableImages(container);\n\n appendedStylesRef.current.forEach((node) => node.remove());\n appendedStylesRef.current = [];\n appendedScriptsRef.current.forEach((node) => node.remove());\n appendedScriptsRef.current = [];\n\n // const hasRenderedBefore = hasRenderedContentRef.current;\n setIsGeneratingStyles(false);\n setIsGeneratingScripts(false);\n const wrapper = doc.createElement(\"div\");\n wrapper.innerHTML = html;\n\n const openScriptCount = (html.match(/<script[\\s>]/gi) || []).length;\n const closeScriptCount = (html.match(/<\\/script>/gi) || []).length;\n const shouldExecuteScripts =\n openScriptCount > 0 && openScriptCount === closeScriptCount;\n\n const resourceQueue: HTMLElement[] = [];\n\n Array.from(wrapper.querySelectorAll(\"style, script\")).forEach((node) => {\n if (node.tagName.toLowerCase() === \"style\") {\n const cloned = doc.createElement(\"style\");\n cloned.textContent = node.textContent || \"\";\n Array.from(node.attributes).forEach((attr) => {\n cloned.setAttribute(attr.name, attr.value);\n });\n resourceQueue.push(cloned);\n } else {\n const replacement = doc.createElement(\"script\");\n Array.from(node.attributes).forEach((attr) => {\n replacement.setAttribute(attr.name, attr.value);\n });\n replacement.textContent = node.textContent || \"\";\n resourceQueue.push(replacement);\n }\n node.remove();\n });\n reuseRenderedImages(wrapper, reusableImages);\n\n const hasStyles = resourceQueue.some(\n (node) => node.tagName.toLowerCase() === \"style\"\n );\n const hasScripts = resourceQueue.some(\n (node) => node.tagName.toLowerCase() === \"script\"\n );\n if (hasStyles) {\n hasStylesRef.current = true;\n styleStartRef.current = performance.now();\n clearTimer(styleTimerRef);\n setIsGeneratingStyles(true);\n }\n if (hasScripts) {\n hasScriptsRef.current = true;\n scriptStartRef.current = performance.now();\n clearTimer(scriptTimerRef);\n setIsGeneratingScripts(true);\n }\n\n const hasFirstElement = !!wrapper.firstElementChild;\n if (hasFirstElement) {\n hasRenderedContentRef.current = true;\n }\n\n const contentNodes = Array.from(wrapper.childNodes);\n container.replaceChildren(...contentNodes);\n\n resourceQueue.forEach((node) => {\n if (node.tagName.toLowerCase() === \"style\") {\n doc.head?.appendChild(node);\n appendedStylesRef.current.push(node as HTMLStyleElement);\n return;\n }\n\n if (shouldExecuteScripts) {\n const scriptNode = node as HTMLScriptElement;\n const scriptText = scriptNode.textContent || \"\";\n const shouldValidate = !scriptNode.src;\n\n if (shouldValidate) {\n try {\n // Validate script is syntactically complete before executing\n\n new Function(scriptText);\n } catch {\n scriptNode.remove();\n return;\n }\n }\n\n try {\n body.appendChild(scriptNode);\n appendedScriptsRef.current.push(scriptNode);\n } catch {\n scriptNode.remove();\n }\n } else {\n // Defer execution until all script tags are fully received\n node.remove();\n }\n });\n requestAnimationFrame(() => {\n if (hasStyles) {\n settleStateWithMinimumDelay(\n setIsGeneratingStyles,\n styleTimerRef,\n styleStartRef,\n () => {\n hasStylesRef.current = false;\n }\n );\n }\n if (hasScripts) {\n settleStateWithMinimumDelay(\n setIsGeneratingScripts,\n scriptTimerRef,\n scriptStartRef,\n () => {\n hasScriptsRef.current = false;\n }\n );\n }\n });\n }, [html, resetToken]);\n\n useEffect(\n () => () => {\n clearTimer(styleTimerRef);\n clearTimer(scriptTimerRef);\n },\n []\n );\n\n const overlayMessage = (() => {\n if (isGeneratingScripts || hasScriptsRef.current)\n return scriptLoadingText || \"Building scripts cache...\";\n if (isGeneratingStyles || hasStylesRef.current)\n return styleLoadingText || \"Building styles...\";\n return null;\n })();\n\n const isBlackboard = mode === \"blackboard\";\n const shouldStretchRootHeight = isBlackboard && stretchRootHeight;\n const sandboxWrapperStyle: React.CSSProperties = {\n position: \"relative\",\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n // Keep blackboard scroll behavior while centering content in non-blackboard mode\n justifyContent: shouldStretchRootHeight\n ? \"flex-start\"\n : isBlackboard\n ? \"space-around\"\n : \"flex-start\",\n };\n const sandboxContainerStyle: React.CSSProperties = {\n pointerEvents: overlayMessage ? \"none\" : undefined,\n margin: isBlackboard ? undefined : \"auto 0\",\n width: \"100%\",\n height: shouldStretchRootHeight ? \"100%\" : undefined,\n minHeight: shouldStretchRootHeight ? 0 : undefined,\n flex: shouldStretchRootHeight ? \"1 1 auto\" : undefined,\n };\n\n return (\n <div\n data-root-vh={hasRootVhHeight ? \"true\" : \"false\"}\n className=\"sandbox-wrapper\"\n style={sandboxWrapperStyle}\n aria-busy={!!overlayMessage}\n >\n <div\n ref={containerRef}\n className=\"sandbox-container\"\n style={sandboxContainerStyle}\n />\n {overlayMessage && (\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: \"rgba(51, 51, 51, 0.80)\",\n color: \"#ffffff\",\n fontSize: 16,\n fontWeight: 700,\n gap: 10,\n pointerEvents: \"auto\",\n zIndex: 20,\n }}\n >\n <Loader2\n aria-hidden\n size={20}\n style={{ animation: \"sandbox-spin 1s linear infinite\" }}\n />\n {overlayMessage}\n </div>\n )}\n </div>\n );\n};\n\nexport default SandboxApp;\n"],"names":["IMAGE_REUSE_ATTRIBUTES","getImageReuseKey","image","attribute","collectReusableImages","root","imageMap","node","key","bucket","syncImageAttributes","sourceImage","targetImage","sourceAttributes","sourceAttributeNames","reuseRenderedImages","nextImage","preservedImage","SandboxApp","html","styleLoadingText","scriptLoadingText","resetToken","mode","hasRootVhHeight","stretchRootHeight","containerRef","useRef","isGeneratingStyles","setIsGeneratingStyles","useState","isGeneratingScripts","setIsGeneratingScripts","appendedStylesRef","appendedScriptsRef","styleStartRef","scriptStartRef","styleTimerRef","scriptTimerRef","hasStylesRef","hasScriptsRef","hasRenderedContentRef","prevResetTokenRef","MIN_LOADING_MS","clearTimer","timerRef","settleStateWithMinimumDelay","setter","startRef","onDone","elapsed","delay","useEffect","doc","styleId","styleEl","container","body","reusableImages","wrapper","openScriptCount","closeScriptCount","shouldExecuteScripts","resourceQueue","cloned","attr","replacement","hasStyles","hasScripts","contentNodes","scriptNode","scriptText","overlayMessage","isBlackboard","shouldStretchRootHeight","sandboxWrapperStyle","sandboxContainerStyle","jsxs","jsx","Loader2"],"mappings":"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"}
@@ -6,6 +6,7 @@ export interface SandboxAppProps {
6
6
  resetToken?: number;
7
7
  mode?: "content" | "blackboard";
8
8
  hasRootVhHeight?: boolean;
9
+ stretchRootHeight?: boolean;
9
10
  }
10
11
  declare const SandboxApp: React.FC<SandboxAppProps>;
11
12
  export default SandboxApp;
@@ -1,7 +1,7 @@
1
- import { j as w } from "../../_virtual/jsx-runtime.es.js";
2
- import { useRef as i, useState as M, useEffect as k } from "react";
3
- import Y from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/loader-circle.es.js";
4
- const Z = [
1
+ import { j as C } from "../../_virtual/jsx-runtime.es.js";
2
+ import { useRef as i, useState as F, useEffect as L } from "react";
3
+ import P from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/loader-circle.es.js";
4
+ const X = [
5
5
  "src",
6
6
  "srcset",
7
7
  "sizes",
@@ -13,171 +13,171 @@ const Z = [
13
13
  "loading",
14
14
  "decoding",
15
15
  "crossorigin",
16
- "referrerpolicy"
17
- ], U = (c) => Z.map(
16
+ "referrerpolicy",
17
+ "fetchpriority"
18
+ ], W = (c) => X.map(
18
19
  (t) => `${t}:${c.getAttribute(t) || ""}`
19
- ).join("|"), ee = (c) => {
20
+ ).join("|"), Y = (c) => {
20
21
  const t = /* @__PURE__ */ new Map();
21
22
  return c.querySelectorAll("img").forEach((u) => {
22
- const o = u, n = U(o), f = t.get(n) || [];
23
- f.push(o), t.set(n, f);
23
+ const o = u, r = W(o), f = t.get(r) || [];
24
+ f.push(o), t.set(r, f);
24
25
  }), t;
25
- }, te = (c, t) => {
26
+ }, Z = (c, t) => {
26
27
  const u = Array.from(c.attributes), o = new Set(
27
- u.map((n) => n.name)
28
+ u.map((r) => r.name)
28
29
  );
29
- Array.from(t.attributes).forEach((n) => {
30
- o.has(n.name) || t.removeAttribute(n.name);
31
- }), u.forEach((n) => {
32
- t.setAttribute(n.name, n.value);
30
+ Array.from(t.attributes).forEach((r) => {
31
+ o.has(r.name) || t.removeAttribute(r.name);
32
+ }), u.forEach((r) => {
33
+ t.setAttribute(r.name, r.value);
33
34
  });
34
- }, re = (c, t) => {
35
+ }, ee = (c, t) => {
35
36
  t.size && c.querySelectorAll("img").forEach((u) => {
36
- const o = u, n = U(o), f = t.get(n), h = f?.shift();
37
- h && (te(o, h), o.replaceWith(h), f && f.length === 0 && t.delete(n));
37
+ const o = u, r = W(o), f = t.get(r), h = f?.shift();
38
+ h && (Z(o, h), o.replaceWith(h), f && f.length === 0 && t.delete(r));
38
39
  });
39
- }, ae = ({
40
+ }, ce = ({
40
41
  html: c,
41
42
  styleLoadingText: t,
42
43
  scriptLoadingText: u,
43
44
  resetToken: o = 0,
44
- mode: n = "content",
45
- hasRootVhHeight: f = !1
45
+ mode: r = "content",
46
+ hasRootVhHeight: f = !1,
47
+ stretchRootHeight: h = !1
46
48
  }) => {
47
- const h = i(null), A = i(null), [, B] = M(!0), [V, C] = M(!1), [$, R] = M(!1), I = i([]), N = i([]), D = i(0), G = i(0), g = i(null), b = i(null), x = i(!1), S = i(!1), j = i(!1), z = i(o), K = 200, d = (r) => {
48
- r.current && (clearTimeout(r.current), r.current = null);
49
- }, W = (r, a, l, L) => {
50
- const v = performance.now() - l.current, p = Math.max(0, K - v);
49
+ const w = i(null), [H, R] = F(!1), [U, I] = F(!1), N = i([]), j = i([]), M = i(0), G = i(0), g = i(null), x = i(null), b = i(!1), S = i(!1), z = i(!1), B = i(o), V = 200, d = (n) => {
50
+ n.current && (clearTimeout(n.current), n.current = null);
51
+ }, D = (n, a, l, k) => {
52
+ const m = performance.now() - l.current, A = Math.max(0, V - m);
51
53
  d(a), a.current = window.setTimeout(() => {
52
- r(!1), L?.(), a.current = null;
53
- }, p);
54
+ n(!1), k?.(), a.current = null;
55
+ }, A);
54
56
  };
55
- k(() => {
56
- const r = A.current?.ownerDocument;
57
- if (!r) return;
57
+ L(() => {
58
+ const n = w.current?.ownerDocument;
59
+ if (!n) return;
58
60
  const a = "sandbox-spinner-style";
59
- let l = r.getElementById(a);
60
- l || (l = r.createElement("style"), l.id = a, r.head?.appendChild(l)), l.textContent = `
61
+ let l = n.getElementById(a);
62
+ l || (l = n.createElement("style"), l.id = a, n.head?.appendChild(l)), l.textContent = `
61
63
  @keyframes sandbox-spin { from { transform: rotate(0deg);} to { transform: rotate(360deg);} }
62
64
  .sandbox-wrapper { align-items: center; }
63
- .sandbox-container { width: 100%; }
65
+ .sandbox-container { position: relative; width: 100%; }
64
66
  .sandbox-container svg,
65
67
  .sandbox-container img { display: block; margin-left: auto; margin-right: auto; }
66
68
  .justify-\\[safe_center\\]{
67
69
  justify-content: safe center;
68
70
  }
69
71
  `;
70
- }, []), k(() => {
71
- o !== z.current && (j.current = !1, z.current = o), d(g), d(b), x.current = !1, S.current = !1;
72
- const r = A.current;
73
- if (!r) return;
74
- const a = r.ownerDocument, l = a?.body;
72
+ }, []), L(() => {
73
+ o !== B.current && (z.current = !1, B.current = o), d(g), d(x), b.current = !1, S.current = !1;
74
+ const n = w.current;
75
+ if (!n) return;
76
+ const a = n.ownerDocument, l = a?.body;
75
77
  if (!l) return;
76
- const L = ee(r);
77
- I.current.forEach((e) => e.remove()), I.current = [], N.current.forEach((e) => e.remove()), N.current = [];
78
- const v = j.current;
79
- B(!v), C(!1), R(!1);
80
- const p = a.createElement("div");
81
- p.innerHTML = c;
82
- const _ = (c.match(/<script[\s>]/gi) || []).length, J = (c.match(/<\/script>/gi) || []).length, P = _ > 0 && _ === J, y = [];
83
- Array.from(p.querySelectorAll("style, script")).forEach((e) => {
78
+ const k = Y(n);
79
+ N.current.forEach((e) => e.remove()), N.current = [], j.current.forEach((e) => e.remove()), j.current = [], R(!1), I(!1);
80
+ const m = a.createElement("div");
81
+ m.innerHTML = c;
82
+ const A = (c.match(/<script[\s>]/gi) || []).length, O = (c.match(/<\/script>/gi) || []).length, Q = A > 0 && A === O, y = [];
83
+ Array.from(m.querySelectorAll("style, script")).forEach((e) => {
84
84
  if (e.tagName.toLowerCase() === "style") {
85
85
  const s = a.createElement("style");
86
- s.textContent = e.textContent || "", Array.from(e.attributes).forEach((m) => {
87
- s.setAttribute(m.name, m.value);
86
+ s.textContent = e.textContent || "", Array.from(e.attributes).forEach((p) => {
87
+ s.setAttribute(p.name, p.value);
88
88
  }), y.push(s);
89
89
  } else {
90
90
  const s = a.createElement("script");
91
- Array.from(e.attributes).forEach((m) => {
92
- s.setAttribute(m.name, m.value);
91
+ Array.from(e.attributes).forEach((p) => {
92
+ s.setAttribute(p.name, p.value);
93
93
  }), s.textContent = e.textContent || "", y.push(s);
94
94
  }
95
95
  e.remove();
96
- }), re(p, L);
97
- const q = y.some(
96
+ }), ee(m, k);
97
+ const _ = y.some(
98
98
  (e) => e.tagName.toLowerCase() === "style"
99
- ), F = y.some(
99
+ ), q = y.some(
100
100
  (e) => e.tagName.toLowerCase() === "script"
101
101
  );
102
- q && (x.current = !0, D.current = performance.now(), d(g), C(!0)), F && (S.current = !0, G.current = performance.now(), d(b), R(!0));
103
- const H = !!p.firstElementChild;
104
- B(!H && !v), H && (j.current = !0), r.innerHTML = "";
105
- const X = Array.from(p.childNodes);
106
- r.append(...X), y.forEach((e) => {
102
+ _ && (b.current = !0, M.current = performance.now(), d(g), R(!0)), q && (S.current = !0, G.current = performance.now(), d(x), I(!0)), !!m.firstElementChild && (z.current = !0);
103
+ const J = Array.from(m.childNodes);
104
+ n.replaceChildren(...J), y.forEach((e) => {
107
105
  if (e.tagName.toLowerCase() === "style") {
108
- a.head?.appendChild(e), I.current.push(e);
106
+ a.head?.appendChild(e), N.current.push(e);
109
107
  return;
110
108
  }
111
- if (P) {
112
- const s = e, m = s.textContent || "";
109
+ if (Q) {
110
+ const s = e, p = s.textContent || "";
113
111
  if (!s.src)
114
112
  try {
115
- new Function(m);
113
+ new Function(p);
116
114
  } catch {
117
115
  s.remove();
118
116
  return;
119
117
  }
120
118
  try {
121
- l.appendChild(s), N.current.push(s);
119
+ l.appendChild(s), j.current.push(s);
122
120
  } catch {
123
121
  s.remove();
124
122
  }
125
123
  } else
126
124
  e.remove();
127
125
  }), requestAnimationFrame(() => {
128
- q && W(
129
- C,
126
+ _ && D(
127
+ R,
130
128
  g,
131
- D,
129
+ M,
132
130
  () => {
133
- x.current = !1;
131
+ b.current = !1;
134
132
  }
135
- ), F && W(
136
- R,
137
- b,
133
+ ), q && D(
134
+ I,
135
+ x,
138
136
  G,
139
137
  () => {
140
138
  S.current = !1;
141
139
  }
142
140
  );
143
141
  });
144
- }, [c, o]), k(
142
+ }, [c, o]), L(
145
143
  () => () => {
146
- d(g), d(b);
144
+ d(g), d(x);
147
145
  },
148
146
  []
149
147
  );
150
- const E = $ || S.current ? u || "Building scripts cache..." : V || x.current ? t || "Building styles..." : null, T = n === "blackboard", O = {
148
+ const v = U || S.current ? u || "Building scripts cache..." : H || b.current ? t || "Building styles..." : null, T = r === "blackboard", E = T && h, $ = {
151
149
  position: "relative",
152
150
  width: "100%",
153
- height: T ? "100vh" : "100%",
151
+ height: "100%",
154
152
  display: "flex",
155
153
  flexDirection: "column",
156
154
  // Keep blackboard scroll behavior while centering content in non-blackboard mode
157
- justifyContent: T ? "space-around" : "flex-start"
158
- }, Q = {
159
- pointerEvents: E ? "none" : void 0,
155
+ justifyContent: E ? "flex-start" : T ? "space-around" : "flex-start"
156
+ }, K = {
157
+ pointerEvents: v ? "none" : void 0,
160
158
  margin: T ? void 0 : "auto 0",
161
- width: "100%"
159
+ width: "100%",
160
+ height: E ? "100%" : void 0,
161
+ minHeight: E ? 0 : void 0,
162
+ flex: E ? "1 1 auto" : void 0
162
163
  };
163
- return /* @__PURE__ */ w.jsxs(
164
+ return /* @__PURE__ */ C.jsxs(
164
165
  "div",
165
166
  {
166
- ref: h,
167
167
  "data-root-vh": f ? "true" : "false",
168
168
  className: "sandbox-wrapper",
169
- style: O,
170
- "aria-busy": !!E,
169
+ style: $,
170
+ "aria-busy": !!v,
171
171
  children: [
172
- /* @__PURE__ */ w.jsx(
172
+ /* @__PURE__ */ C.jsx(
173
173
  "div",
174
174
  {
175
- ref: A,
175
+ ref: w,
176
176
  className: "sandbox-container",
177
- style: Q
177
+ style: K
178
178
  }
179
179
  ),
180
- E && /* @__PURE__ */ w.jsxs(
180
+ v && /* @__PURE__ */ C.jsxs(
181
181
  "div",
182
182
  {
183
183
  style: {
@@ -195,15 +195,15 @@ const Z = [
195
195
  zIndex: 20
196
196
  },
197
197
  children: [
198
- /* @__PURE__ */ w.jsx(
199
- Y,
198
+ /* @__PURE__ */ C.jsx(
199
+ P,
200
200
  {
201
201
  "aria-hidden": !0,
202
202
  size: 20,
203
203
  style: { animation: "sandbox-spin 1s linear infinite" }
204
204
  }
205
205
  ),
206
- E
206
+ v
207
207
  ]
208
208
  }
209
209
  )
@@ -212,6 +212,6 @@ const Z = [
212
212
  );
213
213
  };
214
214
  export {
215
- ae as default
215
+ ce as default
216
216
  };
217
217
  //# sourceMappingURL=SandboxApp.es.js.map