markdown-flow-ui 0.1.81-beta.12 → 0.1.81-beta.14

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 (27) hide show
  1. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/classnames@2.5.1/node_modules/classnames/index.js +1 -1
  2. 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.js +1 -1
  3. 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.js +1 -1
  4. 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.js +1 -1
  5. 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.js +1 -1
  6. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-flow@0.1.6/node_modules/remark-flow/dist/remark-custom-variable.js +1 -1
  7. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-flow@0.1.6/node_modules/remark-flow/dist/remark-interaction.js +1 -1
  8. package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/style-to-object@1.0.11/node_modules/style-to-object/cjs/index.js +1 -1
  9. package/dist/_virtual/index10.js +2 -2
  10. package/dist/_virtual/index3.js +5 -4
  11. package/dist/_virtual/index3.js.map +1 -1
  12. package/dist/_virtual/index4.js +4 -5
  13. package/dist/_virtual/index4.js.map +1 -1
  14. package/dist/_virtual/index9.js +2 -2
  15. package/dist/assets/markdown-flow-ui.css +1 -1
  16. package/dist/components/ContentRender/ContentRender.js +157 -118
  17. package/dist/components/ContentRender/ContentRender.js.map +1 -1
  18. package/dist/components/ContentRender/ContentRender.stories.d.ts +1 -0
  19. package/dist/components/ContentRender/IframeSandbox.d.ts +7 -0
  20. package/dist/components/ContentRender/IframeSandbox.js +60 -0
  21. package/dist/components/ContentRender/IframeSandbox.js.map +1 -0
  22. package/dist/components/ContentRender/SandboxApp.d.ts +6 -0
  23. package/dist/components/ContentRender/SandboxApp.js +21 -0
  24. package/dist/components/ContentRender/SandboxApp.js.map +1 -0
  25. package/dist/components/ui/inputGroup/textarea.js +1 -1
  26. package/dist/markdown-flow-ui-lib.css +1 -1
  27. package/package.json +1 -1
@@ -1,118 +1,140 @@
1
1
  import { j as t } from "../../_virtual/jsx-runtime.js";
2
2
  /* empty css */
3
3
  /* empty css */
4
- import M, { useMemo as z, useRef as B, useEffect as w } from "react";
5
- import H from "../../_virtual/index.js";
4
+ import T, { useMemo as C, useRef as $, useEffect as R } from "react";
5
+ import V from "../../_virtual/index.js";
6
6
  /* empty css */
7
7
  /* empty css */
8
- import L from "./CodeBlock.js";
9
- import T from "./plugins/CustomVariable.js";
10
- import A from "./plugins/MermaidChart.js";
11
- import $ from "./useTypewriterStateMachine.js";
12
- import { preserveCustomVariableProperties as P, restoreCustomVariableProperties as V } from "./utils/custom-variable-props.js";
13
- import { subsetLanguages as _, highlightLanguages as U } from "./utils/highlight-languages.js";
14
- import { parseMarkdownSegments as W, mermaidBlockIsComplete as q } from "./utils/mermaid-parse.js";
15
- import { normalizeInlineHtml as E } from "./utils/normalize-inline-html.js";
16
- import { Markdown as G } from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/react-markdown@10.1.0_@types_react@19.2.2_react@19.0.1/node_modules/react-markdown/lib/index.js";
17
- import K from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rehype-raw@7.0.0/node_modules/rehype-raw/lib/index.js";
18
- import D from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rehype-highlight@7.0.2/node_modules/rehype-highlight/lib/index.js";
19
- import F from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rehype-katex@7.0.1/node_modules/rehype-katex/lib/index.js";
20
- import J from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-gfm@4.0.1/node_modules/remark-gfm/lib/index.js";
21
- import O from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-math@6.0.0/node_modules/remark-math/lib/index.js";
22
- import Q from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-breaks@4.0.0/node_modules/remark-breaks/lib/index.js";
23
- const X = ({ svg: n }) => {
24
- const l = B(null);
25
- return w(() => {
26
- const c = l.current;
27
- if (!c) return;
28
- const s = c.shadowRoot ?? c.attachShadow({ mode: "open" }), f = "content-render-svg-style";
29
- let a = s.getElementById(f);
30
- a || (a = document.createElement("style"), a.id = f, a.textContent = `
8
+ import _ from "./CodeBlock.js";
9
+ import E from "./plugins/CustomVariable.js";
10
+ import I from "./plugins/MermaidChart.js";
11
+ import U from "./useTypewriterStateMachine.js";
12
+ import { preserveCustomVariableProperties as W, restoreCustomVariableProperties as q } from "./utils/custom-variable-props.js";
13
+ import { subsetLanguages as G, highlightLanguages as K } from "./utils/highlight-languages.js";
14
+ import { parseMarkdownSegments as D, mermaidBlockIsComplete as F } from "./utils/mermaid-parse.js";
15
+ import { normalizeInlineHtml as M } from "./utils/normalize-inline-html.js";
16
+ import J from "./IframeSandbox.js";
17
+ import { Markdown as O } from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/react-markdown@10.1.0_@types_react@19.2.2_react@19.0.1/node_modules/react-markdown/lib/index.js";
18
+ import Q from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rehype-raw@7.0.0/node_modules/rehype-raw/lib/index.js";
19
+ import X from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rehype-highlight@7.0.2/node_modules/rehype-highlight/lib/index.js";
20
+ import Y from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rehype-katex@7.0.1/node_modules/rehype-katex/lib/index.js";
21
+ import Z from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-gfm@4.0.1/node_modules/remark-gfm/lib/index.js";
22
+ import ee from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-math@6.0.0/node_modules/remark-math/lib/index.js";
23
+ import te from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-breaks@4.0.0/node_modules/remark-breaks/lib/index.js";
24
+ const H = (r) => {
25
+ const c = /<(script|style|link|iframe|html|head|body|meta|title|base|template|div|section|article|main)[\s>]/i, a = r.search(c);
26
+ if (a === -1)
27
+ return [{ type: "markdown", value: r }];
28
+ const i = /<\/[a-z][^>]*>\s*\n(?=[^\s<])/gi;
29
+ let l = r.length, o;
30
+ for (; o = i.exec(r); )
31
+ if (!(o.index <= a)) {
32
+ l = o.index + o[0].length - 1;
33
+ break;
34
+ }
35
+ const d = [], u = r.slice(0, a), n = r.slice(a, l), m = r.slice(l);
36
+ return u.trim() && d.push({ type: "markdown", value: u }), d.push({ type: "sandbox", value: n }), m.trim() && d.push(...H(m)), d;
37
+ }, re = ({ svg: r }) => {
38
+ const c = $(null);
39
+ return R(() => {
40
+ const a = c.current;
41
+ if (!a) return;
42
+ const i = a.shadowRoot ?? a.attachShadow({ mode: "open" }), l = "content-render-svg-style";
43
+ let o = i.getElementById(l);
44
+ o || (o = document.createElement("style"), o.id = l, o.textContent = `
31
45
  :host { display: block; width: 100%; max-width: 100%; text-align: center; }
32
46
  svg { max-width: 100%; height: auto; display: inline-block; }
33
- `, s.appendChild(a)), Array.from(s.childNodes).filter(
34
- (r) => r !== a
35
- ).forEach((r) => s.removeChild(r));
36
- const x = document.createElement("template");
37
- x.innerHTML = n, s.append(x.content.cloneNode(!0)), s.querySelectorAll("svg").forEach((r) => {
38
- const d = r.getAttribute("viewBox");
39
- if (!d) return;
40
- const u = d.trim().split(/[\s,]+/).map((k) => Number(k));
41
- if (u.length !== 4 || u.some(Number.isNaN)) return;
42
- const [, , h, m] = u, b = r.getAttribute("width"), g = r.getAttribute("height"), j = !!b && b !== "0", p = !!g && g !== "0";
43
- if (!j && !p) {
44
- r.style.width = "100%", r.style.height = "auto", !r.style.aspectRatio && m > 0 && (r.style.aspectRatio = `${h} / ${m}`);
47
+ `, i.appendChild(o)), Array.from(i.childNodes).filter(
48
+ (n) => n !== o
49
+ ).forEach((n) => i.removeChild(n));
50
+ const u = document.createElement("template");
51
+ u.innerHTML = r, i.append(u.content.cloneNode(!0)), i.querySelectorAll("svg").forEach((n) => {
52
+ const m = n.getAttribute("viewBox");
53
+ if (!m) return;
54
+ const f = m.trim().split(/[\s,]+/).map((v) => Number(v));
55
+ if (f.length !== 4 || f.some(Number.isNaN)) return;
56
+ const [, , x, p] = f, g = n.getAttribute("width"), j = n.getAttribute("height"), k = !!g && g !== "0", b = !!j && j !== "0";
57
+ if (!k && !b) {
58
+ n.style.width = "100%", n.style.height = "auto", !n.style.aspectRatio && p > 0 && (n.style.aspectRatio = `${x} / ${p}`);
45
59
  return;
46
60
  }
47
- !j && h > 0 && r.setAttribute("width", `${h}`), !p && m > 0 && r.setAttribute("height", `${m}`);
61
+ !k && x > 0 && n.setAttribute("width", `${x}`), !b && p > 0 && n.setAttribute("height", `${p}`);
48
62
  });
49
- }, [n]), /* @__PURE__ */ t.jsx("div", { className: "content-render-svg-scroll", children: /* @__PURE__ */ t.jsx("div", { className: "content-render-svg", ref: l }) });
50
- }, Ne = ({
51
- content: n,
52
- customRenderBar: l,
53
- onSend: c,
54
- typingSpeed: s = 30,
55
- enableTypewriter: f = !1,
56
- defaultButtonText: a,
57
- defaultInputText: v,
58
- defaultSelectedValues: x,
59
- readonly: r = !1,
60
- onTypeFinished: d,
61
- confirmButtonText: u,
62
- copyButtonText: h,
63
- copiedButtonText: m,
64
- onClickCustomButtonAfterContent: b,
65
- beforeSend: g
63
+ }, [r]), /* @__PURE__ */ t.jsx("div", { className: "content-render-svg-scroll", children: /* @__PURE__ */ t.jsx("div", { className: "content-render-svg", ref: c }) });
64
+ }, ne = [Z, ee, V, te], se = [
65
+ W,
66
+ Q,
67
+ q,
68
+ [X, { languages: K, subset: G }],
69
+ Y
70
+ ], z = ({ content: r, components: c }) => /* @__PURE__ */ t.jsx("div", { className: "markdown-body", children: /* @__PURE__ */ t.jsx(
71
+ O,
72
+ {
73
+ remarkPlugins: ne,
74
+ rehypePlugins: se,
75
+ components: c,
76
+ children: r
77
+ }
78
+ ) }), Ie = ({
79
+ content: r,
80
+ customRenderBar: c,
81
+ onSend: a,
82
+ typingSpeed: i = 30,
83
+ enableTypewriter: l = !1,
84
+ defaultButtonText: o,
85
+ defaultInputText: d,
86
+ defaultSelectedValues: u,
87
+ readonly: n = !1,
88
+ onTypeFinished: m,
89
+ confirmButtonText: f,
90
+ copyButtonText: x,
91
+ copiedButtonText: p,
92
+ onClickCustomButtonAfterContent: g,
93
+ beforeSend: j
66
94
  // tooltipMinLength,
67
95
  }) => {
68
- const j = z(
69
- () => E(n),
70
- [n]
71
- ), { displayContent: p, isComplete: y } = $({
72
- // processMarkdownText will let code block printf("You win!\n") become printf("You win!<br/>");
73
- // content: processMarkdownText(content),
74
- content: j,
75
- typingSpeed: s,
76
- disabled: !f
77
- }), k = {
96
+ const k = C(
97
+ () => M(r),
98
+ [r]
99
+ ), b = {
78
100
  "custom-button-after-content": ({
79
101
  children: e
80
102
  }) => /* @__PURE__ */ t.jsx(
81
103
  "button",
82
104
  {
83
105
  className: "content-render-custom-button-after-content",
84
- onClick: b,
106
+ onClick: g,
85
107
  children: /* @__PURE__ */ t.jsx("span", { className: "content-render-custom-button-after-content-inner", children: e })
86
108
  }
87
109
  ),
88
110
  "custom-variable": (e) => /* @__PURE__ */ t.jsx(
89
- T,
111
+ E,
90
112
  {
91
113
  ...e,
92
- readonly: r,
93
- defaultButtonText: a,
94
- defaultInputText: v,
95
- defaultSelectedValues: x,
96
- onSend: c,
97
- beforeSend: g,
98
- confirmButtonText: u
114
+ readonly: n,
115
+ defaultButtonText: o,
116
+ defaultInputText: d,
117
+ defaultSelectedValues: u,
118
+ onSend: a,
119
+ beforeSend: j,
120
+ confirmButtonText: f
99
121
  }
100
122
  ),
101
123
  code: (e) => {
102
- const { className: o, children: i, ...C } = e;
103
- if (/language-(\w+)/.exec(o || "")?.[1] === "mermaid") {
104
- const R = i?.toString().replace(/\n$/, "") || "", S = q(n, R);
105
- return /* @__PURE__ */ t.jsx(A, { chart: R, frozen: S });
124
+ const { className: s, children: h, ...A } = e;
125
+ if (/language-(\w+)/.exec(s || "")?.[1] === "mermaid") {
126
+ const B = h?.toString().replace(/\n$/, "") || "", P = F(r, B);
127
+ return /* @__PURE__ */ t.jsx(I, { chart: B, frozen: P });
106
128
  }
107
- return /* @__PURE__ */ t.jsx("code", { className: o, ...C, children: i });
129
+ return /* @__PURE__ */ t.jsx("code", { className: s, ...A, children: h });
108
130
  },
109
131
  table: ({ ...e }) => /* @__PURE__ */ t.jsx("div", { className: "content-render-table-container", children: /* @__PURE__ */ t.jsx("table", { className: "content-render-table", ...e }) }),
110
132
  th: ({ ...e }) => /* @__PURE__ */ t.jsx("th", { className: "content-render-th", ...e }),
111
133
  td: ({ ...e }) => /* @__PURE__ */ t.jsx("td", { className: "content-render-td", ...e }),
112
134
  tr: ({ ...e }) => /* @__PURE__ */ t.jsx("tr", { className: "content-render-tr", ...e }),
113
- li: ({ node: e, ...o }) => {
114
- const i = e?.properties?.className;
115
- return typeof i == "string" && i.includes("task-list-item") || Array.isArray(i) && i.includes("task-list-item") ? /* @__PURE__ */ t.jsx("li", { className: "content-render-task-list-item", ...o }) : /* @__PURE__ */ t.jsx("li", { ...o });
135
+ li: ({ node: e, ...s }) => {
136
+ const h = e?.properties?.className;
137
+ return typeof h == "string" && h.includes("task-list-item") || Array.isArray(h) && h.includes("task-list-item") ? /* @__PURE__ */ t.jsx("li", { className: "content-render-task-list-item", ...s }) : /* @__PURE__ */ t.jsx("li", { ...s });
116
138
  },
117
139
  ol: ({ ...e }) => /* @__PURE__ */ t.jsx("ol", { className: "content-render-ol", ...e }),
118
140
  ul: ({ ...e }) => /* @__PURE__ */ t.jsx("ul", { className: "content-render-ul", ...e }),
@@ -125,64 +147,81 @@ const X = ({ svg: n }) => {
125
147
  ...e
126
148
  }
127
149
  ) : /* @__PURE__ */ t.jsx("input", { ...e }),
128
- a: ({ children: e, ...o }) => /* @__PURE__ */ t.jsx("a", { target: "_blank", rel: "noopener noreferrer", ...o, children: e }),
150
+ a: ({ children: e, ...s }) => /* @__PURE__ */ t.jsx("a", { target: "_blank", rel: "noopener noreferrer", ...s, children: e }),
129
151
  pre: (e) => /* @__PURE__ */ t.jsx(
130
- L,
152
+ _,
131
153
  {
132
154
  ...e,
133
- copyButtonText: h,
134
- copiedButtonText: m
155
+ copyButtonText: x,
156
+ copiedButtonText: p
135
157
  }
136
158
  )
137
- }, N = B(!1);
138
- w(() => {
139
- y && !N.current && (N.current = !0, d?.());
140
- }, [y, d]), w(() => {
141
- N.current = !1;
142
- }, [n]);
143
- const I = W(p);
144
- return /* @__PURE__ */ t.jsxs("div", { className: "content-render markdown-body", children: [
145
- I.map((e, o) => {
159
+ }, { displayContent: N, isComplete: v } = U({
160
+ // processMarkdownText will let code block printf("You win!\n") become printf("You win!<br/>");
161
+ // content: processMarkdownText(content),
162
+ content: k,
163
+ typingSpeed: i,
164
+ disabled: !l
165
+ }), S = C(
166
+ () => H(r),
167
+ [r]
168
+ ), y = S.some(
169
+ (e) => e.type === "sandbox"
170
+ ), L = C(
171
+ () => D(N),
172
+ [N]
173
+ ), w = $(!1);
174
+ return R(() => {
175
+ y || v && !w.current && (w.current = !0, m?.());
176
+ }, [y, v, m]), R(() => {
177
+ y || (w.current = !1);
178
+ }, [y, r]), y ? /* @__PURE__ */ t.jsx("div", { className: "content-render", children: S.map(
179
+ (e, s) => e.type === "sandbox" ? /* @__PURE__ */ t.jsx(
180
+ J,
181
+ {
182
+ content: e.value,
183
+ className: "content-render-iframe"
184
+ },
185
+ `sandbox-${s}`
186
+ ) : /* @__PURE__ */ t.jsx(
187
+ z,
188
+ {
189
+ components: b,
190
+ content: M(e.value)
191
+ },
192
+ `md-${s}`
193
+ )
194
+ ) }) : /* @__PURE__ */ t.jsxs("div", { className: "content-render", children: [
195
+ L.map((e, s) => {
146
196
  if (e.type === "text")
147
197
  return /* @__PURE__ */ t.jsx(
148
- G,
198
+ z,
149
199
  {
150
- remarkPlugins: [J, O, H, Q],
151
- rehypePlugins: [
152
- P,
153
- K,
154
- V,
155
- [
156
- D,
157
- { languages: U, subset: _ }
158
- ],
159
- F
160
- ],
161
- components: k,
162
- children: e.value
200
+ components: b,
201
+ content: e.value
163
202
  },
164
- o
203
+ s
165
204
  );
166
205
  if (e.type === "mermaid")
167
206
  return /* @__PURE__ */ t.jsx(
168
- A,
207
+ I,
169
208
  {
170
209
  chart: e.value,
171
210
  frozen: !e.complete
172
211
  },
173
- o
212
+ s
174
213
  );
175
214
  if (e.type === "svg")
176
- return /* @__PURE__ */ t.jsx(X, { svg: e.value }, o);
215
+ return /* @__PURE__ */ t.jsx(re, { svg: e.value }, s);
177
216
  }),
178
- l && /* @__PURE__ */ t.jsx("div", { className: "content-render-custom-bar", children: M.createElement(l, {
179
- content: n,
180
- displayContent: p,
181
- onSend: c
217
+ c && /* @__PURE__ */ t.jsx("div", { className: "content-render-custom-bar", children: T.createElement(c, {
218
+ content: r,
219
+ displayContent: N,
220
+ onSend: a
182
221
  }) })
183
222
  ] });
184
223
  };
185
224
  export {
186
- Ne as default
225
+ Ie as default
187
226
  };
188
227
  //# sourceMappingURL=ContentRender.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ContentRender.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 \"./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\";\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 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 styleEl.textContent = `\n :host { display: block; width: 100%; max-width: 100%; text-align: center; }\n svg { max-width: 100%; height: auto; display: inline-block; }\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 template.innerHTML = svg;\n shadowRoot.append(template.content.cloneNode(true));\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 hasWidth = !!widthAttr && widthAttr !== \"0\";\n const hasHeight = !!heightAttr && heightAttr !== \"0\";\n const shouldUseResponsiveSize = !hasWidth && !hasHeight;\n\n if (shouldUseResponsiveSize) {\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 if (!hasWidth && viewBoxWidth > 0) {\n svgEl.setAttribute(\"width\", `${viewBoxWidth}`);\n }\n if (!hasHeight && viewBoxHeight > 0) {\n svgEl.setAttribute(\"height\", `${viewBoxHeight}`);\n }\n });\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 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 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 { 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 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 hasCompleted = useRef(false);\n\n useEffect(() => {\n if (isComplete && !hasCompleted.current) {\n hasCompleted.current = true; // Mark as completed\n onTypeFinished?.(); // Call the passed callback\n }\n }, [isComplete, onTypeFinished]);\n useEffect(() => {\n hasCompleted.current = false; // Reset completion status when content changes\n }, [content]);\n\n const segments = parseMarkdownSegments(displayContent);\n\n return (\n <div className={`content-render markdown-body`}>\n {segments.map((seg, index) => {\n if (seg.type === \"text\") {\n return (\n <ReactMarkdown\n key={index}\n remarkPlugins={[remarkGfm, remarkMath, remarkFlow, remarkBreaks]}\n rehypePlugins={[\n preserveCustomVariableProperties,\n rehypeRaw,\n restoreCustomVariableProperties,\n [\n rehypeHighlight,\n { languages: highlightLanguages, subset: subsetLanguages },\n ],\n rehypeKatex,\n ]}\n components={components}\n >\n {seg.value}\n </ReactMarkdown>\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","svgEl","viewBox","dimensions","value","viewBoxWidth","viewBoxHeight","widthAttr","heightAttr","hasWidth","hasHeight","jsx","ContentRender","content","customRenderBar","onSend","typingSpeed","enableTypewriter","defaultButtonText","defaultInputText","defaultSelectedValues","readonly","onTypeFinished","confirmButtonText","copyButtonText","copiedButtonText","onClickCustomButtonAfterContent","beforeSend","normalizedContent","useMemo","normalizeInlineHtml","displayContent","isComplete","useTypewriterStateMachine","components","children","props","CustomButtonInputVariable","className","rest","chartContent","frozen","mermaidBlockIsComplete","MermaidChart","CodeBlock","hasCompleted","segments","parseMarkdownSegments","jsxs","seg","index","ReactMarkdown","remarkGfm","remarkMath","remarkFlow","remarkBreaks","preserveCustomVariableProperties","rehypeRaw","restoreCustomVariableProperties","rehypeHighlight","highlightLanguages","subsetLanguages","rehypeKatex","React"],"mappings":"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"}
1
+ {"version":3,"file":"ContentRender.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 \"./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\";\n\ntype RenderSegment =\n | { type: \"markdown\"; value: string }\n | { type: \"sandbox\"; value: string };\n\nconst splitContentSegments = (raw: string): RenderSegment[] => {\n const startPattern =\n /<(script|style|link|iframe|html|head|body|meta|title|base|template|div|section|article|main)[\\s>]/i;\n\n const startIndex = raw.search(startPattern);\n if (startIndex === -1) {\n return [{ type: \"markdown\", value: raw }];\n }\n\n // Find the end of the HTML block: stop at the first closing tag whose\n // following line does not start with another HTML tag.\n const closingBoundary = /<\\/[a-z][^>]*>\\s*\\n(?=[^\\s<])/gi;\n let blockEnd = raw.length;\n let match: RegExpExecArray | null;\n\n while ((match = closingBoundary.exec(raw))) {\n if (match.index <= startIndex) continue;\n blockEnd = match.index + match[0].length - 1; // end before the newline\n break;\n }\n\n const segments: RenderSegment[] = [];\n const before = raw.slice(0, startIndex);\n const htmlBlock = raw.slice(startIndex, blockEnd);\n const after = raw.slice(blockEnd);\n\n if (before.trim()) {\n segments.push({ type: \"markdown\", value: before });\n }\n\n segments.push({ type: \"sandbox\", value: htmlBlock });\n\n if (after.trim()) {\n segments.push(...splitContentSegments(after));\n }\n\n return segments;\n};\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 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 styleEl.textContent = `\n :host { display: block; width: 100%; max-width: 100%; text-align: center; }\n svg { max-width: 100%; height: auto; display: inline-block; }\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 template.innerHTML = svg;\n shadowRoot.append(template.content.cloneNode(true));\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 hasWidth = !!widthAttr && widthAttr !== \"0\";\n const hasHeight = !!heightAttr && heightAttr !== \"0\";\n const shouldUseResponsiveSize = !hasWidth && !hasHeight;\n\n if (shouldUseResponsiveSize) {\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 if (!hasWidth && viewBoxWidth > 0) {\n svgEl.setAttribute(\"width\", `${viewBoxWidth}`);\n }\n if (!hasHeight && viewBoxHeight > 0) {\n svgEl.setAttribute(\"height\", `${viewBoxHeight}`);\n }\n });\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 restoreCustomVariableProperties,\n [rehypeHighlight, { languages: highlightLanguages, subset: subsetLanguages }],\n rehypeKatex,\n];\n\nconst MarkdownRenderer: React.FC<{\n content: string;\n components: CustomComponents;\n}> = ({ content: markdownContent, components }) => (\n <div className=\"markdown-body\">\n <ReactMarkdown\n remarkPlugins={remarkPlugins}\n rehypePlugins={rehypePlugins}\n components={components}\n >\n {markdownContent}\n </ReactMarkdown>\n </div>\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 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),\n [content]\n );\n const hasSandbox = renderSegments.some(\n (segment) => segment.type === \"sandbox\"\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 if (hasSandbox) {\n return (\n <div className=\"content-render\">\n {renderSegments.map((segment, idx) =>\n segment.type === \"sandbox\" ? (\n <IframeSandbox\n key={`sandbox-${idx}`}\n content={segment.value}\n className=\"content-render-iframe\"\n />\n ) : (\n <MarkdownRenderer\n key={`md-${idx}`}\n components={components}\n content={normalizeInlineHtml(segment.value)}\n />\n )\n )}\n </div>\n );\n }\n\n return (\n <div className=\"content-render\">\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":["splitContentSegments","raw","startPattern","startIndex","closingBoundary","blockEnd","match","segments","before","htmlBlock","after","SvgBlockInShadow","svg","hostRef","useRef","useEffect","host","shadowRoot","styleId","styleEl","node","template","svgEl","viewBox","dimensions","value","viewBoxWidth","viewBoxHeight","widthAttr","heightAttr","hasWidth","hasHeight","jsx","remarkPlugins","remarkGfm","remarkMath","remarkFlow","remarkBreaks","rehypePlugins","preserveCustomVariableProperties","rehypeRaw","restoreCustomVariableProperties","rehypeHighlight","highlightLanguages","subsetLanguages","rehypeKatex","MarkdownRenderer","markdownContent","components","ReactMarkdown","ContentRender","content","customRenderBar","onSend","typingSpeed","enableTypewriter","defaultButtonText","defaultInputText","defaultSelectedValues","readonly","onTypeFinished","confirmButtonText","copyButtonText","copiedButtonText","onClickCustomButtonAfterContent","beforeSend","normalizedContent","useMemo","normalizeInlineHtml","children","props","CustomButtonInputVariable","className","rest","chartContent","frozen","mermaidBlockIsComplete","MermaidChart","CodeBlock","displayContent","isComplete","useTypewriterStateMachine","renderSegments","hasSandbox","segment","parseMarkdownSegments","hasCompleted","idx","IframeSandbox","jsxs","seg","index","React"],"mappings":"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"}
@@ -33,3 +33,4 @@ export declare const NativeHtmlElements: Story;
33
33
  export declare const CodeBlockShowcase: Story;
34
34
  export declare const EnglishChineseTypographyPreview: Story;
35
35
  export declare const SVGDemo: Story;
36
+ export declare const HTMLDemo: Story;
@@ -0,0 +1,7 @@
1
+ import { default as React } from 'react';
2
+ export interface IframeSandboxProps {
3
+ content: string;
4
+ className?: string;
5
+ }
6
+ declare const IframeSandbox: React.FC<IframeSandboxProps>;
7
+ export default IframeSandbox;
@@ -0,0 +1,60 @@
1
+ import { j as m } from "../../_virtual/jsx-runtime.js";
2
+ import { useRef as u, useState as R, useEffect as v } from "react";
3
+ import { createRoot as H } from "react-dom/client";
4
+ import E from "./SandboxApp.js";
5
+ const B = ({
6
+ content: s,
7
+ className: a
8
+ }) => {
9
+ const n = u(null), e = u(null), [l, h] = R(480);
10
+ return v(() => {
11
+ const c = n.current;
12
+ if (!c) return;
13
+ const t = c.contentDocument;
14
+ if (!t) return;
15
+ t.open(), t.write(`<!DOCTYPE html>
16
+ <html>
17
+ <head>
18
+ <meta charset="utf-8" />
19
+ <style>
20
+ html, body { margin: 0; padding: 0; }
21
+ </style>
22
+ </head>
23
+ <body>
24
+ <div id="root"></div>
25
+ </body>
26
+ </html>`), t.close();
27
+ const o = t.getElementById("root");
28
+ if (!o) return;
29
+ e.current && e.current.unmount();
30
+ const r = H(o);
31
+ e.current = r, r.render(/* @__PURE__ */ m.jsx(E, { html: s }));
32
+ const d = () => {
33
+ if (!n.current || !t.body) return;
34
+ const f = t.body.getBoundingClientRect(), g = t.documentElement?.getBoundingClientRect(), b = f.height, p = g?.height || 0, x = Math.max(b, p), y = Math.max(200, Math.ceil(x));
35
+ h(y);
36
+ };
37
+ d();
38
+ const i = new ResizeObserver(() => d());
39
+ return i.observe(t.body), o && i.observe(o), () => {
40
+ i.disconnect(), r.unmount(), e.current = null;
41
+ };
42
+ }, [s]), /* @__PURE__ */ m.jsx(
43
+ "iframe",
44
+ {
45
+ ref: n,
46
+ sandbox: "allow-scripts allow-same-origin",
47
+ className: a,
48
+ style: {
49
+ width: "100%",
50
+ height: `${l}px`,
51
+ margin: "16px 0"
52
+ },
53
+ title: "HTML Sandbox"
54
+ }
55
+ );
56
+ };
57
+ export {
58
+ B as default
59
+ };
60
+ //# sourceMappingURL=IframeSandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IframeSandbox.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\";\n\nexport interface IframeSandboxProps {\n content: string;\n className?: string;\n}\n\nconst IframeSandbox: React.FC<IframeSandboxProps> = ({\n content,\n className,\n}) => {\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const rootRef = useRef<Root | null>(null);\n const [height, setHeight] = useState(480);\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 </style>\n </head>\n <body>\n <div id=\"root\"></div>\n </body>\n</html>`);\n doc.close();\n\n const rootEl = doc.getElementById(\"root\");\n if (!rootEl) return undefined;\n\n if (rootRef.current) {\n rootRef.current.unmount();\n }\n\n const root = createRoot(rootEl);\n rootRef.current = root;\n root.render(<SandboxApp html={content} />);\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 nextHeight = Math.max(200, Math.ceil(contentHeight));\n setHeight(nextHeight);\n };\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 root.unmount();\n rootRef.current = null;\n };\n }, [content]);\n\n return (\n <iframe\n ref={iframeRef}\n sandbox=\"allow-scripts allow-same-origin\"\n className={className}\n style={{\n width: \"100%\",\n height: `${height}px`,\n margin: \"16px 0\",\n }}\n title=\"HTML Sandbox\"\n />\n );\n};\n\nexport default IframeSandbox;\n"],"names":["IframeSandbox","content","className","iframeRef","useRef","rootRef","height","setHeight","useState","useEffect","iframe","doc","rootEl","root","createRoot","jsx","SandboxApp","updateHeight","bodyRect","htmlRect","bodyHeight","htmlHeight","contentHeight","nextHeight","resizeObserver"],"mappings":";;;;AASA,MAAMA,IAA8C,CAAC;AAAA,EACnD,SAAAC;AAAA,EACA,WAAAC;AACF,MAAM;AACJ,QAAMC,IAAYC,EAA0B,IAAI,GAC1CC,IAAUD,EAAoB,IAAI,GAClC,CAACE,GAAQC,CAAS,IAAIC,EAAS,GAAG;AAExC,SAAAC,EAAU,MAAM;AACd,UAAMC,IAASP,EAAU;AACzB,QAAI,CAACO,EAAQ;AAEb,UAAMC,IAAMD,EAAO;AACnB,QAAI,CAACC,EAAK;AAEV,IAAAA,EAAI,KAAA,GACJA,EAAI,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAWN,GACJA,EAAI,MAAA;AAEJ,UAAMC,IAASD,EAAI,eAAe,MAAM;AACxC,QAAI,CAACC,EAAQ;AAEb,IAAIP,EAAQ,WACVA,EAAQ,QAAQ,QAAA;AAGlB,UAAMQ,IAAOC,EAAWF,CAAM;AAC9B,IAAAP,EAAQ,UAAUQ,GAClBA,EAAK,OAAOE,gBAAAA,MAACC,GAAA,EAAW,MAAMf,GAAS,CAAE;AAEzC,UAAMgB,IAAe,MAAM;AACzB,UAAI,CAACd,EAAU,WAAW,CAACQ,EAAI,KAAM;AACrC,YAAMO,IAAWP,EAAI,KAAK,sBAAA,GACpBQ,IAAWR,EAAI,iBAAiB,sBAAA,GAChCS,IAAaF,EAAS,QACtBG,IAAaF,GAAU,UAAU,GACjCG,IAAgB,KAAK,IAAIF,GAAYC,CAAU,GAC/CE,IAAa,KAAK,IAAI,KAAK,KAAK,KAAKD,CAAa,CAAC;AACzD,MAAAf,EAAUgB,CAAU;AAAA,IACtB;AAEA,IAAAN,EAAA;AAEA,UAAMO,IAAiB,IAAI,eAAe,MAAMP,GAAc;AAC9D,WAAAO,EAAe,QAAQb,EAAI,IAAI,GAC3BC,KACFY,EAAe,QAAQZ,CAAM,GAGxB,MAAM;AACX,MAAAY,EAAe,WAAA,GACfX,EAAK,QAAA,GACLR,EAAQ,UAAU;AAAA,IACpB;AAAA,EACF,GAAG,CAACJ,CAAO,CAAC,GAGVc,gBAAAA,EAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAKZ;AAAA,MACL,SAAQ;AAAA,MACR,WAAAD;AAAA,MACA,OAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ,GAAGI,CAAM;AAAA,QACjB,QAAQ;AAAA,MAAA;AAAA,MAEV,OAAM;AAAA,IAAA;AAAA,EAAA;AAGZ;"}
@@ -0,0 +1,6 @@
1
+ import { default as React } from 'react';
2
+ export interface SandboxAppProps {
3
+ html: string;
4
+ }
5
+ declare const SandboxApp: React.FC<SandboxAppProps>;
6
+ export default SandboxApp;
@@ -0,0 +1,21 @@
1
+ import { j as s } from "../../_virtual/jsx-runtime.js";
2
+ import { useRef as i, useEffect as u } from "react";
3
+ const p = ({ html: o }) => {
4
+ const c = i(null);
5
+ return u(() => {
6
+ const e = c.current;
7
+ if (!e) return;
8
+ e.innerHTML = "";
9
+ const t = document.createElement("div");
10
+ t.innerHTML = o, t.querySelectorAll("script").forEach((r) => {
11
+ const n = document.createElement("script");
12
+ Array.from(r.attributes).forEach((a) => {
13
+ n.setAttribute(a.name, a.value);
14
+ }), n.textContent = r.textContent, r.replaceWith(n);
15
+ }), e.append(...Array.from(t.childNodes));
16
+ }, [o]), /* @__PURE__ */ s.jsx("div", { ref: c });
17
+ };
18
+ export {
19
+ p as default
20
+ };
21
+ //# sourceMappingURL=SandboxApp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SandboxApp.js","sources":["../../../src/components/ContentRender/SandboxApp.tsx"],"sourcesContent":["import React, { useEffect, useRef } from \"react\";\n\nexport interface SandboxAppProps {\n html: string;\n}\n\nconst SandboxApp: React.FC<SandboxAppProps> = ({ html }) => {\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n container.innerHTML = \"\";\n const wrapper = document.createElement(\"div\");\n wrapper.innerHTML = html;\n\n // Ensure inline scripts execute by recreating them after injection\n wrapper.querySelectorAll(\"script\").forEach((script) => {\n const replacement = document.createElement(\"script\");\n Array.from(script.attributes).forEach((attr) => {\n replacement.setAttribute(attr.name, attr.value);\n });\n replacement.textContent = script.textContent;\n script.replaceWith(replacement);\n });\n\n container.append(...Array.from(wrapper.childNodes));\n }, [html]);\n\n return <div ref={containerRef} />;\n};\n\nexport default SandboxApp;\n"],"names":["SandboxApp","html","containerRef","useRef","useEffect","container","wrapper","script","replacement","attr","jsx"],"mappings":";;AAMA,MAAMA,IAAwC,CAAC,EAAE,MAAAC,QAAW;AAC1D,QAAMC,IAAeC,EAAuB,IAAI;AAEhD,SAAAC,EAAU,MAAM;AACd,UAAMC,IAAYH,EAAa;AAC/B,QAAI,CAACG,EAAW;AAEhB,IAAAA,EAAU,YAAY;AACtB,UAAMC,IAAU,SAAS,cAAc,KAAK;AAC5C,IAAAA,EAAQ,YAAYL,GAGpBK,EAAQ,iBAAiB,QAAQ,EAAE,QAAQ,CAACC,MAAW;AACrD,YAAMC,IAAc,SAAS,cAAc,QAAQ;AACnD,YAAM,KAAKD,EAAO,UAAU,EAAE,QAAQ,CAACE,MAAS;AAC9C,QAAAD,EAAY,aAAaC,EAAK,MAAMA,EAAK,KAAK;AAAA,MAChD,CAAC,GACDD,EAAY,cAAcD,EAAO,aACjCA,EAAO,YAAYC,CAAW;AAAA,IAChC,CAAC,GAEDH,EAAU,OAAO,GAAG,MAAM,KAAKC,EAAQ,UAAU,CAAC;AAAA,EACpD,GAAG,CAACL,CAAI,CAAC,GAEFS,gBAAAA,EAAAA,IAAC,OAAA,EAAI,KAAKR,EAAA,CAAc;AACjC;"}
@@ -1,7 +1,7 @@
1
1
  import { j as i } from "../../../_virtual/jsx-runtime.js";
2
2
  import * as d from "react";
3
3
  import n from "../../../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.js";
4
- import "../../../_virtual/index4.js";
4
+ import "../../../_virtual/index3.js";
5
5
  import "../../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-resize-observer@1.4.3_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-resize-observer/es/index.js";
6
6
  import "../../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-util@5.44.4_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-util/es/hooks/useLayoutEffect.js";
7
7
  import "../../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-util@5.44.4_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-util/es/raf.js";