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