markdown-flow-ui 0.1.92 → 0.1.93-beta.0

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 (108) hide show
  1. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/@braintree_sanitize-url@7.1.1/node_modules/@braintree/sanitize-url/dist/index.cjs.js +1 -1
  2. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/@braintree_sanitize-url@7.1.1/node_modules/@braintree/sanitize-url/dist/index.cjs.js.map +1 -1
  3. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/@braintree_sanitize-url@7.1.1/node_modules/@braintree/sanitize-url/dist/index.es.js +1 -1
  4. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/classnames@2.5.1/node_modules/classnames/index.cjs.js +1 -1
  5. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/classnames@2.5.1/node_modules/classnames/index.es.js +1 -1
  6. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/diff@5.2.0/node_modules/diff/lib/index.cjs.js +6 -0
  7. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/diff@5.2.0/node_modules/diff/lib/index.cjs.js.map +1 -0
  8. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/diff@5.2.0/node_modules/diff/lib/index.es.js +350 -0
  9. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/diff@5.2.0/node_modules/diff/lib/index.es.js.map +1 -0
  10. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/c4Diagram-YG6GDRKO.cjs.js +1 -1
  11. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/c4Diagram-YG6GDRKO.es.js +1 -1
  12. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/chunk-S3R3BYOJ.cjs.js +1 -1
  13. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/chunk-S3R3BYOJ.es.js +1 -1
  14. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/chunk-TZMSLE5B.cjs.js +1 -1
  15. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/chunk-TZMSLE5B.es.js +1 -1
  16. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/ganttDiagram-LVOFAZNH.cjs.js +1 -1
  17. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/ganttDiagram-LVOFAZNH.es.js +1 -1
  18. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/sequenceDiagram-WL72ISMW.cjs.js +1 -1
  19. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/sequenceDiagram-WL72ISMW.es.js +1 -1
  20. 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
  21. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-input@1.8.0_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-input/es/BaseInput.es.js +1 -1
  22. 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
  23. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-textarea@1.10.2_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-textarea/es/ResizableTextArea.es.js +1 -1
  24. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-textarea@1.10.2_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-textarea/es/TextArea.cjs.js +1 -1
  25. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-textarea@1.10.2_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-textarea/es/TextArea.es.js +1 -1
  26. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-textarea@1.10.2_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-textarea/es/index.cjs.js +1 -1
  27. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-textarea@1.10.2_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-textarea/es/index.es.js +1 -1
  28. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-flow@0.1.6/node_modules/remark-flow/dist/index.cjs.js +1 -1
  29. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-flow@0.1.6/node_modules/remark-flow/dist/index.es.js +1 -1
  30. 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
  31. 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
  32. 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
  33. 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
  34. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/style-to-object@1.0.11/node_modules/style-to-object/cjs/index.cjs.js +1 -1
  35. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/style-to-object@1.0.11/node_modules/style-to-object/cjs/index.es.js +1 -1
  36. package/dist/_virtual/index.cjs10.js +1 -1
  37. package/dist/_virtual/index.cjs2.js +1 -1
  38. package/dist/_virtual/index.cjs3.js +1 -1
  39. package/dist/_virtual/index.cjs4.js +1 -1
  40. package/dist/_virtual/index.cjs7.js +1 -1
  41. package/dist/_virtual/index.cjs8.js +1 -1
  42. package/dist/_virtual/index.es10.js +2 -2
  43. package/dist/_virtual/index.es2.js +5 -2
  44. package/dist/_virtual/index.es2.js.map +1 -1
  45. package/dist/_virtual/index.es3.js +2 -4
  46. package/dist/_virtual/index.es3.js.map +1 -1
  47. package/dist/_virtual/index.es4.js +4 -5
  48. package/dist/_virtual/index.es4.js.map +1 -1
  49. package/dist/_virtual/index.es7.js +2 -3
  50. package/dist/_virtual/index.es7.js.map +1 -1
  51. package/dist/_virtual/index.es8.js +3 -2
  52. package/dist/_virtual/index.es8.js.map +1 -1
  53. package/dist/components/ContentRender/ContentRender.cjs.js +2 -2
  54. package/dist/components/ContentRender/ContentRender.cjs.js.map +1 -1
  55. package/dist/components/ContentRender/ContentRender.es.js +111 -104
  56. package/dist/components/ContentRender/ContentRender.es.js.map +1 -1
  57. package/dist/components/ContentRender/ContentRender.stories.d.ts +1 -0
  58. package/dist/components/ContentRender/IframeSandbox.cjs.js +6 -5
  59. package/dist/components/ContentRender/IframeSandbox.cjs.js.map +1 -1
  60. package/dist/components/ContentRender/IframeSandbox.es.js +104 -98
  61. package/dist/components/ContentRender/IframeSandbox.es.js.map +1 -1
  62. package/dist/components/ContentRender/SandboxApp.cjs.js +3 -2
  63. package/dist/components/ContentRender/SandboxApp.cjs.js.map +1 -1
  64. package/dist/components/ContentRender/SandboxApp.es.js +92 -84
  65. package/dist/components/ContentRender/SandboxApp.es.js.map +1 -1
  66. package/dist/components/ContentRender/blackboard/blackboard-runtime.cjs.js +5 -0
  67. package/dist/components/ContentRender/blackboard/blackboard-runtime.cjs.js.map +1 -0
  68. package/dist/components/ContentRender/blackboard/blackboard-runtime.d.ts +18 -0
  69. package/dist/components/ContentRender/blackboard/blackboard-runtime.es.js +137 -0
  70. package/dist/components/ContentRender/blackboard/blackboard-runtime.es.js.map +1 -0
  71. package/dist/components/ContentRender/blackboard/diff-parser.cjs.js +2 -0
  72. package/dist/components/ContentRender/blackboard/diff-parser.cjs.js.map +1 -0
  73. package/dist/components/ContentRender/blackboard/diff-parser.d.ts +8 -0
  74. package/dist/components/ContentRender/blackboard/diff-parser.es.js +132 -0
  75. package/dist/components/ContentRender/blackboard/diff-parser.es.js.map +1 -0
  76. package/dist/components/ContentRender/blackboard/diff-parser.test.d.ts +1 -0
  77. package/dist/components/ContentRender/blackboard-vendor.cjs.js +2 -0
  78. package/dist/components/ContentRender/blackboard-vendor.cjs.js.map +1 -0
  79. package/dist/components/ContentRender/blackboard-vendor.d.ts +5 -0
  80. package/dist/components/ContentRender/blackboard-vendor.es.js +15 -0
  81. package/dist/components/ContentRender/blackboard-vendor.es.js.map +1 -0
  82. package/dist/components/ContentRender/index.cjs.js +1 -1
  83. package/dist/components/ContentRender/index.es.js +1 -0
  84. package/dist/components/ContentRender/index.es.js.map +1 -1
  85. package/dist/components/ContentRender/utils/split-content.cjs.js +2 -2
  86. package/dist/components/ContentRender/utils/split-content.cjs.js.map +1 -1
  87. package/dist/components/ContentRender/utils/split-content.es.js +118 -109
  88. package/dist/components/ContentRender/utils/split-content.es.js.map +1 -1
  89. package/dist/components/ContentRender/vendor/daisyui-v4.min.css.cjs.js +22 -0
  90. package/dist/components/ContentRender/vendor/daisyui-v4.min.css.cjs.js.map +1 -0
  91. package/dist/components/ContentRender/vendor/daisyui-v4.min.css.es.js +25 -0
  92. package/dist/components/ContentRender/vendor/daisyui-v4.min.css.es.js.map +1 -0
  93. package/dist/components/ContentRender/vendor/gsap-v3.min.cjs.js +12 -0
  94. package/dist/components/ContentRender/vendor/gsap-v3.min.cjs.js.map +1 -0
  95. package/dist/components/ContentRender/vendor/gsap-v3.min.es.js +15 -0
  96. package/dist/components/ContentRender/vendor/gsap-v3.min.es.js.map +1 -0
  97. package/dist/components/ContentRender/vendor/tailwindcss-v3.min.cjs.js +2 -0
  98. package/dist/components/ContentRender/vendor/tailwindcss-v3.min.cjs.js.map +1 -0
  99. package/dist/components/ContentRender/vendor/tailwindcss-v3.min.es.js +5 -0
  100. package/dist/components/ContentRender/vendor/tailwindcss-v3.min.es.js.map +1 -0
  101. package/dist/components/MarkdownFlow/MarkdownFlow.cjs.js +1 -1
  102. package/dist/components/MarkdownFlow/MarkdownFlow.cjs.js.map +1 -1
  103. package/dist/components/MarkdownFlow/MarkdownFlow.es.js +3 -2
  104. package/dist/components/MarkdownFlow/MarkdownFlow.es.js.map +1 -1
  105. package/dist/components/ui/inputGroup/textarea.cjs.js +1 -1
  106. package/dist/components/ui/inputGroup/textarea.es.js +1 -1
  107. package/dist/markdown-flow-ui-lib.css +1 -1
  108. package/package.json +4 -1
@@ -24,49 +24,49 @@ import me from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/reh
24
24
  import de from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-gfm@4.0.1/node_modules/remark-gfm/lib/index.es.js";
25
25
  import ue from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-math@6.0.0/node_modules/remark-math/lib/index.es.js";
26
26
  import pe from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-breaks@4.0.0/node_modules/remark-breaks/lib/index.es.js";
27
- const G = ({ svg: s }) => {
28
- const o = D(null);
27
+ const G = ({ svg: o }) => {
28
+ const c = D(null);
29
29
  return V(() => {
30
- const a = o.current;
31
- if (!a) return;
32
- const i = a.shadowRoot ?? a.attachShadow({ mode: "open" }), w = "content-render-svg-style";
33
- let d = i.getElementById(w);
34
- d || (d = document.createElement("style"), d.id = w, d.textContent = `
30
+ const s = c.current;
31
+ if (!s) return;
32
+ const a = s.shadowRoot ?? s.attachShadow({ mode: "open" }), i = "content-render-svg-style";
33
+ let u = a.getElementById(i);
34
+ u || (u = document.createElement("style"), u.id = i, u.textContent = `
35
35
  svg { height: auto; display: inline-block; }
36
36
  svg.content-render-svg-el--responsive { width: 100%; max-width: 100%; }
37
37
  svg.content-render-svg-el--fixed { max-width: none; }
38
- `, i.appendChild(d)), Array.from(i.childNodes).filter(
39
- (n) => n !== d
40
- ).forEach((n) => i.removeChild(n));
41
- const k = document.createElement("template"), M = X(s);
42
- k.innerHTML = M, i.append(k.content.cloneNode(!0));
43
- let b = !1, S = !1;
44
- i.querySelectorAll("svg").forEach((n) => {
38
+ `, a.appendChild(u)), Array.from(a.childNodes).filter(
39
+ (n) => n !== u
40
+ ).forEach((n) => a.removeChild(n));
41
+ const k = document.createElement("template"), T = X(o);
42
+ k.innerHTML = T, a.append(k.content.cloneNode(!0));
43
+ let y = !1, S = !1;
44
+ a.querySelectorAll("svg").forEach((n) => {
45
45
  const C = n.getAttribute("viewBox");
46
46
  if (!C) return;
47
- const y = C.trim().split(/[\s,]+/).map((c) => Number(c));
48
- if (y.length !== 4 || y.some(Number.isNaN)) return;
49
- const [, , h, u] = y, f = n.getAttribute("width"), x = n.getAttribute("height"), L = (c) => {
50
- if (!c) return !1;
51
- const e = c.trim().toLowerCase();
47
+ const j = C.trim().split(/[\s,]+/).map((l) => Number(l));
48
+ if (j.length !== 4 || j.some(Number.isNaN)) return;
49
+ const [, , x, h] = j, p = n.getAttribute("width"), v = n.getAttribute("height"), L = (l) => {
50
+ if (!l) return !1;
51
+ const e = l.trim().toLowerCase();
52
52
  return e === "auto" || e.endsWith("%");
53
- }, B = (c) => {
54
- if (!c) return null;
55
- const e = c.trim().toLowerCase();
53
+ }, $ = (l) => {
54
+ if (!l) return null;
55
+ const e = l.trim().toLowerCase();
56
56
  if (e === "auto" || e.endsWith("%"))
57
57
  return null;
58
58
  const r = Number.parseFloat(e);
59
59
  return Number.isNaN(r) ? null : r;
60
- }, $ = L(f), j = L(x), N = !f || f === "0", g = !x || x === "0", p = B(f), T = B(x);
61
- if ($ || j || N && g || p === h && T === u) {
62
- b = !0, n.classList.add("content-render-svg-el--responsive"), n.classList.remove("content-render-svg-el--fixed"), n.style.width = "100%", n.style.height = "auto", !n.style.aspectRatio && u > 0 && (n.style.aspectRatio = `${h} / ${u}`);
60
+ }, B = L(p), N = L(v), w = !p || p === "0", g = !v || v === "0", f = $(p), I = $(v);
61
+ if (B || N || w && g || f === x && I === h) {
62
+ y = !0, n.classList.add("content-render-svg-el--responsive"), n.classList.remove("content-render-svg-el--fixed"), n.style.width = "100%", n.style.height = "auto", !n.style.aspectRatio && h > 0 && (n.style.aspectRatio = `${x} / ${h}`);
63
63
  return;
64
64
  }
65
- S = !0, n.classList.add("content-render-svg-el--fixed"), n.classList.remove("content-render-svg-el--responsive"), N && h > 0 && n.setAttribute("width", `${h}`), g && u > 0 && n.setAttribute("height", `${u}`);
65
+ S = !0, n.classList.add("content-render-svg-el--fixed"), n.classList.remove("content-render-svg-el--responsive"), w && x > 0 && n.setAttribute("width", `${x}`), g && h > 0 && n.setAttribute("height", `${h}`);
66
66
  });
67
- const R = b && !S;
68
- a.classList.toggle("content-render-svg--responsive", R), a.classList.toggle("content-render-svg--fixed", !R);
69
- }, [s]), /* @__PURE__ */ t.jsx("div", { className: "content-render-svg-scroll", children: /* @__PURE__ */ t.jsx("div", { className: "content-render-svg", ref: o }) });
67
+ const R = y && !S;
68
+ s.classList.toggle("content-render-svg--responsive", R), s.classList.toggle("content-render-svg--fixed", !R);
69
+ }, [o]), /* @__PURE__ */ t.jsx("div", { className: "content-render-svg-scroll", children: /* @__PURE__ */ t.jsx("div", { className: "content-render-svg", ref: c }) });
70
70
  }, he = [de, ue, O, pe], fe = [
71
71
  ee,
72
72
  ce,
@@ -74,66 +74,73 @@ const G = ({ svg: s }) => {
74
74
  te,
75
75
  [le, { languages: ne, subset: re }],
76
76
  me
77
- ], K = ({ content: s, components: o }) => /* @__PURE__ */ t.jsx("div", { className: "markdown-renderer", children: /* @__PURE__ */ t.jsx(
77
+ ], K = ({ content: o, components: c }) => /* @__PURE__ */ t.jsx("div", { className: "markdown-renderer", children: /* @__PURE__ */ t.jsx(
78
78
  ie,
79
79
  {
80
80
  remarkPlugins: he,
81
81
  rehypePlugins: fe,
82
- components: o,
83
- children: s
82
+ components: c,
83
+ children: o
84
84
  }
85
- ) }), xe = (s) => {
86
- if (s.length <= 1) return s;
87
- const o = [];
88
- return s.forEach((a) => {
85
+ ) }), xe = (o, c = !1) => {
86
+ if (o.length <= 1) return o;
87
+ const s = [];
88
+ return o.forEach((a) => {
89
+ const i = s[s.length - 1];
90
+ if (c && a.type === "sandbox" && i?.type === "sandbox") {
91
+ s[s.length - 1] = {
92
+ type: "sandbox",
93
+ value: `${i.value}${a.value}`
94
+ };
95
+ return;
96
+ }
89
97
  if (a.type === "sandbox") {
90
- o.push(a);
98
+ s.push(a);
91
99
  return;
92
100
  }
93
- const i = o[o.length - 1];
94
101
  if (i && i.type !== "sandbox") {
95
- o[o.length - 1] = {
102
+ s[s.length - 1] = {
96
103
  type: "markdown",
97
104
  value: `${i.value}${a.value}`
98
105
  };
99
106
  return;
100
107
  }
101
- o.push({ type: "markdown", value: a.value });
102
- }), o;
108
+ s.push({ type: "markdown", value: a.value });
109
+ }), s;
103
110
  }, qe = ({
104
- content: s,
105
- customRenderBar: o,
106
- onSend: a,
107
- typingSpeed: i = 30,
108
- enableTypewriter: w = !1,
109
- defaultButtonText: d,
111
+ content: o,
112
+ customRenderBar: c,
113
+ onSend: s,
114
+ typingSpeed: a = 30,
115
+ enableTypewriter: i = !1,
116
+ defaultButtonText: u,
110
117
  defaultInputText: W,
111
118
  defaultSelectedValues: k,
112
- readonly: M = !1,
113
- onTypeFinished: b,
119
+ readonly: T = !1,
120
+ onTypeFinished: y,
114
121
  confirmButtonText: S,
115
122
  copyButtonText: R,
116
123
  copiedButtonText: n,
117
124
  sandboxLoadingText: C,
118
- sandboxStyleLoadingText: y,
119
- sandboxScriptLoadingText: h,
120
- sandboxFullscreenButtonText: u,
121
- sandboxMode: f = "content",
122
- onClickCustomButtonAfterContent: x,
125
+ sandboxStyleLoadingText: j,
126
+ sandboxScriptLoadingText: x,
127
+ sandboxFullscreenButtonText: h,
128
+ sandboxMode: p = "content",
129
+ onClickCustomButtonAfterContent: v,
123
130
  beforeSend: L
124
131
  // tooltipMinLength,
125
132
  }) => {
126
- const B = A(
127
- () => q(s),
128
- [s]
129
- ), $ = {
133
+ const $ = A(
134
+ () => q(o),
135
+ [o]
136
+ ), B = {
130
137
  "custom-button-after-content": ({
131
138
  children: e
132
139
  }) => /* @__PURE__ */ t.jsx(
133
140
  "button",
134
141
  {
135
142
  className: "content-render-custom-button-after-content",
136
- onClick: x,
143
+ onClick: v,
137
144
  children: /* @__PURE__ */ t.jsx("span", { className: "content-render-custom-button-after-content-inner", children: e })
138
145
  }
139
146
  ),
@@ -141,30 +148,30 @@ const G = ({ svg: s }) => {
141
148
  Z,
142
149
  {
143
150
  ...e,
144
- readonly: M,
145
- defaultButtonText: d,
151
+ readonly: T,
152
+ defaultButtonText: u,
146
153
  defaultInputText: W,
147
154
  defaultSelectedValues: k,
148
- onSend: a,
155
+ onSend: s,
149
156
  beforeSend: L,
150
157
  confirmButtonText: S
151
158
  }
152
159
  ),
153
160
  code: (e) => {
154
- const { className: r, children: l, ...I } = e;
161
+ const { className: r, children: m, ...M } = e;
155
162
  if (/language-(\w+)/.exec(r || "")?.[1] === "mermaid") {
156
- const v = l?.toString().replace(/\n$/, "") || "", J = se(s, v);
157
- return /* @__PURE__ */ t.jsx(H, { chart: v, frozen: J });
163
+ const b = m?.toString().replace(/\n$/, "") || "", J = se(o, b);
164
+ return /* @__PURE__ */ t.jsx(H, { chart: b, frozen: J });
158
165
  }
159
- return /* @__PURE__ */ t.jsx("code", { className: r, ...I, children: l });
166
+ return /* @__PURE__ */ t.jsx("code", { className: r, ...M, children: m });
160
167
  },
161
168
  table: ({ ...e }) => /* @__PURE__ */ t.jsx("div", { className: "content-render-table-container", children: /* @__PURE__ */ t.jsx("table", { className: "content-render-table", ...e }) }),
162
169
  th: ({ ...e }) => /* @__PURE__ */ t.jsx("th", { className: "content-render-th", ...e }),
163
170
  td: ({ ...e }) => /* @__PURE__ */ t.jsx("td", { className: "content-render-td", ...e }),
164
171
  tr: ({ ...e }) => /* @__PURE__ */ t.jsx("tr", { className: "content-render-tr", ...e }),
165
172
  li: ({ node: e, ...r }) => {
166
- const l = e?.properties?.className;
167
- return typeof l == "string" && l.includes("task-list-item") || Array.isArray(l) && l.includes("task-list-item") ? /* @__PURE__ */ t.jsx("li", { className: "content-render-task-list-item", ...r }) : /* @__PURE__ */ t.jsx("li", { ...r });
173
+ const m = e?.properties?.className;
174
+ return typeof m == "string" && m.includes("task-list-item") || Array.isArray(m) && m.includes("task-list-item") ? /* @__PURE__ */ t.jsx("li", { className: "content-render-task-list-item", ...r }) : /* @__PURE__ */ t.jsx("li", { ...r });
168
175
  },
169
176
  ol: ({ ...e }) => /* @__PURE__ */ t.jsx("ol", { className: "content-render-ol", ...e }),
170
177
  ul: ({ ...e }) => /* @__PURE__ */ t.jsx("ul", { className: "content-render-ul", ...e }),
@@ -186,44 +193,44 @@ const G = ({ svg: s }) => {
186
193
  copiedButtonText: n
187
194
  }
188
195
  )
189
- }, { displayContent: j, isComplete: N } = E({
196
+ }, { displayContent: N, isComplete: w } = E({
190
197
  // processMarkdownText will let code block printf("You win!\n") become printf("You win!<br/>");
191
198
  // content: processMarkdownText(content),
192
- content: B,
193
- typingSpeed: i,
194
- disabled: !w
199
+ content: $,
200
+ typingSpeed: a,
201
+ disabled: !i
195
202
  }), g = A(
196
- () => ae(s, !0),
197
- [s]
198
- ), p = g.some(
203
+ () => ae(o, !0),
204
+ [o]
205
+ ), f = g.some(
199
206
  (e) => e.type === "sandbox"
200
- ), T = A(
201
- () => xe(g),
202
- [g]
207
+ ), I = A(
208
+ () => xe(g, p === "blackboard"),
209
+ [g, p]
203
210
  ), F = A(
204
- () => U(j),
205
- [j]
211
+ () => U(N),
212
+ [N]
206
213
  ), z = D(!1);
207
214
  V(() => {
208
- p || N && !z.current && (z.current = !0, b?.());
209
- }, [p, N, b]), V(() => {
210
- p || (z.current = !1);
211
- }, [p, s]);
212
- const c = (e, r) => {
213
- const l = q(e);
214
- return U(l).map((m, P) => {
215
- const v = `${r}-${m.type}-${P}`;
216
- return m.type === "text" ? /* @__PURE__ */ t.jsx(
215
+ f || w && !z.current && (z.current = !0, y?.());
216
+ }, [f, w, y]), V(() => {
217
+ f || (z.current = !1);
218
+ }, [f, o]);
219
+ const l = (e, r) => {
220
+ const m = q(e);
221
+ return U(m).map((d, P) => {
222
+ const b = `${r}-${d.type}-${P}`;
223
+ return d.type === "text" ? /* @__PURE__ */ t.jsx(
217
224
  K,
218
225
  {
219
- components: $,
220
- content: m.value
226
+ components: B,
227
+ content: d.value
221
228
  },
222
- v
223
- ) : m.type === "mermaid" ? /* @__PURE__ */ t.jsx(H, { chart: m.value, frozen: !m.complete }, v) : m.type === "svg" ? /* @__PURE__ */ t.jsx(G, { svg: m.value }, v) : null;
229
+ b
230
+ ) : d.type === "mermaid" ? /* @__PURE__ */ t.jsx(H, { chart: d.value, frozen: !d.complete }, b) : d.type === "svg" ? /* @__PURE__ */ t.jsx(G, { svg: d.value }, b) : null;
224
231
  });
225
232
  };
226
- return p ? /* @__PURE__ */ t.jsx("div", { className: "content-render markdown-body", children: T.map(
233
+ return f ? /* @__PURE__ */ t.jsx("div", { className: "content-render markdown-body", children: I.map(
227
234
  (e, r) => e.type === "sandbox" ? /* @__PURE__ */ t.jsx(
228
235
  oe,
229
236
  {
@@ -231,20 +238,20 @@ const G = ({ svg: s }) => {
231
238
  content: e.value,
232
239
  className: "content-render-iframe",
233
240
  loadingText: C,
234
- styleLoadingText: y,
235
- scriptLoadingText: h,
236
- fullScreenButtonText: u,
237
- mode: f
241
+ styleLoadingText: j,
242
+ scriptLoadingText: x,
243
+ fullScreenButtonText: h,
244
+ mode: p
238
245
  },
239
246
  `sandbox-${r}`
240
- ) : /* @__PURE__ */ t.jsx(_.Fragment, { children: c(e.value, `md-${r}`) }, `md-${r}`)
247
+ ) : /* @__PURE__ */ t.jsx(_.Fragment, { children: l(e.value, `md-${r}`) }, `md-${r}`)
241
248
  ) }) : /* @__PURE__ */ t.jsxs("div", { className: "content-render markdown-body", children: [
242
249
  F.map((e, r) => {
243
250
  if (e.type === "text")
244
251
  return /* @__PURE__ */ t.jsx(
245
252
  K,
246
253
  {
247
- components: $,
254
+ components: B,
248
255
  content: e.value
249
256
  },
250
257
  r
@@ -261,10 +268,10 @@ const G = ({ svg: s }) => {
261
268
  if (e.type === "svg")
262
269
  return /* @__PURE__ */ t.jsx(G, { svg: e.value }, r);
263
270
  }),
264
- o && /* @__PURE__ */ t.jsx("div", { className: "content-render-custom-bar", children: _.createElement(o, {
265
- content: s,
266
- displayContent: j,
267
- onSend: a
271
+ c && /* @__PURE__ */ t.jsx("div", { className: "content-render-custom-bar", children: _.createElement(c, {
272
+ content: o,
273
+ displayContent: N,
274
+ onSend: s
268
275
  }) })
269
276
  ] });
270
277
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ContentRender.es.js","sources":["../../../src/components/ContentRender/ContentRender.tsx"],"sourcesContent":["import \"highlight.js/styles/github.css\";\nimport \"katex/dist/katex.min.css\";\nimport React, { useEffect, useMemo, useRef } from \"react\";\nimport ReactMarkdown from \"react-markdown\";\nimport rehypeHighlight from \"rehype-highlight\";\nimport rehypeKatex from \"rehype-katex\";\nimport rehypeRaw from \"rehype-raw\";\nimport remarkBreaks from \"remark-breaks\";\nimport remarkFlow from \"remark-flow\";\nimport remarkGfm from \"remark-gfm\";\nimport remarkMath from \"remark-math\";\nimport { CustomRenderBarProps, OnSendContentParams } from \"../types\";\nimport { sanitizeInvalidTagName } from \"./utils/sanitize-invalid-tag-name\";\nimport { stripSvgTextLineBreaks } from \"./utils/strip-svg-text-line-breaks\";\nimport \"./contentRender.css\";\nimport \"./github-markdown-light.css\";\nimport CodeBlock from \"./CodeBlock\";\nimport CustomButtonInputVariable, {\n ComponentsWithCustomVariable,\n} from \"./plugins/CustomVariable\";\nimport MermaidChart from \"./plugins/MermaidChart\";\nimport useTypewriterStateMachine from \"./useTypewriterStateMachine\";\nimport {\n preserveCustomVariableProperties,\n restoreCustomVariableProperties,\n} from \"./utils/custom-variable-props\";\nimport {\n highlightLanguages,\n subsetLanguages,\n} from \"./utils/highlight-languages\";\n// import { processMarkdownText } from \"./utils/process-markdown\";\nimport {\n parseMarkdownSegments,\n mermaidBlockIsComplete,\n} from \"./utils/mermaid-parse\";\nimport { normalizeInlineHtml } from \"./utils/normalize-inline-html\";\nimport IframeSandbox from \"./IframeSandbox\";\nimport {\n splitContentSegments,\n type RenderSegment,\n} from \"./utils/split-content\";\n// Define component Props type\nexport interface ContentRenderProps {\n content: string;\n /**\n+ * Callback invoked when the custom button after content is clicked.\n+ * This button is rendered via the `<custom-button-after-content>` tag in markdown content.\n+ * @example\n+ * ```tsx\n+ * <ContentRender\n+ * content=\"Hello <custom-button-after-content>Ask</custom-button-after-content>\"\n+ * onClickCustomButtonAfterContent={() => console.log('Button clicked')}\n+ * />\n+ * ```\n+ */\n customRenderBar?: CustomRenderBarProps;\n onClickCustomButtonAfterContent?: () => void;\n onSend?: (content: OnSendContentParams) => void;\n typingSpeed?: number;\n enableTypewriter?: boolean;\n defaultButtonText?: string;\n defaultInputText?: string; // Text input by user\n defaultSelectedValues?: string[]; // Default selected values for multi-select\n readonly?: boolean;\n onTypeFinished?: () => void;\n // Multi-select confirm button text (i18n support)\n confirmButtonText?: string;\n // Copy button text (i18n support)\n copyButtonText?: string;\n // Copied state text (i18n support)\n copiedButtonText?: string;\n // Dynamic interaction format for multi-select support\n dynamicInteractionFormat?: string;\n // Loading text before first HTML block renders inside iframe (i18n support)\n sandboxLoadingText?: string;\n // Loading text while styles are being generated inside iframe\n sandboxStyleLoadingText?: string;\n // Loading text while scripts are being cached/executed inside iframe\n sandboxScriptLoadingText?: string;\n // Fullscreen button text for iframe sandbox\n sandboxFullscreenButtonText?: string;\n // Sandbox render mode\n sandboxMode?: \"content\" | \"blackboard\";\n beforeSend?: (param: OnSendContentParams) => boolean;\n // tooltipMinLength?: number; // Control minimum character length for tooltip display, default 10\n}\n\n// Render svg string via Shadow DOM to avoid markdown wrapping\nconst SvgBlockInShadow: React.FC<{ svg: string }> = ({ svg }) => {\n const hostRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const host = hostRef.current;\n if (!host) return;\n const shadowRoot = host.shadowRoot ?? host.attachShadow({ mode: \"open\" });\n const styleId = \"content-render-svg-style\";\n let styleEl = shadowRoot.getElementById(styleId) as HTMLStyleElement | null;\n\n if (!styleEl) {\n styleEl = document.createElement(\"style\");\n styleEl.id = styleId;\n // Keep intrinsic SVG width so the wrapper can scroll horizontally when needed\n styleEl.textContent = `\n svg { height: auto; display: inline-block; }\n svg.content-render-svg-el--responsive { width: 100%; max-width: 100%; }\n svg.content-render-svg-el--fixed { max-width: none; }\n `;\n shadowRoot.appendChild(styleEl);\n }\n\n const nodesToRemove = Array.from(shadowRoot.childNodes).filter(\n (node) => node !== styleEl\n );\n nodesToRemove.forEach((node) => shadowRoot.removeChild(node));\n\n const template = document.createElement(\"template\");\n const cleanedSvg = stripSvgTextLineBreaks(svg);\n template.innerHTML = cleanedSvg;\n shadowRoot.append(template.content.cloneNode(true));\n\n let hasResponsiveSvg = false;\n let hasFixedSvg = false;\n\n shadowRoot.querySelectorAll(\"svg\").forEach((svgEl) => {\n // Derive responsive sizing from viewBox so pure viewBox SVGs stay visible and fluid\n const viewBox = svgEl.getAttribute(\"viewBox\");\n if (!viewBox) return;\n\n const dimensions = viewBox\n .trim()\n .split(/[\\s,]+/)\n .map((value) => Number(value));\n\n if (dimensions.length !== 4 || dimensions.some(Number.isNaN)) return;\n\n const [, , viewBoxWidth, viewBoxHeight] = dimensions;\n const widthAttr = svgEl.getAttribute(\"width\");\n const heightAttr = svgEl.getAttribute(\"height\");\n const isRelativeLength = (value?: string | null) => {\n if (!value) return false;\n const normalized = value.trim().toLowerCase();\n return normalized === \"auto\" || normalized.endsWith(\"%\");\n };\n const toNumericLength = (value?: string | null) => {\n if (!value) return null;\n const normalized = value.trim().toLowerCase();\n if (normalized === \"auto\" || normalized.endsWith(\"%\")) {\n return null;\n }\n const parsed = Number.parseFloat(normalized);\n return Number.isNaN(parsed) ? null : parsed;\n };\n // Treat percentage/auto sizing as responsive so viewBox drives the layout\n const isWidthRelative = isRelativeLength(widthAttr);\n const isHeightRelative = isRelativeLength(heightAttr);\n const widthMissing = !widthAttr || widthAttr === \"0\";\n const heightMissing = !heightAttr || heightAttr === \"0\";\n const numericWidth = toNumericLength(widthAttr);\n const numericHeight = toNumericLength(heightAttr);\n const matchesViewBox =\n numericWidth === viewBoxWidth && numericHeight === viewBoxHeight;\n\n // Prefer responsive layout when sizing is relative or matches the viewBox\n const shouldUseResponsiveSize =\n isWidthRelative ||\n isHeightRelative ||\n (widthMissing && heightMissing) ||\n matchesViewBox;\n\n if (shouldUseResponsiveSize) {\n hasResponsiveSvg = true;\n svgEl.classList.add(\"content-render-svg-el--responsive\");\n svgEl.classList.remove(\"content-render-svg-el--fixed\");\n svgEl.style.width = \"100%\";\n svgEl.style.height = \"auto\";\n if (!svgEl.style.aspectRatio && viewBoxHeight > 0) {\n svgEl.style.aspectRatio = `${viewBoxWidth} / ${viewBoxHeight}`;\n }\n return;\n }\n\n hasFixedSvg = true;\n svgEl.classList.add(\"content-render-svg-el--fixed\");\n svgEl.classList.remove(\"content-render-svg-el--responsive\");\n if (widthMissing && viewBoxWidth > 0) {\n svgEl.setAttribute(\"width\", `${viewBoxWidth}`);\n }\n if (heightMissing && viewBoxHeight > 0) {\n svgEl.setAttribute(\"height\", `${viewBoxHeight}`);\n }\n });\n\n const hostResponsive = hasResponsiveSvg && !hasFixedSvg;\n host.classList.toggle(\"content-render-svg--responsive\", hostResponsive);\n host.classList.toggle(\"content-render-svg--fixed\", !hostResponsive);\n }, [svg]);\n\n return (\n <div className=\"content-render-svg-scroll\">\n <div className=\"content-render-svg\" ref={hostRef} />\n </div>\n );\n};\n\n// Extended component interface\ntype CustomComponents = ComponentsWithCustomVariable & {\n \"custom-button-after-content\"?: React.ComponentType<{\n children: React.ReactNode;\n }>;\n};\n\nconst remarkPlugins = [remarkGfm, remarkMath, remarkFlow, remarkBreaks];\n\nconst rehypePlugins = [\n preserveCustomVariableProperties,\n rehypeRaw,\n sanitizeInvalidTagName,\n restoreCustomVariableProperties,\n [rehypeHighlight, { languages: highlightLanguages, subset: subsetLanguages }],\n rehypeKatex,\n];\n\nexport const MarkdownRenderer: React.FC<{\n content: string;\n components: CustomComponents;\n}> = ({ content: markdownContent, components }) => (\n <div className=\"markdown-renderer\">\n <ReactMarkdown\n remarkPlugins={remarkPlugins}\n rehypePlugins={rehypePlugins}\n components={components}\n >\n {markdownContent}\n </ReactMarkdown>\n </div>\n);\n\nconst mergeNonSandboxSegments = (segments: RenderSegment[]) => {\n if (segments.length <= 1) return segments;\n const merged: RenderSegment[] = [];\n\n segments.forEach((segment) => {\n if (segment.type === \"sandbox\") {\n merged.push(segment);\n return;\n }\n\n const last = merged[merged.length - 1];\n if (last && last.type !== \"sandbox\") {\n merged[merged.length - 1] = {\n type: \"markdown\",\n value: `${last.value}${segment.value}`,\n };\n return;\n }\n\n merged.push({ type: \"markdown\", value: segment.value });\n });\n\n return merged;\n};\n\nconst ContentRender: React.FC<ContentRenderProps> = ({\n content,\n customRenderBar,\n onSend,\n typingSpeed = 30,\n enableTypewriter = false,\n defaultButtonText,\n defaultInputText,\n defaultSelectedValues,\n readonly = false,\n onTypeFinished,\n confirmButtonText,\n copyButtonText,\n copiedButtonText,\n sandboxLoadingText,\n sandboxStyleLoadingText,\n sandboxScriptLoadingText,\n sandboxFullscreenButtonText,\n sandboxMode = \"content\",\n onClickCustomButtonAfterContent,\n beforeSend,\n // tooltipMinLength,\n}) => {\n const normalizedContent = useMemo(\n () => normalizeInlineHtml(content),\n [content]\n );\n\n // Use custom Hook to handle typewriter effect\n const components: CustomComponents = {\n \"custom-button-after-content\": ({\n children,\n }: {\n children: React.ReactNode;\n }) => {\n return (\n <button\n className=\"content-render-custom-button-after-content\"\n onClick={onClickCustomButtonAfterContent}\n >\n <span className=\"content-render-custom-button-after-content-inner\">\n {children}\n </span>\n </button>\n );\n },\n \"custom-variable\": (props) => (\n <CustomButtonInputVariable\n {...props}\n readonly={readonly}\n defaultButtonText={defaultButtonText}\n defaultInputText={defaultInputText}\n defaultSelectedValues={defaultSelectedValues}\n onSend={onSend}\n beforeSend={beforeSend}\n confirmButtonText={confirmButtonText}\n // tooltipMinLength={tooltipMinLength}\n />\n ),\n code: (props) => {\n const { className, children, ...rest } = props as {\n className?: string;\n children?: React.ReactNode;\n };\n const match = /language-(\\w+)/.exec(className || \"\");\n const language = match?.[1];\n if (language === \"mermaid\") {\n const chartContent = children?.toString().replace(/\\n$/, \"\") || \"\";\n const frozen = mermaidBlockIsComplete(content, chartContent);\n return <MermaidChart chart={chartContent} frozen={frozen} />;\n }\n\n return (\n <code className={className} {...rest}>\n {children}\n </code>\n );\n },\n table: ({ ...props }) => (\n <div className=\"content-render-table-container\">\n <table className=\"content-render-table\" {...props} />\n </div>\n ),\n th: ({ ...props }) => <th className=\"content-render-th\" {...props} />,\n td: ({ ...props }) => <td className=\"content-render-td\" {...props} />,\n tr: ({ ...props }) => <tr className=\"content-render-tr\" {...props} />,\n li: ({ node, ...props }) => {\n const className = node?.properties?.className;\n const hasTaskListItem =\n (typeof className === \"string\" &&\n className.includes(\"task-list-item\")) ||\n (Array.isArray(className) && className.includes(\"task-list-item\"));\n if (hasTaskListItem) {\n return <li className=\"content-render-task-list-item\" {...props} />;\n }\n return <li {...props} />;\n },\n ol: ({ ...props }) => <ol className=\"content-render-ol\" {...props} />,\n ul: ({ ...props }) => <ul className=\"content-render-ul\" {...props} />,\n input: ({ ...props }) => {\n if (props.type === \"checkbox\") {\n return (\n <input\n type=\"checkbox\"\n className=\"content-render-checkbox\"\n disabled\n {...props}\n />\n );\n }\n return <input {...props} />;\n },\n a: ({ children, ...props }) => (\n <a target=\"_blank\" rel=\"noopener noreferrer\" {...props}>\n {children}\n </a>\n ),\n pre: (props) => (\n <CodeBlock\n {...props}\n copyButtonText={copyButtonText}\n copiedButtonText={copiedButtonText}\n />\n ),\n };\n\n const { displayContent, isComplete } = useTypewriterStateMachine({\n // processMarkdownText will let code block printf(\"You win!\\n\") become printf(\"You win!<br/>\");\n // content: processMarkdownText(content),\n content: normalizedContent,\n typingSpeed,\n disabled: !enableTypewriter,\n });\n\n const renderSegments = useMemo(\n () => splitContentSegments(content, true),\n [content]\n );\n\n const hasSandbox = renderSegments.some(\n (segment) => segment.type === \"sandbox\"\n );\n const mergedRenderSegments = useMemo(\n () => mergeNonSandboxSegments(renderSegments),\n [renderSegments]\n );\n\n const segments = useMemo(\n () => parseMarkdownSegments(displayContent),\n [displayContent]\n );\n\n const hasCompleted = useRef(false);\n\n useEffect(() => {\n if (hasSandbox) return;\n if (isComplete && !hasCompleted.current) {\n hasCompleted.current = true; // Mark as completed\n onTypeFinished?.(); // Call the passed callback\n }\n }, [hasSandbox, isComplete, onTypeFinished]);\n\n useEffect(() => {\n if (hasSandbox) return;\n hasCompleted.current = false; // Reset completion status when content changes\n }, [hasSandbox, content]);\n\n const renderMarkdownSegments = (raw: string, keyPrefix: string) => {\n const normalized = normalizeInlineHtml(raw);\n const parsed = parseMarkdownSegments(normalized);\n\n return parsed.map((seg, index) => {\n const key = `${keyPrefix}-${seg.type}-${index}`;\n\n if (seg.type === \"text\") {\n return (\n <MarkdownRenderer\n key={key}\n components={components}\n content={seg.value}\n />\n );\n }\n\n if (seg.type === \"mermaid\") {\n return (\n <MermaidChart key={key} chart={seg.value} frozen={!seg.complete} />\n );\n }\n\n if (seg.type === \"svg\") {\n return <SvgBlockInShadow key={key} svg={seg.value} />;\n }\n\n return null;\n });\n };\n\n if (hasSandbox) {\n return (\n <div className=\"content-render markdown-body\">\n {mergedRenderSegments.map((segment, idx) =>\n segment.type === \"sandbox\" ? (\n <IframeSandbox\n key={`sandbox-${idx}`}\n hideFullScreen\n content={segment.value}\n className=\"content-render-iframe\"\n loadingText={sandboxLoadingText}\n styleLoadingText={sandboxStyleLoadingText}\n scriptLoadingText={sandboxScriptLoadingText}\n fullScreenButtonText={sandboxFullscreenButtonText}\n mode={sandboxMode}\n />\n ) : (\n <React.Fragment key={`md-${idx}`}>\n {renderMarkdownSegments(segment.value, `md-${idx}`)}\n </React.Fragment>\n )\n )}\n </div>\n );\n }\n\n return (\n <div className=\"content-render markdown-body\">\n {segments.map((seg, index) => {\n if (seg.type === \"text\") {\n return (\n <MarkdownRenderer\n key={index}\n components={components}\n content={seg.value}\n />\n );\n }\n\n if (seg.type === \"mermaid\") {\n return (\n <MermaidChart\n key={index}\n chart={seg.value}\n frozen={!seg.complete}\n />\n );\n }\n\n if (seg.type === \"svg\") {\n return <SvgBlockInShadow key={index} svg={seg.value} />;\n }\n })}\n\n {customRenderBar && (\n <div className=\"content-render-custom-bar\">\n {React.createElement(customRenderBar, {\n content,\n displayContent,\n onSend,\n })}\n </div>\n )}\n </div>\n );\n};\n\nexport default ContentRender;\n"],"names":["SvgBlockInShadow","svg","hostRef","useRef","useEffect","host","shadowRoot","styleId","styleEl","node","template","cleanedSvg","stripSvgTextLineBreaks","hasResponsiveSvg","hasFixedSvg","svgEl","viewBox","dimensions","value","viewBoxWidth","viewBoxHeight","widthAttr","heightAttr","isRelativeLength","normalized","toNumericLength","parsed","isWidthRelative","isHeightRelative","widthMissing","heightMissing","numericWidth","numericHeight","hostResponsive","jsx","remarkPlugins","remarkGfm","remarkMath","remarkFlow","remarkBreaks","rehypePlugins","preserveCustomVariableProperties","rehypeRaw","sanitizeInvalidTagName","restoreCustomVariableProperties","rehypeHighlight","highlightLanguages","subsetLanguages","rehypeKatex","MarkdownRenderer","markdownContent","components","ReactMarkdown","mergeNonSandboxSegments","segments","merged","segment","last","ContentRender","content","customRenderBar","onSend","typingSpeed","enableTypewriter","defaultButtonText","defaultInputText","defaultSelectedValues","readonly","onTypeFinished","confirmButtonText","copyButtonText","copiedButtonText","sandboxLoadingText","sandboxStyleLoadingText","sandboxScriptLoadingText","sandboxFullscreenButtonText","sandboxMode","onClickCustomButtonAfterContent","beforeSend","normalizedContent","useMemo","normalizeInlineHtml","children","props","CustomButtonInputVariable","className","rest","chartContent","frozen","mermaidBlockIsComplete","MermaidChart","CodeBlock","displayContent","isComplete","useTypewriterStateMachine","renderSegments","splitContentSegments","hasSandbox","mergedRenderSegments","parseMarkdownSegments","hasCompleted","renderMarkdownSegments","raw","keyPrefix","seg","index","key","idx","IframeSandbox","React","jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"ContentRender.es.js","sources":["../../../src/components/ContentRender/ContentRender.tsx"],"sourcesContent":["import \"highlight.js/styles/github.css\";\nimport \"katex/dist/katex.min.css\";\nimport React, { useEffect, useMemo, useRef } from \"react\";\nimport ReactMarkdown from \"react-markdown\";\nimport rehypeHighlight from \"rehype-highlight\";\nimport rehypeKatex from \"rehype-katex\";\nimport rehypeRaw from \"rehype-raw\";\nimport remarkBreaks from \"remark-breaks\";\nimport remarkFlow from \"remark-flow\";\nimport remarkGfm from \"remark-gfm\";\nimport remarkMath from \"remark-math\";\nimport { CustomRenderBarProps, OnSendContentParams } from \"../types\";\nimport { sanitizeInvalidTagName } from \"./utils/sanitize-invalid-tag-name\";\nimport { stripSvgTextLineBreaks } from \"./utils/strip-svg-text-line-breaks\";\nimport \"./contentRender.css\";\nimport \"./github-markdown-light.css\";\nimport CodeBlock from \"./CodeBlock\";\nimport CustomButtonInputVariable, {\n ComponentsWithCustomVariable,\n} from \"./plugins/CustomVariable\";\nimport MermaidChart from \"./plugins/MermaidChart\";\nimport useTypewriterStateMachine from \"./useTypewriterStateMachine\";\nimport {\n preserveCustomVariableProperties,\n restoreCustomVariableProperties,\n} from \"./utils/custom-variable-props\";\nimport {\n highlightLanguages,\n subsetLanguages,\n} from \"./utils/highlight-languages\";\n// import { processMarkdownText } from \"./utils/process-markdown\";\nimport {\n parseMarkdownSegments,\n mermaidBlockIsComplete,\n} from \"./utils/mermaid-parse\";\nimport { normalizeInlineHtml } from \"./utils/normalize-inline-html\";\nimport IframeSandbox from \"./IframeSandbox\";\nimport {\n splitContentSegments,\n type RenderSegment,\n} from \"./utils/split-content\";\n// Define component Props type\nexport interface ContentRenderProps {\n content: string;\n /**\n+ * Callback invoked when the custom button after content is clicked.\n+ * This button is rendered via the `<custom-button-after-content>` tag in markdown content.\n+ * @example\n+ * ```tsx\n+ * <ContentRender\n+ * content=\"Hello <custom-button-after-content>Ask</custom-button-after-content>\"\n+ * onClickCustomButtonAfterContent={() => console.log('Button clicked')}\n+ * />\n+ * ```\n+ */\n customRenderBar?: CustomRenderBarProps;\n onClickCustomButtonAfterContent?: () => void;\n onSend?: (content: OnSendContentParams) => void;\n typingSpeed?: number;\n enableTypewriter?: boolean;\n defaultButtonText?: string;\n defaultInputText?: string; // Text input by user\n defaultSelectedValues?: string[]; // Default selected values for multi-select\n readonly?: boolean;\n onTypeFinished?: () => void;\n // Multi-select confirm button text (i18n support)\n confirmButtonText?: string;\n // Copy button text (i18n support)\n copyButtonText?: string;\n // Copied state text (i18n support)\n copiedButtonText?: string;\n // Dynamic interaction format for multi-select support\n dynamicInteractionFormat?: string;\n // Loading text before first HTML block renders inside iframe (i18n support)\n sandboxLoadingText?: string;\n // Loading text while styles are being generated inside iframe\n sandboxStyleLoadingText?: string;\n // Loading text while scripts are being cached/executed inside iframe\n sandboxScriptLoadingText?: string;\n // Fullscreen button text for iframe sandbox\n sandboxFullscreenButtonText?: string;\n // Sandbox render mode\n sandboxMode?: \"content\" | \"blackboard\";\n beforeSend?: (param: OnSendContentParams) => boolean;\n // tooltipMinLength?: number; // Control minimum character length for tooltip display, default 10\n}\n\n// Render svg string via Shadow DOM to avoid markdown wrapping\nconst SvgBlockInShadow: React.FC<{ svg: string }> = ({ svg }) => {\n const hostRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const host = hostRef.current;\n if (!host) return;\n const shadowRoot = host.shadowRoot ?? host.attachShadow({ mode: \"open\" });\n const styleId = \"content-render-svg-style\";\n let styleEl = shadowRoot.getElementById(styleId) as HTMLStyleElement | null;\n\n if (!styleEl) {\n styleEl = document.createElement(\"style\");\n styleEl.id = styleId;\n // Keep intrinsic SVG width so the wrapper can scroll horizontally when needed\n styleEl.textContent = `\n svg { height: auto; display: inline-block; }\n svg.content-render-svg-el--responsive { width: 100%; max-width: 100%; }\n svg.content-render-svg-el--fixed { max-width: none; }\n `;\n shadowRoot.appendChild(styleEl);\n }\n\n const nodesToRemove = Array.from(shadowRoot.childNodes).filter(\n (node) => node !== styleEl\n );\n nodesToRemove.forEach((node) => shadowRoot.removeChild(node));\n\n const template = document.createElement(\"template\");\n const cleanedSvg = stripSvgTextLineBreaks(svg);\n template.innerHTML = cleanedSvg;\n shadowRoot.append(template.content.cloneNode(true));\n\n let hasResponsiveSvg = false;\n let hasFixedSvg = false;\n\n shadowRoot.querySelectorAll(\"svg\").forEach((svgEl) => {\n // Derive responsive sizing from viewBox so pure viewBox SVGs stay visible and fluid\n const viewBox = svgEl.getAttribute(\"viewBox\");\n if (!viewBox) return;\n\n const dimensions = viewBox\n .trim()\n .split(/[\\s,]+/)\n .map((value) => Number(value));\n\n if (dimensions.length !== 4 || dimensions.some(Number.isNaN)) return;\n\n const [, , viewBoxWidth, viewBoxHeight] = dimensions;\n const widthAttr = svgEl.getAttribute(\"width\");\n const heightAttr = svgEl.getAttribute(\"height\");\n const isRelativeLength = (value?: string | null) => {\n if (!value) return false;\n const normalized = value.trim().toLowerCase();\n return normalized === \"auto\" || normalized.endsWith(\"%\");\n };\n const toNumericLength = (value?: string | null) => {\n if (!value) return null;\n const normalized = value.trim().toLowerCase();\n if (normalized === \"auto\" || normalized.endsWith(\"%\")) {\n return null;\n }\n const parsed = Number.parseFloat(normalized);\n return Number.isNaN(parsed) ? null : parsed;\n };\n // Treat percentage/auto sizing as responsive so viewBox drives the layout\n const isWidthRelative = isRelativeLength(widthAttr);\n const isHeightRelative = isRelativeLength(heightAttr);\n const widthMissing = !widthAttr || widthAttr === \"0\";\n const heightMissing = !heightAttr || heightAttr === \"0\";\n const numericWidth = toNumericLength(widthAttr);\n const numericHeight = toNumericLength(heightAttr);\n const matchesViewBox =\n numericWidth === viewBoxWidth && numericHeight === viewBoxHeight;\n\n // Prefer responsive layout when sizing is relative or matches the viewBox\n const shouldUseResponsiveSize =\n isWidthRelative ||\n isHeightRelative ||\n (widthMissing && heightMissing) ||\n matchesViewBox;\n\n if (shouldUseResponsiveSize) {\n hasResponsiveSvg = true;\n svgEl.classList.add(\"content-render-svg-el--responsive\");\n svgEl.classList.remove(\"content-render-svg-el--fixed\");\n svgEl.style.width = \"100%\";\n svgEl.style.height = \"auto\";\n if (!svgEl.style.aspectRatio && viewBoxHeight > 0) {\n svgEl.style.aspectRatio = `${viewBoxWidth} / ${viewBoxHeight}`;\n }\n return;\n }\n\n hasFixedSvg = true;\n svgEl.classList.add(\"content-render-svg-el--fixed\");\n svgEl.classList.remove(\"content-render-svg-el--responsive\");\n if (widthMissing && viewBoxWidth > 0) {\n svgEl.setAttribute(\"width\", `${viewBoxWidth}`);\n }\n if (heightMissing && viewBoxHeight > 0) {\n svgEl.setAttribute(\"height\", `${viewBoxHeight}`);\n }\n });\n\n const hostResponsive = hasResponsiveSvg && !hasFixedSvg;\n host.classList.toggle(\"content-render-svg--responsive\", hostResponsive);\n host.classList.toggle(\"content-render-svg--fixed\", !hostResponsive);\n }, [svg]);\n\n return (\n <div className=\"content-render-svg-scroll\">\n <div className=\"content-render-svg\" ref={hostRef} />\n </div>\n );\n};\n\n// Extended component interface\ntype CustomComponents = ComponentsWithCustomVariable & {\n \"custom-button-after-content\"?: React.ComponentType<{\n children: React.ReactNode;\n }>;\n};\n\nconst remarkPlugins = [remarkGfm, remarkMath, remarkFlow, remarkBreaks];\n\nconst rehypePlugins = [\n preserveCustomVariableProperties,\n rehypeRaw,\n sanitizeInvalidTagName,\n restoreCustomVariableProperties,\n [rehypeHighlight, { languages: highlightLanguages, subset: subsetLanguages }],\n rehypeKatex,\n];\n\nexport const MarkdownRenderer: React.FC<{\n content: string;\n components: CustomComponents;\n}> = ({ content: markdownContent, components }) => (\n <div className=\"markdown-renderer\">\n <ReactMarkdown\n remarkPlugins={remarkPlugins}\n rehypePlugins={rehypePlugins}\n components={components}\n >\n {markdownContent}\n </ReactMarkdown>\n </div>\n);\n\nconst mergeNonSandboxSegments = (\n segments: RenderSegment[],\n mergeSandboxSegments = false\n) => {\n if (segments.length <= 1) return segments;\n const merged: RenderSegment[] = [];\n\n segments.forEach((segment) => {\n const last = merged[merged.length - 1];\n\n if (\n mergeSandboxSegments &&\n segment.type === \"sandbox\" &&\n last?.type === \"sandbox\"\n ) {\n merged[merged.length - 1] = {\n type: \"sandbox\",\n value: `${last.value}${segment.value}`,\n };\n return;\n }\n\n if (segment.type === \"sandbox\") {\n merged.push(segment);\n return;\n }\n\n if (last && last.type !== \"sandbox\") {\n merged[merged.length - 1] = {\n type: \"markdown\",\n value: `${last.value}${segment.value}`,\n };\n return;\n }\n\n merged.push({ type: \"markdown\", value: segment.value });\n });\n\n return merged;\n};\n\nconst ContentRender: React.FC<ContentRenderProps> = ({\n content,\n customRenderBar,\n onSend,\n typingSpeed = 30,\n enableTypewriter = false,\n defaultButtonText,\n defaultInputText,\n defaultSelectedValues,\n readonly = false,\n onTypeFinished,\n confirmButtonText,\n copyButtonText,\n copiedButtonText,\n sandboxLoadingText,\n sandboxStyleLoadingText,\n sandboxScriptLoadingText,\n sandboxFullscreenButtonText,\n sandboxMode = \"content\",\n onClickCustomButtonAfterContent,\n beforeSend,\n // tooltipMinLength,\n}) => {\n const normalizedContent = useMemo(\n () => normalizeInlineHtml(content),\n [content]\n );\n\n // Use custom Hook to handle typewriter effect\n const components: CustomComponents = {\n \"custom-button-after-content\": ({\n children,\n }: {\n children: React.ReactNode;\n }) => {\n return (\n <button\n className=\"content-render-custom-button-after-content\"\n onClick={onClickCustomButtonAfterContent}\n >\n <span className=\"content-render-custom-button-after-content-inner\">\n {children}\n </span>\n </button>\n );\n },\n \"custom-variable\": (props) => (\n <CustomButtonInputVariable\n {...props}\n readonly={readonly}\n defaultButtonText={defaultButtonText}\n defaultInputText={defaultInputText}\n defaultSelectedValues={defaultSelectedValues}\n onSend={onSend}\n beforeSend={beforeSend}\n confirmButtonText={confirmButtonText}\n // tooltipMinLength={tooltipMinLength}\n />\n ),\n code: (props) => {\n const { className, children, ...rest } = props as {\n className?: string;\n children?: React.ReactNode;\n };\n const match = /language-(\\w+)/.exec(className || \"\");\n const language = match?.[1];\n if (language === \"mermaid\") {\n const chartContent = children?.toString().replace(/\\n$/, \"\") || \"\";\n const frozen = mermaidBlockIsComplete(content, chartContent);\n return <MermaidChart chart={chartContent} frozen={frozen} />;\n }\n\n return (\n <code className={className} {...rest}>\n {children}\n </code>\n );\n },\n table: ({ ...props }) => (\n <div className=\"content-render-table-container\">\n <table className=\"content-render-table\" {...props} />\n </div>\n ),\n th: ({ ...props }) => <th className=\"content-render-th\" {...props} />,\n td: ({ ...props }) => <td className=\"content-render-td\" {...props} />,\n tr: ({ ...props }) => <tr className=\"content-render-tr\" {...props} />,\n li: ({ node, ...props }) => {\n const className = node?.properties?.className;\n const hasTaskListItem =\n (typeof className === \"string\" &&\n className.includes(\"task-list-item\")) ||\n (Array.isArray(className) && className.includes(\"task-list-item\"));\n if (hasTaskListItem) {\n return <li className=\"content-render-task-list-item\" {...props} />;\n }\n return <li {...props} />;\n },\n ol: ({ ...props }) => <ol className=\"content-render-ol\" {...props} />,\n ul: ({ ...props }) => <ul className=\"content-render-ul\" {...props} />,\n input: ({ ...props }) => {\n if (props.type === \"checkbox\") {\n return (\n <input\n type=\"checkbox\"\n className=\"content-render-checkbox\"\n disabled\n {...props}\n />\n );\n }\n return <input {...props} />;\n },\n a: ({ children, ...props }) => (\n <a target=\"_blank\" rel=\"noopener noreferrer\" {...props}>\n {children}\n </a>\n ),\n pre: (props) => (\n <CodeBlock\n {...props}\n copyButtonText={copyButtonText}\n copiedButtonText={copiedButtonText}\n />\n ),\n };\n\n const { displayContent, isComplete } = useTypewriterStateMachine({\n // processMarkdownText will let code block printf(\"You win!\\n\") become printf(\"You win!<br/>\");\n // content: processMarkdownText(content),\n content: normalizedContent,\n typingSpeed,\n disabled: !enableTypewriter,\n });\n\n const renderSegments = useMemo(\n () => splitContentSegments(content, true),\n [content]\n );\n\n const hasSandbox = renderSegments.some(\n (segment) => segment.type === \"sandbox\"\n );\n const mergedRenderSegments = useMemo(\n () => mergeNonSandboxSegments(renderSegments, sandboxMode === \"blackboard\"),\n [renderSegments, sandboxMode]\n );\n\n const segments = useMemo(\n () => parseMarkdownSegments(displayContent),\n [displayContent]\n );\n\n const hasCompleted = useRef(false);\n\n useEffect(() => {\n if (hasSandbox) return;\n if (isComplete && !hasCompleted.current) {\n hasCompleted.current = true; // Mark as completed\n onTypeFinished?.(); // Call the passed callback\n }\n }, [hasSandbox, isComplete, onTypeFinished]);\n\n useEffect(() => {\n if (hasSandbox) return;\n hasCompleted.current = false; // Reset completion status when content changes\n }, [hasSandbox, content]);\n\n const renderMarkdownSegments = (raw: string, keyPrefix: string) => {\n const normalized = normalizeInlineHtml(raw);\n const parsed = parseMarkdownSegments(normalized);\n\n return parsed.map((seg, index) => {\n const key = `${keyPrefix}-${seg.type}-${index}`;\n\n if (seg.type === \"text\") {\n return (\n <MarkdownRenderer\n key={key}\n components={components}\n content={seg.value}\n />\n );\n }\n\n if (seg.type === \"mermaid\") {\n return (\n <MermaidChart key={key} chart={seg.value} frozen={!seg.complete} />\n );\n }\n\n if (seg.type === \"svg\") {\n return <SvgBlockInShadow key={key} svg={seg.value} />;\n }\n\n return null;\n });\n };\n\n if (hasSandbox) {\n return (\n <div className=\"content-render markdown-body\">\n {mergedRenderSegments.map((segment, idx) =>\n segment.type === \"sandbox\" ? (\n <IframeSandbox\n key={`sandbox-${idx}`}\n hideFullScreen\n content={segment.value}\n className=\"content-render-iframe\"\n loadingText={sandboxLoadingText}\n styleLoadingText={sandboxStyleLoadingText}\n scriptLoadingText={sandboxScriptLoadingText}\n fullScreenButtonText={sandboxFullscreenButtonText}\n mode={sandboxMode}\n />\n ) : (\n <React.Fragment key={`md-${idx}`}>\n {renderMarkdownSegments(segment.value, `md-${idx}`)}\n </React.Fragment>\n )\n )}\n </div>\n );\n }\n\n return (\n <div className=\"content-render markdown-body\">\n {segments.map((seg, index) => {\n if (seg.type === \"text\") {\n return (\n <MarkdownRenderer\n key={index}\n components={components}\n content={seg.value}\n />\n );\n }\n\n if (seg.type === \"mermaid\") {\n return (\n <MermaidChart\n key={index}\n chart={seg.value}\n frozen={!seg.complete}\n />\n );\n }\n\n if (seg.type === \"svg\") {\n return <SvgBlockInShadow key={index} svg={seg.value} />;\n }\n })}\n\n {customRenderBar && (\n <div className=\"content-render-custom-bar\">\n {React.createElement(customRenderBar, {\n content,\n displayContent,\n onSend,\n })}\n </div>\n )}\n </div>\n );\n};\n\nexport default ContentRender;\n"],"names":["SvgBlockInShadow","svg","hostRef","useRef","useEffect","host","shadowRoot","styleId","styleEl","node","template","cleanedSvg","stripSvgTextLineBreaks","hasResponsiveSvg","hasFixedSvg","svgEl","viewBox","dimensions","value","viewBoxWidth","viewBoxHeight","widthAttr","heightAttr","isRelativeLength","normalized","toNumericLength","parsed","isWidthRelative","isHeightRelative","widthMissing","heightMissing","numericWidth","numericHeight","hostResponsive","jsx","remarkPlugins","remarkGfm","remarkMath","remarkFlow","remarkBreaks","rehypePlugins","preserveCustomVariableProperties","rehypeRaw","sanitizeInvalidTagName","restoreCustomVariableProperties","rehypeHighlight","highlightLanguages","subsetLanguages","rehypeKatex","MarkdownRenderer","markdownContent","components","ReactMarkdown","mergeNonSandboxSegments","segments","mergeSandboxSegments","merged","segment","last","ContentRender","content","customRenderBar","onSend","typingSpeed","enableTypewriter","defaultButtonText","defaultInputText","defaultSelectedValues","readonly","onTypeFinished","confirmButtonText","copyButtonText","copiedButtonText","sandboxLoadingText","sandboxStyleLoadingText","sandboxScriptLoadingText","sandboxFullscreenButtonText","sandboxMode","onClickCustomButtonAfterContent","beforeSend","normalizedContent","useMemo","normalizeInlineHtml","children","props","CustomButtonInputVariable","className","rest","chartContent","frozen","mermaidBlockIsComplete","MermaidChart","CodeBlock","displayContent","isComplete","useTypewriterStateMachine","renderSegments","splitContentSegments","hasSandbox","mergedRenderSegments","parseMarkdownSegments","hasCompleted","renderMarkdownSegments","raw","keyPrefix","seg","index","key","idx","IframeSandbox","React","jsxs"],"mappings":"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"}
@@ -35,3 +35,4 @@ export declare const EnglishChineseTypographyPreview: Story;
35
35
  export declare const SVGDemo: Story;
36
36
  export declare const HTMLDemo: Story;
37
37
  export declare const HTMLDemoIframeOnly: Story;
38
+ export declare const IframeSandboxBlackboardDiffPlayback: Story;
@@ -1,15 +1,16 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const h=require("../../_virtual/jsx-runtime.cjs.js"),n=require("react"),$=require("react-dom/client"),B=require("./SandboxApp.cjs.js"),P=require("./utils/split-content.cjs.js"),_=require("./ContentRender.cjs.js"),L=({content:f,type:S,className:Y,loadingText:C,styleLoadingText:H,scriptLoadingText:j,fullScreenButtonText:p,hideFullScreen:M=!1,mode:c="content"})=>{const q=n.useRef(null),i=n.useRef(null),x=n.useRef(null),k=n.useRef(null),R=n.useRef(()=>{}),[z,A]=n.useState(480),[F,O]=n.useState(0),[D,I]=n.useState(!1),v=n.useRef(""),u=n.useMemo(()=>{const t=P.splitContentSegments(f).filter(o=>o.type==="sandbox");return(c==="blackboard"?t[t.length-1]?.value||"":t.map(o=>o.value).join(`
2
- `))||""},[f,c]),N=n.useMemo(()=>{const e=u.trim();if(!e)return!1;const t=e.match(/^<([a-zA-Z][\w:-]*)(\s[^>]*?)?>/);if(!t)return!1;const r=t[2]||"",o=r.match(/\bheight\s*=\s*["']([^"']+)["']/i);if(o&&/vh$/i.test(o[1].trim()))return!0;const d=r.match(/\bstyle\s*=\s*["']([^"']+)["']/i);return d?/height\s*:\s*[^;]*vh\b/i.test(d[1]):!1},[u]);n.useEffect(()=>{if(c!=="blackboard"){v.current=u;return}const e=v.current;!(e&&u.startsWith(e))&&e&&O(r=>r+1),v.current=u},[u,c]),n.useEffect(()=>{const e=i.current;if(!e)return;const t=e.contentDocument;if(!t)return;t.open(),t.write(`<!DOCTYPE html>
3
- <html>
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const m=require("../../_virtual/jsx-runtime.cjs.js"),n=require("react"),I=require("react-dom/client"),V=require("./SandboxApp.cjs.js"),W=require("./utils/split-content.cjs.js"),K=require("./ContentRender.cjs.js"),T=()=>Promise.resolve().then(()=>require("./blackboard-vendor.cjs.js")).then(l=>l.injectBlackboardLibraries),N=/!\+\+\+[\s\S]*?!\+\+\+/g,G=l=>{const i=l.trim();return!i||!i.match(N)?.length?!1:i.replace(N,"").trim().length===0},Y=({content:l,type:i,className:z,loadingText:x,styleLoadingText:H,scriptLoadingText:j,fullScreenButtonText:v,hideFullScreen:q=!1,mode:r="content"})=>{const F=n.useRef(null),h=n.useRef(null),R=n.useRef(null),M=n.useRef(null),w=n.useRef(()=>{}),[B,O]=n.useState(480),[S,P]=n.useState(0),[D,L]=n.useState(!1),E=n.useRef(""),u=n.useMemo(()=>{if(r==="blackboard"&&i==="sandbox")return l||"";const e=W.splitContentSegments(l).filter(s=>s.type==="sandbox");return(r==="blackboard"?e[e.length-1]?.value||"":e.map(s=>s.value).join(`
2
+ `))||""},[l,r,i]),A=n.useMemo(()=>{const t=u.trim();if(!t)return!1;const e=t.match(/^<([a-zA-Z][\w:-]*)(\s[^>]*?)?>/);if(!e)return!1;const o=e[2]||"",s=o.match(/\bheight\s*=\s*["']([^"']+)["']/i);if(s&&/vh$/i.test(s[1].trim()))return!0;const b=o.match(/\bstyle\s*=\s*["']([^"']+)["']/i);return b?/height\s*:\s*[^;]*vh\b/i.test(b[1]):!1},[u]);n.useEffect(()=>{if(r!=="blackboard"||i!=="sandbox"){E.current=u;return}const t=E.current,e=t&&u.startsWith(t),o=G(u);!e&&t&&!o&&P(s=>s+1),E.current=u},[u,r,i]),n.useEffect(()=>{const t=h.current;if(!t)return;const e=t.contentDocument;if(!e)return;e.open(),e.write(`<!DOCTYPE html>
3
+ <html${r==="blackboard"?' style="height: 100%;"':""}>
4
4
  <head>
5
5
  <meta charset="utf-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
7
  <style>
7
- html, body { margin: 0; padding: 0; }
8
+ html, body { margin: 0; padding: 0;${r==="blackboard"?" width: 100%; height: 100%; overflow: auto;":""} }
8
9
  *, *::before, *::after { box-sizing: border-box; }
9
10
  </style>
10
11
  </head>
11
12
  <body>
12
13
  <div id="root"></div>
13
14
  </body>
14
- </html>`),t.close(),k.current=t;const r=t.getElementById("root");if(!r)return;const o=$.createRoot(r);x.current=o;const d=(m,a)=>{const s=m.trim().toLowerCase();if(!s)return null;const l=Number.parseFloat(s);return Number.isNaN(l)?null:s.endsWith("vh")?l/100*a:s.endsWith("px")||/^[0-9.]+$/.test(s)?l:null},W=()=>{if(!i.current||!t.body)return null;const a=t.body.querySelector(".sandbox-wrapper")?.firstElementChild;if(!a)return null;const s=Array.from(a.children);if(s.length!==1)return null;const l=s[0],b=l.style.height||l.getAttribute("height");if(!b)return null;const w=i.current.ownerDocument?.documentElement?.clientHeight||window.innerHeight,g=d(b,w);return g?Math.ceil(g):null},y=()=>{if(!i.current||!t.body)return;const m=t.body.getBoundingClientRect(),a=t.documentElement?.getBoundingClientRect(),s=m.height,l=a?.height||0,b=Math.max(s,l),w=W(),g=Math.max(200,w??Math.ceil(b));A(g)};R.current=y,y();const E=new ResizeObserver(()=>y());return E.observe(t.body),r&&E.observe(r),()=>{E.disconnect(),setTimeout(()=>{o.unmount(),x.current=null,k.current=null,R.current=()=>{}},0)}},[]),n.useEffect(()=>{const e=()=>{I(!!document.fullscreenElement)};return document.addEventListener("fullscreenchange",e),()=>document.removeEventListener("fullscreenchange",e)},[]);const V=()=>{const e=q.current||i.current;if(e){if(document.fullscreenElement){document.exitFullscreen().catch(()=>{});return}e.requestFullscreen&&e.requestFullscreen().catch(()=>{})}};return n.useEffect(()=>{const e=x.current;e&&(e.render(h.jsxRuntimeExports.jsx(B.default,{html:u,loadingText:C,styleLoadingText:H,scriptLoadingText:j,fullScreenButtonText:p,hideFullScreen:M,resetToken:F,hasRootVhHeight:N,mode:c})),requestAnimationFrame(()=>R.current?.()))},[f,u,C,H,j,p,F,c]),h.jsxRuntimeExports.jsxs("div",{ref:q,"data-root-vh":N?"true":"false",className:"w-full h-full overflow-auto relative flex flex-col content-render-iframe-sandbox",children:[!M&&h.jsxRuntimeExports.jsx("button",{type:"button",onClick:V,className:"absolute top-2 right-2 z-50 p-1.5 bg-black/75 text-white rounded-md cursor-pointer",children:D?"退出全屏":p||"全屏浏览"}),c==="blackboard"&&S==="markdown"?h.jsxRuntimeExports.jsx(_.default,{content:f}):h.jsxRuntimeExports.jsx("iframe",{ref:i,sandbox:"allow-scripts allow-same-origin",allow:"fullscreen",allowFullScreen:!0,className:"w-full",style:{height:c==="blackboard"?"100%":`${z}px`}})]})};exports.default=L;
15
+ </html>`),e.close(),r==="blackboard"&&T().then(f=>f(e)),M.current=e;const o=e.getElementById("root");if(!o)return;const s=I.createRoot(o);R.current=s;const b=(f,d)=>{const c=f.trim().toLowerCase();if(!c)return null;const a=Number.parseFloat(c);return Number.isNaN(a)?null:c.endsWith("vh")?a/100*d:c.endsWith("px")||/^[0-9.]+$/.test(c)?a:null},$=()=>{if(!h.current||!e.body)return null;const d=e.body.querySelector(".sandbox-wrapper")?.firstElementChild;if(!d)return null;const c=Array.from(d.children);if(c.length!==1)return null;const a=c[0],g=a.style.height||a.getAttribute("height");if(!g)return null;const C=h.current.ownerDocument?.documentElement?.clientHeight||window.innerHeight,p=b(g,C);return p?Math.ceil(p):null},y=()=>{if(!h.current||!e.body)return;const f=e.body.getBoundingClientRect(),d=e.documentElement?.getBoundingClientRect(),c=f.height,a=d?.height||0,g=Math.max(c,a),C=$(),p=Math.max(200,C??Math.ceil(g));O(p)};w.current=y,y();const k=new ResizeObserver(()=>y());return k.observe(e.body),o&&k.observe(o),()=>{k.disconnect(),setTimeout(()=>{s.unmount(),R.current=null,M.current=null,w.current=()=>{}},0)}},[]),n.useEffect(()=>{const t=()=>{L(!!document.fullscreenElement)};return document.addEventListener("fullscreenchange",t),()=>document.removeEventListener("fullscreenchange",t)},[]);const _=()=>{const t=F.current||h.current;if(t){if(document.fullscreenElement){document.exitFullscreen().catch(()=>{});return}t.requestFullscreen&&t.requestFullscreen().catch(()=>{})}};return n.useEffect(()=>{const t=R.current;t&&(t.render(m.jsxRuntimeExports.jsx(V.default,{html:u,loadingText:x,styleLoadingText:H,scriptLoadingText:j,fullScreenButtonText:v,hideFullScreen:q,resetToken:S,hasRootVhHeight:A,mode:r})),requestAnimationFrame(()=>w.current?.()))},[l,u,x,H,j,v,S,r]),m.jsxRuntimeExports.jsxs("div",{ref:F,"data-root-vh":A?"true":"false",className:"w-full h-full overflow-auto relative flex flex-col content-render-iframe-sandbox",children:[!q&&m.jsxRuntimeExports.jsx("button",{type:"button",onClick:_,className:"absolute top-2 right-2 z-50 p-1.5 bg-black/75 text-white rounded-md cursor-pointer",children:D?"退出全屏":v||"全屏浏览"}),r==="blackboard"&&i==="markdown"?m.jsxRuntimeExports.jsx(K.default,{content:l}):m.jsxRuntimeExports.jsx("iframe",{ref:h,sandbox:"allow-scripts allow-same-origin",allow:"fullscreen",allowFullScreen:!0,className:"w-full",style:{height:r==="blackboard"?"100%":`${B}px`}})]})};exports.default=Y;
15
16
  //# sourceMappingURL=IframeSandbox.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"IframeSandbox.cjs.js","sources":["../../../src/components/ContentRender/IframeSandbox.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport { createRoot, Root } from \"react-dom/client\";\nimport SandboxApp from \"./SandboxApp\";\nimport { splitContentSegments } from \"./utils/split-content\";\nimport ContentRender from \"./ContentRender\";\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 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 [height, setHeight] = useState(480);\n const [resetToken, setResetToken] = useState(0);\n const [isFullscreen, setIsFullscreen] = useState(false);\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 hasRootVhHeight = React.useMemo(() => {\n const normalized = htmlContent.trim();\n if (!normalized) return false;\n const rootMatch = normalized.match(/^<([a-zA-Z][\\w:-]*)(\\s[^>]*?)?>/);\n if (!rootMatch) return false;\n const attrs = rootMatch[2] || \"\";\n const heightAttrMatch = attrs.match(/\\bheight\\s*=\\s*[\"']([^\"']+)[\"']/i);\n if (heightAttrMatch && /vh$/i.test(heightAttrMatch[1].trim())) {\n return true;\n }\n const styleAttrMatch = attrs.match(/\\bstyle\\s*=\\s*[\"']([^\"']+)[\"']/i);\n if (!styleAttrMatch) return false;\n return /height\\s*:\\s*[^;]*vh\\b/i.test(styleAttrMatch[1]);\n }, [htmlContent]);\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>\n <head>\n <meta charset=\"utf-8\" />\n <style>\n html, body { margin: 0; padding: 0; }\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 docRef.current = doc;\n\n const rootEl = doc.getElementById(\"root\");\n if (!rootEl) return undefined;\n\n const root = createRoot(rootEl);\n rootRef.current = root;\n\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 (normalized.endsWith(\"vh\")) {\n return (numeric / 100) * parentViewportHeight;\n }\n if (normalized.endsWith(\"px\") || /^[0-9.]+$/.test(normalized)) {\n return numeric;\n }\n return null;\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 if (!heightValue) return null;\n const parentViewportHeight =\n iframeRef.current.ownerDocument?.documentElement?.clientHeight ||\n window.innerHeight;\n const parsed = parseExplicitHeight(heightValue, parentViewportHeight);\n return parsed ? Math.ceil(parsed) : 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 updateHeightRef.current = updateHeight;\n\n updateHeight();\n\n const resizeObserver = new ResizeObserver(() => updateHeight());\n resizeObserver.observe(doc.body);\n if (rootEl) {\n resizeObserver.observe(rootEl);\n }\n\n return () => {\n resizeObserver.disconnect();\n // Defer unmount to avoid React warning when parent is mid-render\n setTimeout(() => {\n root.unmount();\n rootRef.current = null;\n docRef.current = null;\n updateHeightRef.current = () => {};\n }, 0);\n };\n }, []);\n\n useEffect(() => {\n const onFullscreenChange = () => {\n setIsFullscreen(Boolean(document.fullscreenElement));\n };\n document.addEventListener(\"fullscreenchange\", onFullscreenChange);\n return () =>\n document.removeEventListener(\"fullscreenchange\", onFullscreenChange);\n }, []);\n\n const toggleFullscreen = () => {\n const target = containerRef.current || iframeRef.current;\n if (!target) return;\n if (document.fullscreenElement) {\n document.exitFullscreen().catch(() => {});\n return;\n }\n if (target.requestFullscreen) {\n target.requestFullscreen().catch(() => {});\n }\n };\n\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n\n root.render(\n <SandboxApp\n html={htmlContent}\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 content,\n htmlContent,\n loadingText,\n styleLoadingText,\n scriptLoadingText,\n fullScreenButtonText,\n resetToken,\n mode,\n ]);\n\n return (\n <div\n ref={containerRef}\n data-root-vh={hasRootVhHeight ? \"true\" : \"false\"}\n className={\n \"w-full h-full overflow-auto relative flex flex-col content-render-iframe-sandbox\"\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 <ContentRender content={content} />\n ) : (\n <iframe\n ref={iframeRef}\n sandbox=\"allow-scripts allow-same-origin\"\n allow=\"fullscreen\"\n allowFullScreen\n className={(className, \"w-full\")}\n style={{\n height: mode === \"blackboard\" ? \"100%\" : `${height}px`,\n // height: `${height}px`,\n // margin: \"16px 0\",\n }}\n />\n )}\n </div>\n );\n};\n\nexport default IframeSandbox;\n"],"names":["IframeSandbox","content","type","className","loadingText","styleLoadingText","scriptLoadingText","fullScreenButtonText","hideFullScreen","mode","containerRef","useRef","iframeRef","rootRef","docRef","updateHeightRef","height","setHeight","useState","resetToken","setResetToken","isFullscreen","setIsFullscreen","prevHtmlRef","htmlContent","React","sandboxSegments","splitContentSegments","seg","hasRootVhHeight","normalized","rootMatch","attrs","heightAttrMatch","styleAttrMatch","useEffect","prev","token","iframe","doc","rootEl","root","createRoot","parseExplicitHeight","value","parentViewportHeight","numeric","resolveExplicitHeight","container","elements","target","heightValue","parsed","updateHeight","bodyRect","htmlRect","bodyHeight","htmlHeight","contentHeight","explicitHeight","nextHeight","resizeObserver","onFullscreenChange","toggleFullscreen","jsx","SandboxApp","jsxs","ContentRender"],"mappings":"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"}
1
+ {"version":3,"file":"IframeSandbox.cjs.js","sources":["../../../src/components/ContentRender/IframeSandbox.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport { createRoot, Root } from \"react-dom/client\";\nimport SandboxApp from \"./SandboxApp\";\nimport { splitContentSegments } from \"./utils/split-content\";\nimport ContentRender from \"./ContentRender\";\n// Lazy-loaded to avoid bundling ~3.3 MB of vendor libs for non-blackboard consumers\nconst loadBlackboardVendor = () =>\n import(\"./blackboard-vendor\").then((m) => m.injectBlackboardLibraries);\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 DIFF_BLOCK_GLOBAL_PATTERN = /!\\+\\+\\+[\\s\\S]*?!\\+\\+\\+/g;\n\nconst isPureDiffPayload = (raw: string) => {\n const normalized = raw.trim();\n if (!normalized) {\n return false;\n }\n\n const matchedBlocks = normalized.match(DIFF_BLOCK_GLOBAL_PATTERN);\n if (!matchedBlocks?.length) {\n return false;\n }\n\n const rest = normalized.replace(DIFF_BLOCK_GLOBAL_PATTERN, \"\").trim();\n return rest.length === 0;\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 [height, setHeight] = useState(480);\n const [resetToken, setResetToken] = useState(0);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const prevHtmlRef = useRef<string>(\"\");\n const htmlContent = React.useMemo(() => {\n if (mode === \"blackboard\" && type === \"sandbox\") {\n return content || \"\";\n }\n\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, type]);\n const hasRootVhHeight = React.useMemo(() => {\n const normalized = htmlContent.trim();\n if (!normalized) return false;\n const rootMatch = normalized.match(/^<([a-zA-Z][\\w:-]*)(\\s[^>]*?)?>/);\n if (!rootMatch) return false;\n const attrs = rootMatch[2] || \"\";\n const heightAttrMatch = attrs.match(/\\bheight\\s*=\\s*[\"']([^\"']+)[\"']/i);\n if (heightAttrMatch && /vh$/i.test(heightAttrMatch[1].trim())) {\n return true;\n }\n const styleAttrMatch = attrs.match(/\\bstyle\\s*=\\s*[\"']([^\"']+)[\"']/i);\n if (!styleAttrMatch) return false;\n return /height\\s*:\\s*[^;]*vh\\b/i.test(styleAttrMatch[1]);\n }, [htmlContent]);\n useEffect(() => {\n if (mode !== \"blackboard\" || type !== \"sandbox\") {\n prevHtmlRef.current = htmlContent;\n return;\n }\n const prev = prevHtmlRef.current;\n const isContinuation = prev && htmlContent.startsWith(prev);\n const shouldKeepState = isPureDiffPayload(htmlContent);\n if (!isContinuation && prev && !shouldKeepState) {\n setResetToken((token) => token + 1);\n }\n prevHtmlRef.current = htmlContent;\n }, [htmlContent, mode, type]);\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 { margin: 0; padding: 0;${mode === \"blackboard\" ? \" width: 100%; height: 100%; 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 // Inject Tailwind/DaisyUI/GSAP into iframe for blackboard mode.\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 if (mode === \"blackboard\") {\n loadBlackboardVendor().then((inject) => inject(doc));\n }\n\n docRef.current = doc;\n\n const rootEl = doc.getElementById(\"root\");\n if (!rootEl) return undefined;\n\n const root = createRoot(rootEl);\n rootRef.current = root;\n\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 (normalized.endsWith(\"vh\")) {\n return (numeric / 100) * parentViewportHeight;\n }\n if (normalized.endsWith(\"px\") || /^[0-9.]+$/.test(normalized)) {\n return numeric;\n }\n return null;\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 if (!heightValue) return null;\n const parentViewportHeight =\n iframeRef.current.ownerDocument?.documentElement?.clientHeight ||\n window.innerHeight;\n const parsed = parseExplicitHeight(heightValue, parentViewportHeight);\n return parsed ? Math.ceil(parsed) : 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 updateHeightRef.current = updateHeight;\n\n updateHeight();\n\n const resizeObserver = new ResizeObserver(() => updateHeight());\n resizeObserver.observe(doc.body);\n if (rootEl) {\n resizeObserver.observe(rootEl);\n }\n\n return () => {\n resizeObserver.disconnect();\n // Defer unmount to avoid React warning when parent is mid-render\n setTimeout(() => {\n root.unmount();\n rootRef.current = null;\n docRef.current = null;\n updateHeightRef.current = () => {};\n }, 0);\n };\n }, []);\n\n useEffect(() => {\n const onFullscreenChange = () => {\n setIsFullscreen(Boolean(document.fullscreenElement));\n };\n document.addEventListener(\"fullscreenchange\", onFullscreenChange);\n return () =>\n document.removeEventListener(\"fullscreenchange\", onFullscreenChange);\n }, []);\n\n const toggleFullscreen = () => {\n const target = containerRef.current || iframeRef.current;\n if (!target) return;\n if (document.fullscreenElement) {\n document.exitFullscreen().catch(() => {});\n return;\n }\n if (target.requestFullscreen) {\n target.requestFullscreen().catch(() => {});\n }\n };\n\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n\n root.render(\n <SandboxApp\n html={htmlContent}\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 content,\n htmlContent,\n loadingText,\n styleLoadingText,\n scriptLoadingText,\n fullScreenButtonText,\n resetToken,\n mode,\n ]);\n\n return (\n <div\n ref={containerRef}\n data-root-vh={hasRootVhHeight ? \"true\" : \"false\"}\n className={\n \"w-full h-full overflow-auto relative flex flex-col content-render-iframe-sandbox\"\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 <ContentRender content={content} />\n ) : (\n <iframe\n ref={iframeRef}\n sandbox=\"allow-scripts allow-same-origin\"\n allow=\"fullscreen\"\n allowFullScreen\n className={(className, \"w-full\")}\n style={{\n height: mode === \"blackboard\" ? \"100%\" : `${height}px`,\n // height: `${height}px`,\n // margin: \"16px 0\",\n }}\n />\n )}\n </div>\n );\n};\n\nexport default IframeSandbox;\n"],"names":["loadBlackboardVendor","m","DIFF_BLOCK_GLOBAL_PATTERN","isPureDiffPayload","raw","normalized","IframeSandbox","content","type","className","loadingText","styleLoadingText","scriptLoadingText","fullScreenButtonText","hideFullScreen","mode","containerRef","useRef","iframeRef","rootRef","docRef","updateHeightRef","height","setHeight","useState","resetToken","setResetToken","isFullscreen","setIsFullscreen","prevHtmlRef","htmlContent","React","sandboxSegments","splitContentSegments","seg","hasRootVhHeight","rootMatch","attrs","heightAttrMatch","styleAttrMatch","useEffect","prev","isContinuation","shouldKeepState","token","iframe","doc","inject","rootEl","root","createRoot","parseExplicitHeight","value","parentViewportHeight","numeric","resolveExplicitHeight","container","elements","target","heightValue","parsed","updateHeight","bodyRect","htmlRect","bodyHeight","htmlHeight","contentHeight","explicitHeight","nextHeight","resizeObserver","onFullscreenChange","toggleFullscreen","jsx","SandboxApp","jsxs","ContentRender"],"mappings":"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"}