markdown-flow-ui 0.1.86 → 0.1.87
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.
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/classnames@2.5.1/node_modules/classnames/index.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/classnames@2.5.1/node_modules/classnames/index.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/hast-util-to-jsx-runtime@2.3.6/node_modules/hast-util-to-jsx-runtime/lib/index.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/hast-util-to-jsx-runtime@2.3.6/node_modules/hast-util-to-jsx-runtime/lib/index.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/c4Diagram-YG6GDRKO.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/c4Diagram-YG6GDRKO.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/chunk-S3R3BYOJ.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/chunk-S3R3BYOJ.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/chunk-TZMSLE5B.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/chunk-TZMSLE5B.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/ganttDiagram-LVOFAZNH.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/ganttDiagram-LVOFAZNH.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/sequenceDiagram-WL72ISMW.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/sequenceDiagram-WL72ISMW.es.js +1 -1
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-flow@0.1.6/node_modules/remark-flow/dist/index.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-flow@0.1.6/node_modules/remark-flow/dist/index.es.js +1 -1
- 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
- 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
- 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
- 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
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/style-to-object@1.0.11/node_modules/style-to-object/cjs/index.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/style-to-object@1.0.11/node_modules/style-to-object/cjs/index.cjs.js.map +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/style-to-object@1.0.11/node_modules/style-to-object/cjs/index.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/unified@11.0.5/node_modules/unified/lib/index.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/unified@11.0.5/node_modules/unified/lib/index.es.js +1 -1
- package/dist/_virtual/index.cjs10.js +1 -1
- package/dist/_virtual/index.cjs2.js +1 -1
- package/dist/_virtual/index.cjs3.js +1 -1
- package/dist/_virtual/index.cjs4.js +1 -1
- package/dist/_virtual/index.cjs5.js +1 -1
- package/dist/_virtual/index.cjs6.js +1 -1
- package/dist/_virtual/index.cjs7.js +1 -1
- package/dist/_virtual/index.cjs8.js +1 -1
- package/dist/_virtual/index.es10.js +2 -2
- package/dist/_virtual/index.es2.js +2 -5
- package/dist/_virtual/index.es2.js.map +1 -1
- package/dist/_virtual/index.es3.js +4 -2
- package/dist/_virtual/index.es3.js.map +1 -1
- package/dist/_virtual/index.es4.js +5 -4
- package/dist/_virtual/index.es4.js.map +1 -1
- package/dist/_virtual/index.es5.js +5 -3
- package/dist/_virtual/index.es5.js.map +1 -1
- package/dist/_virtual/index.es6.js +5 -2
- package/dist/_virtual/index.es6.js.map +1 -1
- package/dist/_virtual/index.es7.js +2 -5
- package/dist/_virtual/index.es7.js.map +1 -1
- package/dist/_virtual/index.es8.js +3 -5
- package/dist/_virtual/index.es8.js.map +1 -1
- package/dist/assets/markdown-flow-ui.css +1 -1
- package/dist/components/ContentRender/ContentRender.cjs.js +2 -2
- package/dist/components/ContentRender/ContentRender.cjs.js.map +1 -1
- package/dist/components/ContentRender/ContentRender.es.js +158 -143
- package/dist/components/ContentRender/ContentRender.es.js.map +1 -1
- package/dist/components/ContentRender/IframeSandbox.cjs.js +3 -2
- package/dist/components/ContentRender/IframeSandbox.cjs.js.map +1 -1
- package/dist/components/ContentRender/IframeSandbox.es.js +13 -12
- package/dist/components/ContentRender/IframeSandbox.es.js.map +1 -1
- package/dist/components/ContentRender/SandboxApp.cjs.js +7 -1
- package/dist/components/ContentRender/SandboxApp.cjs.js.map +1 -1
- package/dist/components/ContentRender/SandboxApp.d.ts +0 -1
- package/dist/components/ContentRender/SandboxApp.es.js +66 -60
- package/dist/components/ContentRender/SandboxApp.es.js.map +1 -1
- package/dist/components/ContentRender/utils/split-content.cjs.js +3 -3
- package/dist/components/ContentRender/utils/split-content.cjs.js.map +1 -1
- package/dist/components/ContentRender/utils/split-content.es.js +100 -46
- package/dist/components/ContentRender/utils/split-content.es.js.map +1 -1
- package/dist/components/ui/inputGroup/textarea.cjs.js +1 -1
- package/dist/components/ui/inputGroup/textarea.es.js +1 -1
- package/dist/markdown-flow-ui-lib.css +1 -1
- package/package.json +1 -1
|
@@ -1,133 +1,139 @@
|
|
|
1
|
-
import { j as
|
|
2
|
-
import { useRef as n, useState as
|
|
3
|
-
import
|
|
4
|
-
const
|
|
1
|
+
import { j as v } from "../../_virtual/jsx-runtime.es.js";
|
|
2
|
+
import { useRef as n, useState as A, useEffect as N } from "react";
|
|
3
|
+
import K from "../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/loader-circle.es.js";
|
|
4
|
+
const Z = ({
|
|
5
5
|
html: u,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
scriptLoadingText: k,
|
|
6
|
+
styleLoadingText: F,
|
|
7
|
+
scriptLoadingText: z,
|
|
9
8
|
resetToken: f = 0,
|
|
10
|
-
mode:
|
|
9
|
+
mode: W = "content"
|
|
11
10
|
}) => {
|
|
12
|
-
const
|
|
11
|
+
const k = n(null), S = n(null), [, I] = A(!0), [q, b] = A(!1), [H, C] = A(!1), w = n([]), E = n([]), j = n(0), L = n(0), p = n(null), d = n(null), m = n(!1), h = n(!1), R = n(!1), M = n(f), V = 200, c = (t) => {
|
|
13
12
|
t.current && (clearTimeout(t.current), t.current = null);
|
|
14
|
-
},
|
|
15
|
-
const
|
|
13
|
+
}, D = (t, s, o, x) => {
|
|
14
|
+
const i = performance.now() - o.current, g = Math.max(0, V - i);
|
|
16
15
|
c(s), s.current = window.setTimeout(() => {
|
|
17
|
-
t(!1),
|
|
18
|
-
},
|
|
16
|
+
t(!1), x?.(), s.current = null;
|
|
17
|
+
}, g);
|
|
19
18
|
};
|
|
20
|
-
|
|
21
|
-
const t =
|
|
19
|
+
N(() => {
|
|
20
|
+
const t = S.current?.ownerDocument;
|
|
22
21
|
if (!t) return;
|
|
23
22
|
const s = "sandbox-spinner-style";
|
|
24
23
|
let o = t.getElementById(s);
|
|
25
|
-
o || (o = t.createElement("style"), o.id = s,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
o || (o = t.createElement("style"), o.id = s, t.head?.appendChild(o)), o.textContent = `
|
|
25
|
+
@keyframes sandbox-spin { from { transform: rotate(0deg);} to { transform: rotate(360deg);} }
|
|
26
|
+
.sandbox-wrapper { align-items: center; }
|
|
27
|
+
@media (max-width: 640px) {
|
|
28
|
+
.sandbox-wrapper { align-items: stretch; }
|
|
29
|
+
}
|
|
30
|
+
`;
|
|
31
|
+
}, []), N(() => {
|
|
32
|
+
f !== M.current && (R.current = !1, M.current = f), c(p), c(d), m.current = !1, h.current = !1;
|
|
33
|
+
const t = S.current;
|
|
29
34
|
if (!t) return;
|
|
30
35
|
const s = t.ownerDocument, o = s?.body;
|
|
31
36
|
if (!o) return;
|
|
32
|
-
w.current.forEach((e) => e.remove()), w.current = [],
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
Array.from(
|
|
37
|
+
w.current.forEach((e) => e.remove()), w.current = [], E.current.forEach((e) => e.remove()), E.current = [];
|
|
38
|
+
const x = R.current;
|
|
39
|
+
I(!x), b(!1), C(!1), t.innerHTML = "";
|
|
40
|
+
const i = document.createElement("div");
|
|
41
|
+
i.innerHTML = u;
|
|
42
|
+
const g = (u.match(/<script[\s>]/gi) || []).length, O = (u.match(/<\/script>/gi) || []).length, Q = g > 0 && g === O, l = [];
|
|
43
|
+
Array.from(i.querySelectorAll("style, script")).forEach((e) => {
|
|
39
44
|
if (e.tagName.toLowerCase() === "style") {
|
|
40
45
|
const r = s.createElement("style");
|
|
41
|
-
r.textContent = e.textContent || "", Array.from(e.attributes).forEach((
|
|
42
|
-
r.setAttribute(
|
|
46
|
+
r.textContent = e.textContent || "", Array.from(e.attributes).forEach((a) => {
|
|
47
|
+
r.setAttribute(a.name, a.value);
|
|
43
48
|
}), l.push(r);
|
|
44
49
|
} else {
|
|
45
50
|
const r = s.createElement("script");
|
|
46
|
-
Array.from(e.attributes).forEach((
|
|
47
|
-
r.setAttribute(
|
|
51
|
+
Array.from(e.attributes).forEach((a) => {
|
|
52
|
+
r.setAttribute(a.name, a.value);
|
|
48
53
|
}), r.textContent = e.textContent || "", l.push(r);
|
|
49
54
|
}
|
|
50
55
|
e.remove();
|
|
51
56
|
});
|
|
52
|
-
const
|
|
57
|
+
const T = l.some(
|
|
53
58
|
(e) => e.tagName.toLowerCase() === "style"
|
|
54
|
-
),
|
|
59
|
+
), B = l.some(
|
|
55
60
|
(e) => e.tagName.toLowerCase() === "script"
|
|
56
61
|
);
|
|
57
|
-
|
|
58
|
-
const G = !!
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
t.append(...
|
|
62
|
+
T && (m.current = !0, j.current = performance.now(), c(p), b(!0)), B && (h.current = !0, L.current = performance.now(), c(d), C(!0));
|
|
63
|
+
const G = !!i.firstElementChild;
|
|
64
|
+
I(!G && !x), G && (R.current = !0);
|
|
65
|
+
const J = Array.from(i.childNodes);
|
|
66
|
+
t.append(...J), l.forEach((e) => {
|
|
62
67
|
if (e.tagName.toLowerCase() === "style") {
|
|
63
68
|
s.head?.appendChild(e), w.current.push(e);
|
|
64
69
|
return;
|
|
65
70
|
}
|
|
66
|
-
if (
|
|
67
|
-
const r = e,
|
|
71
|
+
if (Q) {
|
|
72
|
+
const r = e, a = r.textContent || "";
|
|
68
73
|
if (!r.src)
|
|
69
74
|
try {
|
|
70
|
-
new Function(
|
|
75
|
+
new Function(a);
|
|
71
76
|
} catch {
|
|
72
77
|
r.remove();
|
|
73
78
|
return;
|
|
74
79
|
}
|
|
75
80
|
try {
|
|
76
|
-
o.appendChild(r),
|
|
81
|
+
o.appendChild(r), E.current.push(r);
|
|
77
82
|
} catch {
|
|
78
83
|
r.remove();
|
|
79
84
|
}
|
|
80
85
|
} else
|
|
81
86
|
e.remove();
|
|
82
87
|
}), requestAnimationFrame(() => {
|
|
83
|
-
|
|
84
|
-
|
|
88
|
+
T && D(
|
|
89
|
+
b,
|
|
85
90
|
p,
|
|
86
91
|
j,
|
|
87
92
|
() => {
|
|
88
93
|
m.current = !1;
|
|
89
94
|
}
|
|
90
|
-
),
|
|
91
|
-
|
|
95
|
+
), B && D(
|
|
96
|
+
C,
|
|
92
97
|
d,
|
|
93
|
-
|
|
98
|
+
L,
|
|
94
99
|
() => {
|
|
95
100
|
h.current = !1;
|
|
96
101
|
}
|
|
97
102
|
);
|
|
98
103
|
});
|
|
99
|
-
}, [u, f]),
|
|
104
|
+
}, [u, f]), N(
|
|
100
105
|
() => () => {
|
|
101
106
|
c(p), c(d);
|
|
102
107
|
},
|
|
103
108
|
[]
|
|
104
109
|
);
|
|
105
|
-
const y =
|
|
106
|
-
return /* @__PURE__ */
|
|
110
|
+
const y = H || h.current ? z || "Building scripts cache..." : q || m.current ? F || "Building styles..." : null, _ = W === "blackboard";
|
|
111
|
+
return /* @__PURE__ */ v.jsxs(
|
|
107
112
|
"div",
|
|
108
113
|
{
|
|
109
|
-
ref:
|
|
114
|
+
ref: k,
|
|
115
|
+
className: "sandbox-wrapper",
|
|
110
116
|
style: {
|
|
111
117
|
position: "relative",
|
|
112
118
|
width: "100%",
|
|
113
|
-
height:
|
|
114
|
-
display:
|
|
115
|
-
flexDirection:
|
|
119
|
+
height: _ ? "100vh" : void 0,
|
|
120
|
+
display: "flex",
|
|
121
|
+
flexDirection: "column",
|
|
116
122
|
// if use center, too long iframe wont see header
|
|
117
|
-
justifyContent:
|
|
123
|
+
justifyContent: "space-around"
|
|
118
124
|
},
|
|
119
125
|
"aria-busy": !!y,
|
|
120
126
|
children: [
|
|
121
|
-
/* @__PURE__ */
|
|
127
|
+
/* @__PURE__ */ v.jsx(
|
|
122
128
|
"div",
|
|
123
129
|
{
|
|
124
|
-
ref:
|
|
130
|
+
ref: S,
|
|
125
131
|
style: {
|
|
126
132
|
pointerEvents: y ? "none" : void 0
|
|
127
133
|
}
|
|
128
134
|
}
|
|
129
135
|
),
|
|
130
|
-
y && /* @__PURE__ */
|
|
136
|
+
y && /* @__PURE__ */ v.jsxs(
|
|
131
137
|
"div",
|
|
132
138
|
{
|
|
133
139
|
style: {
|
|
@@ -145,8 +151,8 @@ const ee = ({
|
|
|
145
151
|
zIndex: 20
|
|
146
152
|
},
|
|
147
153
|
children: [
|
|
148
|
-
/* @__PURE__ */
|
|
149
|
-
|
|
154
|
+
/* @__PURE__ */ v.jsx(
|
|
155
|
+
K,
|
|
150
156
|
{
|
|
151
157
|
"aria-hidden": !0,
|
|
152
158
|
size: 20,
|
|
@@ -162,6 +168,6 @@ const ee = ({
|
|
|
162
168
|
);
|
|
163
169
|
};
|
|
164
170
|
export {
|
|
165
|
-
|
|
171
|
+
Z as default
|
|
166
172
|
};
|
|
167
173
|
//# sourceMappingURL=SandboxApp.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SandboxApp.es.js","sources":["../../../src/components/ContentRender/SandboxApp.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport { Loader2 } from \"lucide-react\";\n\nexport interface SandboxAppProps {\n html: string;\n loadingText?: string;\n styleLoadingText?: string;\n scriptLoadingText?: string;\n resetToken?: number;\n mode?: \"content\" | \"blackboard\";\n}\n\nconst SandboxApp: React.FC<SandboxAppProps> = ({\n html,\n loadingText,\n styleLoadingText,\n scriptLoadingText,\n resetToken = 0,\n mode = \"content\",\n}) => {\n const wrapperRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const [isWaitingFirstDiv, setIsWaitingFirstDiv] = useState(true);\n const [isGeneratingStyles, setIsGeneratingStyles] = useState(false);\n const [isGeneratingScripts, setIsGeneratingScripts] = useState(false);\n const appendedStylesRef = useRef<HTMLStyleElement[]>([]);\n const appendedScriptsRef = useRef<HTMLScriptElement[]>([]);\n const styleStartRef = useRef(0);\n const scriptStartRef = useRef(0);\n const styleTimerRef = useRef<number | null>(null);\n const scriptTimerRef = useRef<number | null>(null);\n const hasStylesRef = useRef(false);\n const hasScriptsRef = useRef(false);\n const hasRenderedContentRef = useRef(false);\n const prevResetTokenRef = useRef(resetToken);\n const MIN_LOADING_MS = 200;\n\n const clearTimer = (timerRef: React.MutableRefObject<number | null>) => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n\n const settleStateWithMinimumDelay = (\n setter: React.Dispatch<React.SetStateAction<boolean>>,\n timerRef: React.MutableRefObject<number | null>,\n startRef: React.MutableRefObject<number>,\n onDone?: () => void\n ) => {\n const elapsed = performance.now() - startRef.current;\n const delay = Math.max(0, MIN_LOADING_MS - elapsed);\n clearTimer(timerRef);\n timerRef.current = window.setTimeout(() => {\n setter(false);\n onDone?.();\n timerRef.current = null;\n }, delay);\n };\n\n useEffect(() => {\n const doc = containerRef.current?.ownerDocument;\n if (!doc) return;\n const styleId = \"sandbox-spinner-style\";\n let styleEl = doc.getElementById(styleId) as HTMLStyleElement | null;\n if (!styleEl) {\n styleEl = doc.createElement(\"style\");\n styleEl.id = styleId;\n styleEl.textContent =\n \"@keyframes sandbox-spin { from { transform: rotate(0deg);} to { transform: rotate(360deg);} }\";\n doc.head?.appendChild(styleEl);\n }\n }, []);\n\n useEffect(() => {\n if (resetToken !== prevResetTokenRef.current) {\n hasRenderedContentRef.current = false;\n prevResetTokenRef.current = resetToken;\n }\n clearTimer(styleTimerRef);\n clearTimer(scriptTimerRef);\n hasStylesRef.current = false;\n hasScriptsRef.current = false;\n\n const container = containerRef.current;\n if (!container) return;\n const doc = container.ownerDocument;\n const body = doc?.body;\n if (!body) return;\n\n appendedStylesRef.current.forEach((node) => node.remove());\n appendedStylesRef.current = [];\n appendedScriptsRef.current.forEach((node) => node.remove());\n appendedScriptsRef.current = [];\n\n const hasRenderedBefore = hasRenderedContentRef.current;\n setIsWaitingFirstDiv(!hasRenderedBefore);\n setIsGeneratingStyles(false);\n setIsGeneratingScripts(false);\n container.innerHTML = \"\";\n const wrapper = document.createElement(\"div\");\n wrapper.innerHTML = html;\n\n const openScriptCount = (html.match(/<script[\\s>]/gi) || []).length;\n const closeScriptCount = (html.match(/<\\/script>/gi) || []).length;\n const shouldExecuteScripts =\n openScriptCount > 0 && openScriptCount === closeScriptCount;\n\n const resourceQueue: HTMLElement[] = [];\n\n Array.from(wrapper.querySelectorAll(\"style, script\")).forEach((node) => {\n if (node.tagName.toLowerCase() === \"style\") {\n const cloned = doc.createElement(\"style\");\n cloned.textContent = node.textContent || \"\";\n Array.from(node.attributes).forEach((attr) => {\n cloned.setAttribute(attr.name, attr.value);\n });\n resourceQueue.push(cloned);\n } else {\n const replacement = doc.createElement(\"script\");\n Array.from(node.attributes).forEach((attr) => {\n replacement.setAttribute(attr.name, attr.value);\n });\n replacement.textContent = node.textContent || \"\";\n resourceQueue.push(replacement);\n }\n node.remove();\n });\n\n const hasStyles = resourceQueue.some(\n (node) => node.tagName.toLowerCase() === \"style\"\n );\n const hasScripts = resourceQueue.some(\n (node) => node.tagName.toLowerCase() === \"script\"\n );\n if (hasStyles) {\n hasStylesRef.current = true;\n styleStartRef.current = performance.now();\n clearTimer(styleTimerRef);\n setIsGeneratingStyles(true);\n }\n if (hasScripts) {\n hasScriptsRef.current = true;\n scriptStartRef.current = performance.now();\n clearTimer(scriptTimerRef);\n setIsGeneratingScripts(true);\n }\n\n const hasFirstElement = !!wrapper.firstElementChild;\n setIsWaitingFirstDiv(!hasFirstElement && !hasRenderedBefore);\n if (hasFirstElement) {\n hasRenderedContentRef.current = true;\n }\n\n const contentNodes = Array.from(wrapper.childNodes);\n container.append(...contentNodes);\n\n resourceQueue.forEach((node) => {\n if (node.tagName.toLowerCase() === \"style\") {\n doc.head?.appendChild(node);\n appendedStylesRef.current.push(node as HTMLStyleElement);\n return;\n }\n\n if (shouldExecuteScripts) {\n const scriptNode = node as HTMLScriptElement;\n const scriptText = scriptNode.textContent || \"\";\n const shouldValidate = !scriptNode.src;\n\n if (shouldValidate) {\n try {\n // Validate script is syntactically complete before executing\n\n new Function(scriptText);\n } catch {\n scriptNode.remove();\n return;\n }\n }\n\n try {\n body.appendChild(scriptNode);\n appendedScriptsRef.current.push(scriptNode);\n } catch {\n scriptNode.remove();\n }\n } else {\n // Defer execution until all script tags are fully received\n node.remove();\n }\n });\n requestAnimationFrame(() => {\n if (hasStyles) {\n settleStateWithMinimumDelay(\n setIsGeneratingStyles,\n styleTimerRef,\n styleStartRef,\n () => {\n hasStylesRef.current = false;\n }\n );\n }\n if (hasScripts) {\n settleStateWithMinimumDelay(\n setIsGeneratingScripts,\n scriptTimerRef,\n scriptStartRef,\n () => {\n hasScriptsRef.current = false;\n }\n );\n }\n });\n }, [html, resetToken]);\n\n useEffect(\n () => () => {\n clearTimer(styleTimerRef);\n clearTimer(scriptTimerRef);\n },\n []\n );\n\n const overlayMessage = (() => {\n if (isGeneratingScripts || hasScriptsRef.current)\n return scriptLoadingText || \"Building scripts cache...\";\n if (isGeneratingStyles || hasStylesRef.current)\n return styleLoadingText || \"Building styles...\";\n if (isWaitingFirstDiv) return loadingText || \"Loading...\";\n return null;\n })();\n\n const isBlackboard = mode === \"blackboard\";\n\n return (\n <div\n ref={wrapperRef}\n style={{\n position: \"relative\",\n width: \"100%\",\n height: isBlackboard ? \"100vh\" : undefined,\n display: isBlackboard ? \"flex\" : undefined,\n flexDirection: isBlackboard ? \"column\" : undefined,\n // if use center, too long iframe wont see header\n justifyContent: isBlackboard ? \"space-around\" : undefined,\n }}\n aria-busy={!!overlayMessage}\n >\n <div\n ref={containerRef}\n style={{\n pointerEvents: overlayMessage ? \"none\" : undefined,\n }}\n />\n {overlayMessage && (\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: \"rgba(51, 51, 51, 0.80)\",\n color: \"#ffffff\",\n fontSize: 16,\n fontWeight: 700,\n gap: 10,\n pointerEvents: \"auto\",\n zIndex: 20,\n }}\n >\n <Loader2\n aria-hidden\n size={20}\n style={{ animation: \"sandbox-spin 1s linear infinite\" }}\n />\n {overlayMessage}\n </div>\n )}\n </div>\n );\n};\n\nexport default SandboxApp;\n"],"names":["SandboxApp","html","loadingText","styleLoadingText","scriptLoadingText","resetToken","mode","wrapperRef","useRef","containerRef","isWaitingFirstDiv","setIsWaitingFirstDiv","useState","isGeneratingStyles","setIsGeneratingStyles","isGeneratingScripts","setIsGeneratingScripts","appendedStylesRef","appendedScriptsRef","styleStartRef","scriptStartRef","styleTimerRef","scriptTimerRef","hasStylesRef","hasScriptsRef","hasRenderedContentRef","prevResetTokenRef","MIN_LOADING_MS","clearTimer","timerRef","settleStateWithMinimumDelay","setter","startRef","onDone","elapsed","delay","useEffect","doc","styleId","styleEl","container","body","node","hasRenderedBefore","wrapper","openScriptCount","closeScriptCount","shouldExecuteScripts","resourceQueue","cloned","attr","replacement","hasStyles","hasScripts","hasFirstElement","contentNodes","scriptNode","scriptText","overlayMessage","isBlackboard","jsxs","jsx","Loader2"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SandboxApp.es.js","sources":["../../../src/components/ContentRender/SandboxApp.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport { Loader2 } from \"lucide-react\";\n\nexport interface SandboxAppProps {\n html: string;\n styleLoadingText?: string;\n scriptLoadingText?: string;\n resetToken?: number;\n mode?: \"content\" | \"blackboard\";\n}\n\nconst SandboxApp: React.FC<SandboxAppProps> = ({\n html,\n styleLoadingText,\n scriptLoadingText,\n resetToken = 0,\n mode = \"content\",\n}) => {\n const wrapperRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const [, setIsWaitingFirstDiv] = useState(true);\n const [isGeneratingStyles, setIsGeneratingStyles] = useState(false);\n const [isGeneratingScripts, setIsGeneratingScripts] = useState(false);\n const appendedStylesRef = useRef<HTMLStyleElement[]>([]);\n const appendedScriptsRef = useRef<HTMLScriptElement[]>([]);\n const styleStartRef = useRef(0);\n const scriptStartRef = useRef(0);\n const styleTimerRef = useRef<number | null>(null);\n const scriptTimerRef = useRef<number | null>(null);\n const hasStylesRef = useRef(false);\n const hasScriptsRef = useRef(false);\n const hasRenderedContentRef = useRef(false);\n const prevResetTokenRef = useRef(resetToken);\n const MIN_LOADING_MS = 200;\n\n const clearTimer = (timerRef: React.MutableRefObject<number | null>) => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n\n const settleStateWithMinimumDelay = (\n setter: React.Dispatch<React.SetStateAction<boolean>>,\n timerRef: React.MutableRefObject<number | null>,\n startRef: React.MutableRefObject<number>,\n onDone?: () => void\n ) => {\n const elapsed = performance.now() - startRef.current;\n const delay = Math.max(0, MIN_LOADING_MS - elapsed);\n clearTimer(timerRef);\n timerRef.current = window.setTimeout(() => {\n setter(false);\n onDone?.();\n timerRef.current = null;\n }, delay);\n };\n\n useEffect(() => {\n const doc = containerRef.current?.ownerDocument;\n if (!doc) return;\n const styleId = \"sandbox-spinner-style\";\n let styleEl = doc.getElementById(styleId) as HTMLStyleElement | null;\n if (!styleEl) {\n styleEl = doc.createElement(\"style\");\n styleEl.id = styleId;\n doc.head?.appendChild(styleEl);\n }\n styleEl.textContent = `\n @keyframes sandbox-spin { from { transform: rotate(0deg);} to { transform: rotate(360deg);} }\n .sandbox-wrapper { align-items: center; }\n @media (max-width: 640px) {\n .sandbox-wrapper { align-items: stretch; }\n }\n `;\n }, []);\n\n useEffect(() => {\n if (resetToken !== prevResetTokenRef.current) {\n hasRenderedContentRef.current = false;\n prevResetTokenRef.current = resetToken;\n }\n clearTimer(styleTimerRef);\n clearTimer(scriptTimerRef);\n hasStylesRef.current = false;\n hasScriptsRef.current = false;\n\n const container = containerRef.current;\n if (!container) return;\n const doc = container.ownerDocument;\n const body = doc?.body;\n if (!body) return;\n\n appendedStylesRef.current.forEach((node) => node.remove());\n appendedStylesRef.current = [];\n appendedScriptsRef.current.forEach((node) => node.remove());\n appendedScriptsRef.current = [];\n\n const hasRenderedBefore = hasRenderedContentRef.current;\n setIsWaitingFirstDiv(!hasRenderedBefore);\n setIsGeneratingStyles(false);\n setIsGeneratingScripts(false);\n container.innerHTML = \"\";\n const wrapper = document.createElement(\"div\");\n wrapper.innerHTML = html;\n\n const openScriptCount = (html.match(/<script[\\s>]/gi) || []).length;\n const closeScriptCount = (html.match(/<\\/script>/gi) || []).length;\n const shouldExecuteScripts =\n openScriptCount > 0 && openScriptCount === closeScriptCount;\n\n const resourceQueue: HTMLElement[] = [];\n\n Array.from(wrapper.querySelectorAll(\"style, script\")).forEach((node) => {\n if (node.tagName.toLowerCase() === \"style\") {\n const cloned = doc.createElement(\"style\");\n cloned.textContent = node.textContent || \"\";\n Array.from(node.attributes).forEach((attr) => {\n cloned.setAttribute(attr.name, attr.value);\n });\n resourceQueue.push(cloned);\n } else {\n const replacement = doc.createElement(\"script\");\n Array.from(node.attributes).forEach((attr) => {\n replacement.setAttribute(attr.name, attr.value);\n });\n replacement.textContent = node.textContent || \"\";\n resourceQueue.push(replacement);\n }\n node.remove();\n });\n\n const hasStyles = resourceQueue.some(\n (node) => node.tagName.toLowerCase() === \"style\"\n );\n const hasScripts = resourceQueue.some(\n (node) => node.tagName.toLowerCase() === \"script\"\n );\n if (hasStyles) {\n hasStylesRef.current = true;\n styleStartRef.current = performance.now();\n clearTimer(styleTimerRef);\n setIsGeneratingStyles(true);\n }\n if (hasScripts) {\n hasScriptsRef.current = true;\n scriptStartRef.current = performance.now();\n clearTimer(scriptTimerRef);\n setIsGeneratingScripts(true);\n }\n\n const hasFirstElement = !!wrapper.firstElementChild;\n setIsWaitingFirstDiv(!hasFirstElement && !hasRenderedBefore);\n if (hasFirstElement) {\n hasRenderedContentRef.current = true;\n }\n\n const contentNodes = Array.from(wrapper.childNodes);\n container.append(...contentNodes);\n\n resourceQueue.forEach((node) => {\n if (node.tagName.toLowerCase() === \"style\") {\n doc.head?.appendChild(node);\n appendedStylesRef.current.push(node as HTMLStyleElement);\n return;\n }\n\n if (shouldExecuteScripts) {\n const scriptNode = node as HTMLScriptElement;\n const scriptText = scriptNode.textContent || \"\";\n const shouldValidate = !scriptNode.src;\n\n if (shouldValidate) {\n try {\n // Validate script is syntactically complete before executing\n\n new Function(scriptText);\n } catch {\n scriptNode.remove();\n return;\n }\n }\n\n try {\n body.appendChild(scriptNode);\n appendedScriptsRef.current.push(scriptNode);\n } catch {\n scriptNode.remove();\n }\n } else {\n // Defer execution until all script tags are fully received\n node.remove();\n }\n });\n requestAnimationFrame(() => {\n if (hasStyles) {\n settleStateWithMinimumDelay(\n setIsGeneratingStyles,\n styleTimerRef,\n styleStartRef,\n () => {\n hasStylesRef.current = false;\n }\n );\n }\n if (hasScripts) {\n settleStateWithMinimumDelay(\n setIsGeneratingScripts,\n scriptTimerRef,\n scriptStartRef,\n () => {\n hasScriptsRef.current = false;\n }\n );\n }\n });\n }, [html, resetToken]);\n\n useEffect(\n () => () => {\n clearTimer(styleTimerRef);\n clearTimer(scriptTimerRef);\n },\n []\n );\n\n const overlayMessage = (() => {\n if (isGeneratingScripts || hasScriptsRef.current)\n return scriptLoadingText || \"Building scripts cache...\";\n if (isGeneratingStyles || hasStylesRef.current)\n return styleLoadingText || \"Building styles...\";\n return null;\n })();\n\n const isBlackboard = mode === \"blackboard\";\n\n return (\n <div\n ref={wrapperRef}\n className=\"sandbox-wrapper\"\n style={{\n position: \"relative\",\n width: \"100%\",\n height: isBlackboard ? \"100vh\" : undefined,\n display: \"flex\",\n flexDirection: \"column\",\n // if use center, too long iframe wont see header\n justifyContent: \"space-around\",\n }}\n aria-busy={!!overlayMessage}\n >\n <div\n ref={containerRef}\n style={{\n pointerEvents: overlayMessage ? \"none\" : undefined,\n }}\n />\n {overlayMessage && (\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: \"rgba(51, 51, 51, 0.80)\",\n color: \"#ffffff\",\n fontSize: 16,\n fontWeight: 700,\n gap: 10,\n pointerEvents: \"auto\",\n zIndex: 20,\n }}\n >\n <Loader2\n aria-hidden\n size={20}\n style={{ animation: \"sandbox-spin 1s linear infinite\" }}\n />\n {overlayMessage}\n </div>\n )}\n </div>\n );\n};\n\nexport default SandboxApp;\n"],"names":["SandboxApp","html","styleLoadingText","scriptLoadingText","resetToken","mode","wrapperRef","useRef","containerRef","setIsWaitingFirstDiv","useState","isGeneratingStyles","setIsGeneratingStyles","isGeneratingScripts","setIsGeneratingScripts","appendedStylesRef","appendedScriptsRef","styleStartRef","scriptStartRef","styleTimerRef","scriptTimerRef","hasStylesRef","hasScriptsRef","hasRenderedContentRef","prevResetTokenRef","MIN_LOADING_MS","clearTimer","timerRef","settleStateWithMinimumDelay","setter","startRef","onDone","elapsed","delay","useEffect","doc","styleId","styleEl","container","body","node","hasRenderedBefore","wrapper","openScriptCount","closeScriptCount","shouldExecuteScripts","resourceQueue","cloned","attr","replacement","hasStyles","hasScripts","hasFirstElement","contentNodes","scriptNode","scriptText","overlayMessage","isBlackboard","jsxs","jsx","Loader2"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
2
|
-
`),
|
|
3
|
-
`);return{start:
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const N=/<(script|style|link|iframe|html|head|body|meta|title|base|template|div|section|article|main)[\s>]/i,R=[/<svg[\s\S]*?<\/svg>/i,/<img\b[^>]*?>/i,/```mermaid[\s\S]*?```/i,/```[a-zA-Z0-9]+[\s\S]*?```/i],M=/!\[[^\]]*]\([^\s)\n]+(?:\s+"[^"]*")?\)/i,B=/<\/[a-z][^>]*>\s*\n(?=[^\s<])/gi,O=/<custom-button-after-content\b[\s\S]*?<\/custom-button-after-content>/gi,T=t=>{const e=[],n=/```/g;let s;for(;(s=n.exec(t))!==null;){const o=s.index,c=n.exec(t);if(!c){e.push({start:o,end:t.length});break}e.push({start:o,end:c.index+3})}return e},_=(t,e)=>e.some(({start:n,end:s})=>t>=n&&t<s),y=(t,e,n)=>{const s=e.flags.includes("g")?e.flags:`${e.flags}g`,o=new RegExp(e.source,s);let c;for(;(c=o.exec(t))!==null;)if(!_(c.index,n))return c.index;return-1},P=(t,e)=>{let n=t.length,s;for(B.lastIndex=0;s=B.exec(t);)if(!(s.index<=e)){n=s.index+s[0].length;break}return n},F=t=>{if(!t.length)return t;const e=[];return t.forEach(n=>{if(n.type!=="sandbox"){e.push(n);return}O.lastIndex=0;let s=0,o;for(;(o=O.exec(n.value))!==null;){const i=n.value.slice(s,o.index);i.trim()&&e.push({type:"sandbox",value:i}),e.push({type:"markdown",value:o[0]}),s=o.index+o[0].length}const c=n.value.slice(s);c.trim()&&e.push({type:"sandbox",value:c})}),e},C=t=>{let e=null;return R.forEach(n=>{const s=n.exec(t);if(!s||typeof s.index!="number")return;const o=s.index,c=s.index+s[0].length;(!e||o<e.start)&&(e={start:o,end:c})}),e},z=(t,e)=>{const n=y(t,M,e);if(n===-1)return null;const s=t.slice(n).match(M);return s?{start:n,end:n+s[0].length}:null},D=t=>{const e=t.match(/^\s*\|.+\|\s*$/m);if(!e||typeof e.index!="number")return null;const n=e[0].match(/^\s*/)?.[0].length??0,s=e.index+n,o=t.slice(s).split(`
|
|
2
|
+
`),c=[];for(const h of o){if(!h.trim().startsWith("|"))break;c.push(h)}const i=c.join(`
|
|
3
|
+
`);return{start:s,block:i,end:s+i.length}},f=(t,e=!1)=>{const n=l=>F(l),s=t.indexOf("```");if(e&&s!==-1&&t.indexOf("```",s+3)===-1)return n([{type:"markdown",value:t}]);const o=T(t),c=y(t,N,o),i=y(t,/<svg\b/i,o),h=c!==-1&&i!==-1&&c<i;if(i!==-1&&!h){const l=t.slice(0,i),r=t.indexOf("</svg>",i),a=r===-1?`${t.slice(i)}</svg>`:t.slice(i,r+6),b=r===-1?"":t.slice(r+6);if(e){const p=[];return l.trim()&&p.push({type:"text",value:l}),p.push({type:"markdown",value:a}),b.trim()&&p.push(...f(b,!0)),n(p)}if(r===-1)return n([{type:"markdown",value:a}])}const u=D(t);if(u){const l=[],r=t.slice(0,u.start);e&&r.trim()&&l.push({type:"text",value:r}),l.push({type:"markdown",value:u.block});const a=t.slice(u.end),b=a.length<t.length;return a.trim()&&b&&l.push(...e?f(a,!0):f(a)),n(l)}const m=C(t),g=z(t,o),d=m&&g?m.start<=g.start?m:g:m??g;if(c===-1&&!d)return e&&t.trim()?n([{type:"text",value:t}]):[];const v=!!d&&(c===-1||d.start<c),S=v?d.start:c,I=v?d.end:P(t,S),x=[],k=t.slice(0,S),A=t.slice(S,I),E=t.slice(I);return e&&k.trim()&&x.push({type:"text",value:k}),x.push({type:v?"markdown":"sandbox",value:A}),E.trim()&&x.push(...f(E,e)),n(x)};exports.splitContentSegments=f;
|
|
4
4
|
//# sourceMappingURL=split-content.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"split-content.cjs.js","sources":["../../../../src/components/ContentRender/utils/split-content.ts"],"sourcesContent":["export type RenderSegment =\n | { type: \"markdown\"; value: string }\n | { type: \"sandbox\"; value: string }\n | { type: \"text\"; value: string };\n\nconst SANDBOX_START_PATTERN =\n /<(script|style|link|iframe|html|head|body|meta|title|base|template|div|section|article|main)[\\s>]/i;\n\nconst INLINE_SANDBOX_PATTERNS: RegExp[] = [\n /<svg[\\s\\S]*?<\\/svg>/i,\n /<img\\b[^>]*?>/i,\n /```mermaid[\\s\\S]*?```/i,\n /```[a-zA-Z0-9]+[\\s\\S]*?```/i,\n];\n\nconst closingBoundary = /<\\/[a-z][^>]*>\\s*\\n(?=[^\\s<])/gi;\n\ntype MatchResult = { start: number; end: number };\n\nconst findHtmlBlockEnd = (raw: string, startIndex: number) => {\n let blockEnd = raw.length;\n let match: RegExpExecArray | null;\n closingBoundary.lastIndex = 0;\n\n while ((match = closingBoundary.exec(raw))) {\n if (match.index <= startIndex) continue;\n blockEnd = match.index + match[0].length;\n break;\n }\n\n return blockEnd;\n};\n\nconst findInlineSandboxMatch = (raw: string): MatchResult | null => {\n let earliest: MatchResult | null = null;\n\n INLINE_SANDBOX_PATTERNS.forEach((pattern) => {\n const match = pattern.exec(raw);\n if (!match || typeof match.index !== \"number\") return;\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (!earliest || start < earliest.start) {\n earliest = { start, end };\n }\n });\n\n return earliest;\n};\n\nconst extractTableBlock = (\n raw: string\n): { start: number; block: string; end: number } | null => {\n const tableMatch = raw.match(/^\\s*\\|.+\\|\\s*$/m);\n if (!tableMatch || typeof tableMatch.index !== \"number\") return null;\n\n const leadingSpaces = tableMatch[0].match(/^\\s*/)?.[0].length ?? 0;\n const tableStart = tableMatch.index + leadingSpaces;\n\n const lines = raw.slice(tableStart).split(\"\\n\");\n const tableLines: string[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed.startsWith(\"|\")) break;\n tableLines.push(line);\n }\n\n const block = tableLines.join(\"\\n\");\n return { start: tableStart, block, end: tableStart + block.length };\n};\n\n// Split incoming markdown content into markdown and sandbox HTML segments\nexport const splitContentSegments = (\n raw: string,\n keepText = false\n): RenderSegment[] => {\n const fenceStart = raw.indexOf(\"```\");\n if (keepText && fenceStart !== -1) {\n const closingFence = raw.indexOf(\"```\", fenceStart + 3);\n if (closingFence === -1) {\n return [{ type: \"markdown\", value: raw }];\n }\n }\n\n const svgOpenIndex = raw.search(/<svg\\b/i);\n if (svgOpenIndex !== -1 && raw.indexOf(\"</svg>\", svgOpenIndex) === -1) {\n return [{ type: \"markdown\", value: raw }];\n }\n\n const tableBlock = extractTableBlock(raw);\n if (tableBlock) {\n const segments: RenderSegment[] = [];\n const before = raw.slice(0, tableBlock.start);\n if (keepText && before.trim()) {\n segments.push({ type: \"text\", value: before });\n }\n segments.push({ type: \"markdown\", value: tableBlock.block });\n const after = raw.slice(tableBlock.end);\n const hasProgress = after.length < raw.length;\n if (after.trim() && hasProgress) {\n segments.push(\n ...(keepText\n ? splitContentSegments(after, true)\n : splitContentSegments(after))\n );\n }\n return segments;\n }\n\n const completeSvgMatch = raw.match(/<svg[\\s\\S]*?<\\/svg>/i);\n if (completeSvgMatch && keepText) {\n const hasLeadingContent =\n svgOpenIndex > -1 && raw.slice(0, svgOpenIndex).trim().length > 0;\n if (!hasLeadingContent) {\n if (!raw.trim().toLowerCase().endsWith(\"</svg>\")) {\n return [{ type: \"markdown\", value: `${raw}</svg>` }];\n }\n return [{ type: \"markdown\", value: raw }];\n }\n }\n\n const sandboxStartIndex = raw.search(SANDBOX_START_PATTERN);\n const inlineMatch = findInlineSandboxMatch(raw);\n\n if (sandboxStartIndex === -1 && !inlineMatch) {\n if (keepText && raw.trim()) {\n return [{ type: \"text\", value: raw }];\n }\n return [];\n }\n\n const shouldUseInline =\n !!inlineMatch &&\n (sandboxStartIndex === -1 || inlineMatch.start < sandboxStartIndex);\n\n const startIndex = shouldUseInline ? inlineMatch!.start : sandboxStartIndex;\n const blockEnd = shouldUseInline\n ? inlineMatch!.end\n : findHtmlBlockEnd(raw, startIndex);\n\n const segments: RenderSegment[] = [];\n const before = raw.slice(0, startIndex);\n const matchedBlock = raw.slice(startIndex, blockEnd);\n const after = raw.slice(blockEnd);\n\n if (keepText && before.trim()) {\n segments.push({ type: \"text\", value: before });\n }\n\n segments.push({\n type: shouldUseInline ? \"markdown\" : \"sandbox\",\n value: matchedBlock,\n });\n\n if (after.trim()) {\n segments.push(...splitContentSegments(after, keepText));\n }\n\n return segments;\n};\n"],"names":["SANDBOX_START_PATTERN","INLINE_SANDBOX_PATTERNS","closingBoundary","findHtmlBlockEnd","raw","startIndex","blockEnd","match","findInlineSandboxMatch","earliest","pattern","start","end","extractTableBlock","tableMatch","leadingSpaces","tableStart","lines","tableLines","line","block","splitContentSegments","keepText","fenceStart","svgOpenIndex","tableBlock","segments","before","after","hasProgress","sandboxStartIndex","inlineMatch","shouldUseInline","matchedBlock"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"split-content.cjs.js","sources":["../../../../src/components/ContentRender/utils/split-content.ts"],"sourcesContent":["export type RenderSegment =\n | { type: \"markdown\"; value: string }\n | { type: \"sandbox\"; value: string }\n | { type: \"text\"; value: string };\n\nconst SANDBOX_START_PATTERN =\n /<(script|style|link|iframe|html|head|body|meta|title|base|template|div|section|article|main)[\\s>]/i;\n\nconst INLINE_SANDBOX_PATTERNS: RegExp[] = [\n /<svg[\\s\\S]*?<\\/svg>/i,\n /<img\\b[^>]*?>/i,\n /```mermaid[\\s\\S]*?```/i,\n /```[a-zA-Z0-9]+[\\s\\S]*?```/i,\n];\nconst MARKDOWN_IMAGE_PATTERN = /!\\[[^\\]]*]\\([^\\s)\\n]+(?:\\s+\"[^\"]*\")?\\)/i;\n\nconst closingBoundary = /<\\/[a-z][^>]*>\\s*\\n(?=[^\\s<])/gi;\nconst CUSTOM_BUTTON_PATTERN =\n /<custom-button-after-content\\b[\\s\\S]*?<\\/custom-button-after-content>/gi;\n\ntype MatchResult = { start: number; end: number };\ntype FenceRange = { start: number; end: number };\n\nconst getFenceRanges = (raw: string): FenceRange[] => {\n const ranges: FenceRange[] = [];\n const fencePattern = /```/g;\n let match: RegExpExecArray | null;\n\n while ((match = fencePattern.exec(raw)) !== null) {\n const start = match.index;\n const closeMatch = fencePattern.exec(raw);\n if (!closeMatch) {\n ranges.push({ start, end: raw.length });\n break;\n }\n ranges.push({ start, end: closeMatch.index + 3 });\n }\n\n return ranges;\n};\n\nconst isIndexInRanges = (index: number, ranges: FenceRange[]) =>\n ranges.some(({ start, end }) => index >= start && index < end);\n\nconst findFirstMatchOutsideFence = (\n raw: string,\n pattern: RegExp,\n fenceRanges: FenceRange[]\n) => {\n const flags = pattern.flags.includes(\"g\")\n ? pattern.flags\n : `${pattern.flags}g`;\n const matcher = new RegExp(pattern.source, flags);\n let match: RegExpExecArray | null;\n\n while ((match = matcher.exec(raw)) !== null) {\n if (!isIndexInRanges(match.index, fenceRanges)) {\n return match.index;\n }\n }\n\n return -1;\n};\n\nconst findHtmlBlockEnd = (raw: string, startIndex: number) => {\n let blockEnd = raw.length;\n let match: RegExpExecArray | null;\n closingBoundary.lastIndex = 0;\n\n while ((match = closingBoundary.exec(raw))) {\n if (match.index <= startIndex) continue;\n blockEnd = match.index + match[0].length;\n break;\n }\n\n return blockEnd;\n};\n\nconst splitCustomButtonsFromSandbox = (segments: RenderSegment[]) => {\n if (!segments.length) return segments;\n const output: RenderSegment[] = [];\n\n segments.forEach((segment) => {\n if (segment.type !== \"sandbox\") {\n output.push(segment);\n return;\n }\n\n CUSTOM_BUTTON_PATTERN.lastIndex = 0;\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = CUSTOM_BUTTON_PATTERN.exec(segment.value)) !== null) {\n const before = segment.value.slice(lastIndex, match.index);\n if (before.trim()) {\n output.push({ type: \"sandbox\", value: before });\n }\n output.push({ type: \"markdown\", value: match[0] });\n lastIndex = match.index + match[0].length;\n }\n\n const rest = segment.value.slice(lastIndex);\n if (rest.trim()) {\n output.push({ type: \"sandbox\", value: rest });\n }\n });\n\n return output;\n};\n\nconst findInlineSandboxMatch = (raw: string): MatchResult | null => {\n let earliest: MatchResult | null = null;\n\n INLINE_SANDBOX_PATTERNS.forEach((pattern) => {\n const match = pattern.exec(raw);\n if (!match || typeof match.index !== \"number\") return;\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (!earliest || start < earliest.start) {\n earliest = { start, end };\n }\n });\n\n return earliest;\n};\n\nconst findMarkdownImageMatch = (\n raw: string,\n fenceRanges: FenceRange[]\n): MatchResult | null => {\n const start = findFirstMatchOutsideFence(\n raw,\n MARKDOWN_IMAGE_PATTERN,\n fenceRanges\n );\n\n if (start === -1) return null;\n const match = raw.slice(start).match(MARKDOWN_IMAGE_PATTERN);\n if (!match) return null;\n\n return { start, end: start + match[0].length };\n};\n\nconst extractTableBlock = (\n raw: string\n): { start: number; block: string; end: number } | null => {\n const tableMatch = raw.match(/^\\s*\\|.+\\|\\s*$/m);\n if (!tableMatch || typeof tableMatch.index !== \"number\") return null;\n\n const leadingSpaces = tableMatch[0].match(/^\\s*/)?.[0].length ?? 0;\n const tableStart = tableMatch.index + leadingSpaces;\n\n const lines = raw.slice(tableStart).split(\"\\n\");\n const tableLines: string[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed.startsWith(\"|\")) break;\n tableLines.push(line);\n }\n\n const block = tableLines.join(\"\\n\");\n return { start: tableStart, block, end: tableStart + block.length };\n};\n\n// Split incoming markdown content into markdown and sandbox HTML segments\nexport const splitContentSegments = (\n raw: string,\n keepText = false\n): RenderSegment[] => {\n const finalizeSegments = (segments: RenderSegment[]) =>\n splitCustomButtonsFromSandbox(segments);\n\n const fenceStart = raw.indexOf(\"```\");\n if (keepText && fenceStart !== -1) {\n const closingFence = raw.indexOf(\"```\", fenceStart + 3);\n if (closingFence === -1) {\n return finalizeSegments([{ type: \"markdown\", value: raw }]);\n }\n }\n\n const fenceRanges = getFenceRanges(raw);\n // Avoid treating fenced code blocks as sandbox content.\n const sandboxStartIndex = findFirstMatchOutsideFence(\n raw,\n SANDBOX_START_PATTERN,\n fenceRanges\n );\n const svgOpenIndex = findFirstMatchOutsideFence(raw, /<svg\\b/i, fenceRanges);\n const hasSandboxBeforeSvg =\n sandboxStartIndex !== -1 &&\n svgOpenIndex !== -1 &&\n sandboxStartIndex < svgOpenIndex;\n if (svgOpenIndex !== -1 && !hasSandboxBeforeSvg) {\n const before = raw.slice(0, svgOpenIndex);\n const closeIdx = raw.indexOf(\"</svg>\", svgOpenIndex);\n const svgBlock =\n closeIdx === -1\n ? `${raw.slice(svgOpenIndex)}</svg>`\n : raw.slice(svgOpenIndex, closeIdx + \"</svg>\".length);\n const after = closeIdx === -1 ? \"\" : raw.slice(closeIdx + \"</svg>\".length);\n\n if (keepText) {\n const segments: RenderSegment[] = [];\n if (before.trim()) {\n segments.push({ type: \"text\", value: before });\n }\n segments.push({ type: \"markdown\", value: svgBlock });\n if (after.trim()) {\n segments.push(...splitContentSegments(after, true));\n }\n return finalizeSegments(segments);\n }\n\n if (closeIdx === -1) {\n return finalizeSegments([{ type: \"markdown\", value: svgBlock }]);\n }\n }\n\n const tableBlock = extractTableBlock(raw);\n if (tableBlock) {\n const segments: RenderSegment[] = [];\n const before = raw.slice(0, tableBlock.start);\n if (keepText && before.trim()) {\n segments.push({ type: \"text\", value: before });\n }\n segments.push({ type: \"markdown\", value: tableBlock.block });\n const after = raw.slice(tableBlock.end);\n const hasProgress = after.length < raw.length;\n if (after.trim() && hasProgress) {\n segments.push(\n ...(keepText\n ? splitContentSegments(after, true)\n : splitContentSegments(after))\n );\n }\n return finalizeSegments(segments);\n }\n\n const inlineMatch = findInlineSandboxMatch(raw);\n const markdownImageMatch = findMarkdownImageMatch(raw, fenceRanges);\n const inlineCandidate =\n inlineMatch && markdownImageMatch\n ? inlineMatch.start <= markdownImageMatch.start\n ? inlineMatch\n : markdownImageMatch\n : (inlineMatch ?? markdownImageMatch);\n\n if (sandboxStartIndex === -1 && !inlineCandidate) {\n if (keepText && raw.trim()) {\n return finalizeSegments([{ type: \"text\", value: raw }]);\n }\n return [];\n }\n\n const shouldUseInline =\n !!inlineCandidate &&\n (sandboxStartIndex === -1 || inlineCandidate.start < sandboxStartIndex);\n\n const startIndex = shouldUseInline\n ? inlineCandidate!.start\n : sandboxStartIndex;\n const blockEnd = shouldUseInline\n ? inlineCandidate!.end\n : findHtmlBlockEnd(raw, startIndex);\n\n const segments: RenderSegment[] = [];\n const before = raw.slice(0, startIndex);\n const matchedBlock = raw.slice(startIndex, blockEnd);\n const after = raw.slice(blockEnd);\n\n if (keepText && before.trim()) {\n segments.push({ type: \"text\", value: before });\n }\n\n segments.push({\n type: shouldUseInline ? \"markdown\" : \"sandbox\",\n value: matchedBlock,\n });\n\n if (after.trim()) {\n segments.push(...splitContentSegments(after, keepText));\n }\n\n return finalizeSegments(segments);\n};\n"],"names":["SANDBOX_START_PATTERN","INLINE_SANDBOX_PATTERNS","MARKDOWN_IMAGE_PATTERN","closingBoundary","CUSTOM_BUTTON_PATTERN","getFenceRanges","raw","ranges","fencePattern","match","start","closeMatch","isIndexInRanges","index","end","findFirstMatchOutsideFence","pattern","fenceRanges","flags","matcher","findHtmlBlockEnd","startIndex","blockEnd","splitCustomButtonsFromSandbox","segments","output","segment","lastIndex","before","rest","findInlineSandboxMatch","earliest","findMarkdownImageMatch","extractTableBlock","tableMatch","leadingSpaces","tableStart","lines","tableLines","line","block","splitContentSegments","keepText","finalizeSegments","fenceStart","sandboxStartIndex","svgOpenIndex","hasSandboxBeforeSvg","closeIdx","svgBlock","after","tableBlock","hasProgress","inlineMatch","markdownImageMatch","inlineCandidate","shouldUseInline","matchedBlock"],"mappings":"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"}
|
|
@@ -1,64 +1,118 @@
|
|
|
1
|
-
const
|
|
1
|
+
const O = /<(script|style|link|iframe|html|head|body|meta|title|base|template|div|section|article|main)[\s>]/i, R = [
|
|
2
2
|
/<svg[\s\S]*?<\/svg>/i,
|
|
3
3
|
/<img\b[^>]*?>/i,
|
|
4
4
|
/```mermaid[\s\S]*?```/i,
|
|
5
5
|
/```[a-zA-Z0-9]+[\s\S]*?```/i
|
|
6
|
-
],
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
], B = /!\[[^\]]*]\([^\s)\n]+(?:\s+"[^"]*")?\)/i, M = /<\/[a-z][^>]*>\s*\n(?=[^\s<])/gi, A = /<custom-button-after-content\b[\s\S]*?<\/custom-button-after-content>/gi, T = (t) => {
|
|
7
|
+
const n = [], e = /```/g;
|
|
8
|
+
let s;
|
|
9
|
+
for (; (s = e.exec(t)) !== null; ) {
|
|
10
|
+
const o = s.index, c = e.exec(t);
|
|
11
|
+
if (!c) {
|
|
12
|
+
n.push({ start: o, end: t.length });
|
|
11
13
|
break;
|
|
12
14
|
}
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
+
n.push({ start: o, end: c.index + 3 });
|
|
16
|
+
}
|
|
17
|
+
return n;
|
|
18
|
+
}, _ = (t, n) => n.some(({ start: e, end: s }) => t >= e && t < s), y = (t, n, e) => {
|
|
19
|
+
const s = n.flags.includes("g") ? n.flags : `${n.flags}g`, o = new RegExp(n.source, s);
|
|
20
|
+
let c;
|
|
21
|
+
for (; (c = o.exec(t)) !== null; )
|
|
22
|
+
if (!_(c.index, e))
|
|
23
|
+
return c.index;
|
|
24
|
+
return -1;
|
|
25
|
+
}, F = (t, n) => {
|
|
26
|
+
let e = t.length, s;
|
|
27
|
+
for (M.lastIndex = 0; s = M.exec(t); )
|
|
28
|
+
if (!(s.index <= n)) {
|
|
29
|
+
e = s.index + s[0].length;
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
return e;
|
|
33
|
+
}, P = (t) => {
|
|
34
|
+
if (!t.length) return t;
|
|
35
|
+
const n = [];
|
|
36
|
+
return t.forEach((e) => {
|
|
37
|
+
if (e.type !== "sandbox") {
|
|
38
|
+
n.push(e);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
A.lastIndex = 0;
|
|
42
|
+
let s = 0, o;
|
|
43
|
+
for (; (o = A.exec(e.value)) !== null; ) {
|
|
44
|
+
const i = e.value.slice(s, o.index);
|
|
45
|
+
i.trim() && n.push({ type: "sandbox", value: i }), n.push({ type: "markdown", value: o[0] }), s = o.index + o[0].length;
|
|
46
|
+
}
|
|
47
|
+
const c = e.value.slice(s);
|
|
48
|
+
c.trim() && n.push({ type: "sandbox", value: c });
|
|
49
|
+
}), n;
|
|
50
|
+
}, C = (t) => {
|
|
15
51
|
let n = null;
|
|
16
|
-
return
|
|
17
|
-
const
|
|
18
|
-
if (!
|
|
19
|
-
const
|
|
20
|
-
(!n ||
|
|
52
|
+
return R.forEach((e) => {
|
|
53
|
+
const s = e.exec(t);
|
|
54
|
+
if (!s || typeof s.index != "number") return;
|
|
55
|
+
const o = s.index, c = s.index + s[0].length;
|
|
56
|
+
(!n || o < n.start) && (n = { start: o, end: c });
|
|
21
57
|
}), n;
|
|
22
|
-
},
|
|
58
|
+
}, z = (t, n) => {
|
|
59
|
+
const e = y(
|
|
60
|
+
t,
|
|
61
|
+
B,
|
|
62
|
+
n
|
|
63
|
+
);
|
|
64
|
+
if (e === -1) return null;
|
|
65
|
+
const s = t.slice(e).match(B);
|
|
66
|
+
return s ? { start: e, end: e + s[0].length } : null;
|
|
67
|
+
}, D = (t) => {
|
|
23
68
|
const n = t.match(/^\s*\|.+\|\s*$/m);
|
|
24
69
|
if (!n || typeof n.index != "number") return null;
|
|
25
|
-
const
|
|
26
|
-
`),
|
|
27
|
-
for (const
|
|
28
|
-
if (!
|
|
29
|
-
|
|
70
|
+
const e = n[0].match(/^\s*/)?.[0].length ?? 0, s = n.index + e, o = t.slice(s).split(`
|
|
71
|
+
`), c = [];
|
|
72
|
+
for (const f of o) {
|
|
73
|
+
if (!f.trim().startsWith("|")) break;
|
|
74
|
+
c.push(f);
|
|
30
75
|
}
|
|
31
|
-
const
|
|
76
|
+
const i = c.join(`
|
|
32
77
|
`);
|
|
33
|
-
return { start:
|
|
34
|
-
},
|
|
35
|
-
const s = t.indexOf("```");
|
|
78
|
+
return { start: s, block: i, end: s + i.length };
|
|
79
|
+
}, p = (t, n = !1) => {
|
|
80
|
+
const e = (l) => P(l), s = t.indexOf("```");
|
|
36
81
|
if (n && s !== -1 && t.indexOf("```", s + 3) === -1)
|
|
37
|
-
return [{ type: "markdown", value: t }];
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
82
|
+
return e([{ type: "markdown", value: t }]);
|
|
83
|
+
const o = T(t), c = y(
|
|
84
|
+
t,
|
|
85
|
+
O,
|
|
86
|
+
o
|
|
87
|
+
), i = y(t, /<svg\b/i, o), f = c !== -1 && i !== -1 && c < i;
|
|
88
|
+
if (i !== -1 && !f) {
|
|
89
|
+
const l = t.slice(0, i), a = t.indexOf("</svg>", i), r = a === -1 ? `${t.slice(i)}</svg>` : t.slice(i, a + 6), x = a === -1 ? "" : t.slice(a + 6);
|
|
90
|
+
if (n) {
|
|
91
|
+
const b = [];
|
|
92
|
+
return l.trim() && b.push({ type: "text", value: l }), b.push({ type: "markdown", value: r }), x.trim() && b.push(...p(x, !0)), e(b);
|
|
93
|
+
}
|
|
94
|
+
if (a === -1)
|
|
95
|
+
return e([{ type: "markdown", value: r }]);
|
|
96
|
+
}
|
|
97
|
+
const u = D(t);
|
|
98
|
+
if (u) {
|
|
99
|
+
const l = [], a = t.slice(0, u.start);
|
|
100
|
+
n && a.trim() && l.push({ type: "text", value: a }), l.push({ type: "markdown", value: u.block });
|
|
101
|
+
const r = t.slice(u.end), x = r.length < t.length;
|
|
102
|
+
return r.trim() && x && l.push(
|
|
103
|
+
...n ? p(r, !0) : p(r)
|
|
104
|
+
), e(l);
|
|
49
105
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
value: x
|
|
59
|
-
}), b.trim() && d.push(...u(b, n)), d;
|
|
106
|
+
const h = C(t), m = z(t, o), d = h && m ? h.start <= m.start ? h : m : h ?? m;
|
|
107
|
+
if (c === -1 && !d)
|
|
108
|
+
return n && t.trim() ? e([{ type: "text", value: t }]) : [];
|
|
109
|
+
const v = !!d && (c === -1 || d.start < c), S = v ? d.start : c, I = v ? d.end : F(t, S), g = [], k = t.slice(0, S), N = t.slice(S, I), E = t.slice(I);
|
|
110
|
+
return n && k.trim() && g.push({ type: "text", value: k }), g.push({
|
|
111
|
+
type: v ? "markdown" : "sandbox",
|
|
112
|
+
value: N
|
|
113
|
+
}), E.trim() && g.push(...p(E, n)), e(g);
|
|
60
114
|
};
|
|
61
115
|
export {
|
|
62
|
-
|
|
116
|
+
p as splitContentSegments
|
|
63
117
|
};
|
|
64
118
|
//# sourceMappingURL=split-content.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"split-content.es.js","sources":["../../../../src/components/ContentRender/utils/split-content.ts"],"sourcesContent":["export type RenderSegment =\n | { type: \"markdown\"; value: string }\n | { type: \"sandbox\"; value: string }\n | { type: \"text\"; value: string };\n\nconst SANDBOX_START_PATTERN =\n /<(script|style|link|iframe|html|head|body|meta|title|base|template|div|section|article|main)[\\s>]/i;\n\nconst INLINE_SANDBOX_PATTERNS: RegExp[] = [\n /<svg[\\s\\S]*?<\\/svg>/i,\n /<img\\b[^>]*?>/i,\n /```mermaid[\\s\\S]*?```/i,\n /```[a-zA-Z0-9]+[\\s\\S]*?```/i,\n];\n\nconst closingBoundary = /<\\/[a-z][^>]*>\\s*\\n(?=[^\\s<])/gi;\n\ntype MatchResult = { start: number; end: number };\n\nconst findHtmlBlockEnd = (raw: string, startIndex: number) => {\n let blockEnd = raw.length;\n let match: RegExpExecArray | null;\n closingBoundary.lastIndex = 0;\n\n while ((match = closingBoundary.exec(raw))) {\n if (match.index <= startIndex) continue;\n blockEnd = match.index + match[0].length;\n break;\n }\n\n return blockEnd;\n};\n\nconst findInlineSandboxMatch = (raw: string): MatchResult | null => {\n let earliest: MatchResult | null = null;\n\n INLINE_SANDBOX_PATTERNS.forEach((pattern) => {\n const match = pattern.exec(raw);\n if (!match || typeof match.index !== \"number\") return;\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (!earliest || start < earliest.start) {\n earliest = { start, end };\n }\n });\n\n return earliest;\n};\n\nconst extractTableBlock = (\n raw: string\n): { start: number; block: string; end: number } | null => {\n const tableMatch = raw.match(/^\\s*\\|.+\\|\\s*$/m);\n if (!tableMatch || typeof tableMatch.index !== \"number\") return null;\n\n const leadingSpaces = tableMatch[0].match(/^\\s*/)?.[0].length ?? 0;\n const tableStart = tableMatch.index + leadingSpaces;\n\n const lines = raw.slice(tableStart).split(\"\\n\");\n const tableLines: string[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed.startsWith(\"|\")) break;\n tableLines.push(line);\n }\n\n const block = tableLines.join(\"\\n\");\n return { start: tableStart, block, end: tableStart + block.length };\n};\n\n// Split incoming markdown content into markdown and sandbox HTML segments\nexport const splitContentSegments = (\n raw: string,\n keepText = false\n): RenderSegment[] => {\n const fenceStart = raw.indexOf(\"```\");\n if (keepText && fenceStart !== -1) {\n const closingFence = raw.indexOf(\"```\", fenceStart + 3);\n if (closingFence === -1) {\n return [{ type: \"markdown\", value: raw }];\n }\n }\n\n const svgOpenIndex = raw.search(/<svg\\b/i);\n if (svgOpenIndex !== -1 && raw.indexOf(\"</svg>\", svgOpenIndex) === -1) {\n return [{ type: \"markdown\", value: raw }];\n }\n\n const tableBlock = extractTableBlock(raw);\n if (tableBlock) {\n const segments: RenderSegment[] = [];\n const before = raw.slice(0, tableBlock.start);\n if (keepText && before.trim()) {\n segments.push({ type: \"text\", value: before });\n }\n segments.push({ type: \"markdown\", value: tableBlock.block });\n const after = raw.slice(tableBlock.end);\n const hasProgress = after.length < raw.length;\n if (after.trim() && hasProgress) {\n segments.push(\n ...(keepText\n ? splitContentSegments(after, true)\n : splitContentSegments(after))\n );\n }\n return segments;\n }\n\n const completeSvgMatch = raw.match(/<svg[\\s\\S]*?<\\/svg>/i);\n if (completeSvgMatch && keepText) {\n const hasLeadingContent =\n svgOpenIndex > -1 && raw.slice(0, svgOpenIndex).trim().length > 0;\n if (!hasLeadingContent) {\n if (!raw.trim().toLowerCase().endsWith(\"</svg>\")) {\n return [{ type: \"markdown\", value: `${raw}</svg>` }];\n }\n return [{ type: \"markdown\", value: raw }];\n }\n }\n\n const sandboxStartIndex = raw.search(SANDBOX_START_PATTERN);\n const inlineMatch = findInlineSandboxMatch(raw);\n\n if (sandboxStartIndex === -1 && !inlineMatch) {\n if (keepText && raw.trim()) {\n return [{ type: \"text\", value: raw }];\n }\n return [];\n }\n\n const shouldUseInline =\n !!inlineMatch &&\n (sandboxStartIndex === -1 || inlineMatch.start < sandboxStartIndex);\n\n const startIndex = shouldUseInline ? inlineMatch!.start : sandboxStartIndex;\n const blockEnd = shouldUseInline\n ? inlineMatch!.end\n : findHtmlBlockEnd(raw, startIndex);\n\n const segments: RenderSegment[] = [];\n const before = raw.slice(0, startIndex);\n const matchedBlock = raw.slice(startIndex, blockEnd);\n const after = raw.slice(blockEnd);\n\n if (keepText && before.trim()) {\n segments.push({ type: \"text\", value: before });\n }\n\n segments.push({\n type: shouldUseInline ? \"markdown\" : \"sandbox\",\n value: matchedBlock,\n });\n\n if (after.trim()) {\n segments.push(...splitContentSegments(after, keepText));\n }\n\n return segments;\n};\n"],"names":["SANDBOX_START_PATTERN","INLINE_SANDBOX_PATTERNS","closingBoundary","findHtmlBlockEnd","raw","startIndex","blockEnd","match","findInlineSandboxMatch","earliest","pattern","start","end","extractTableBlock","tableMatch","leadingSpaces","tableStart","lines","tableLines","line","block","splitContentSegments","keepText","fenceStart","svgOpenIndex","tableBlock","segments","before","after","hasProgress","sandboxStartIndex","inlineMatch","shouldUseInline","matchedBlock"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"split-content.es.js","sources":["../../../../src/components/ContentRender/utils/split-content.ts"],"sourcesContent":["export type RenderSegment =\n | { type: \"markdown\"; value: string }\n | { type: \"sandbox\"; value: string }\n | { type: \"text\"; value: string };\n\nconst SANDBOX_START_PATTERN =\n /<(script|style|link|iframe|html|head|body|meta|title|base|template|div|section|article|main)[\\s>]/i;\n\nconst INLINE_SANDBOX_PATTERNS: RegExp[] = [\n /<svg[\\s\\S]*?<\\/svg>/i,\n /<img\\b[^>]*?>/i,\n /```mermaid[\\s\\S]*?```/i,\n /```[a-zA-Z0-9]+[\\s\\S]*?```/i,\n];\nconst MARKDOWN_IMAGE_PATTERN = /!\\[[^\\]]*]\\([^\\s)\\n]+(?:\\s+\"[^\"]*\")?\\)/i;\n\nconst closingBoundary = /<\\/[a-z][^>]*>\\s*\\n(?=[^\\s<])/gi;\nconst CUSTOM_BUTTON_PATTERN =\n /<custom-button-after-content\\b[\\s\\S]*?<\\/custom-button-after-content>/gi;\n\ntype MatchResult = { start: number; end: number };\ntype FenceRange = { start: number; end: number };\n\nconst getFenceRanges = (raw: string): FenceRange[] => {\n const ranges: FenceRange[] = [];\n const fencePattern = /```/g;\n let match: RegExpExecArray | null;\n\n while ((match = fencePattern.exec(raw)) !== null) {\n const start = match.index;\n const closeMatch = fencePattern.exec(raw);\n if (!closeMatch) {\n ranges.push({ start, end: raw.length });\n break;\n }\n ranges.push({ start, end: closeMatch.index + 3 });\n }\n\n return ranges;\n};\n\nconst isIndexInRanges = (index: number, ranges: FenceRange[]) =>\n ranges.some(({ start, end }) => index >= start && index < end);\n\nconst findFirstMatchOutsideFence = (\n raw: string,\n pattern: RegExp,\n fenceRanges: FenceRange[]\n) => {\n const flags = pattern.flags.includes(\"g\")\n ? pattern.flags\n : `${pattern.flags}g`;\n const matcher = new RegExp(pattern.source, flags);\n let match: RegExpExecArray | null;\n\n while ((match = matcher.exec(raw)) !== null) {\n if (!isIndexInRanges(match.index, fenceRanges)) {\n return match.index;\n }\n }\n\n return -1;\n};\n\nconst findHtmlBlockEnd = (raw: string, startIndex: number) => {\n let blockEnd = raw.length;\n let match: RegExpExecArray | null;\n closingBoundary.lastIndex = 0;\n\n while ((match = closingBoundary.exec(raw))) {\n if (match.index <= startIndex) continue;\n blockEnd = match.index + match[0].length;\n break;\n }\n\n return blockEnd;\n};\n\nconst splitCustomButtonsFromSandbox = (segments: RenderSegment[]) => {\n if (!segments.length) return segments;\n const output: RenderSegment[] = [];\n\n segments.forEach((segment) => {\n if (segment.type !== \"sandbox\") {\n output.push(segment);\n return;\n }\n\n CUSTOM_BUTTON_PATTERN.lastIndex = 0;\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = CUSTOM_BUTTON_PATTERN.exec(segment.value)) !== null) {\n const before = segment.value.slice(lastIndex, match.index);\n if (before.trim()) {\n output.push({ type: \"sandbox\", value: before });\n }\n output.push({ type: \"markdown\", value: match[0] });\n lastIndex = match.index + match[0].length;\n }\n\n const rest = segment.value.slice(lastIndex);\n if (rest.trim()) {\n output.push({ type: \"sandbox\", value: rest });\n }\n });\n\n return output;\n};\n\nconst findInlineSandboxMatch = (raw: string): MatchResult | null => {\n let earliest: MatchResult | null = null;\n\n INLINE_SANDBOX_PATTERNS.forEach((pattern) => {\n const match = pattern.exec(raw);\n if (!match || typeof match.index !== \"number\") return;\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (!earliest || start < earliest.start) {\n earliest = { start, end };\n }\n });\n\n return earliest;\n};\n\nconst findMarkdownImageMatch = (\n raw: string,\n fenceRanges: FenceRange[]\n): MatchResult | null => {\n const start = findFirstMatchOutsideFence(\n raw,\n MARKDOWN_IMAGE_PATTERN,\n fenceRanges\n );\n\n if (start === -1) return null;\n const match = raw.slice(start).match(MARKDOWN_IMAGE_PATTERN);\n if (!match) return null;\n\n return { start, end: start + match[0].length };\n};\n\nconst extractTableBlock = (\n raw: string\n): { start: number; block: string; end: number } | null => {\n const tableMatch = raw.match(/^\\s*\\|.+\\|\\s*$/m);\n if (!tableMatch || typeof tableMatch.index !== \"number\") return null;\n\n const leadingSpaces = tableMatch[0].match(/^\\s*/)?.[0].length ?? 0;\n const tableStart = tableMatch.index + leadingSpaces;\n\n const lines = raw.slice(tableStart).split(\"\\n\");\n const tableLines: string[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed.startsWith(\"|\")) break;\n tableLines.push(line);\n }\n\n const block = tableLines.join(\"\\n\");\n return { start: tableStart, block, end: tableStart + block.length };\n};\n\n// Split incoming markdown content into markdown and sandbox HTML segments\nexport const splitContentSegments = (\n raw: string,\n keepText = false\n): RenderSegment[] => {\n const finalizeSegments = (segments: RenderSegment[]) =>\n splitCustomButtonsFromSandbox(segments);\n\n const fenceStart = raw.indexOf(\"```\");\n if (keepText && fenceStart !== -1) {\n const closingFence = raw.indexOf(\"```\", fenceStart + 3);\n if (closingFence === -1) {\n return finalizeSegments([{ type: \"markdown\", value: raw }]);\n }\n }\n\n const fenceRanges = getFenceRanges(raw);\n // Avoid treating fenced code blocks as sandbox content.\n const sandboxStartIndex = findFirstMatchOutsideFence(\n raw,\n SANDBOX_START_PATTERN,\n fenceRanges\n );\n const svgOpenIndex = findFirstMatchOutsideFence(raw, /<svg\\b/i, fenceRanges);\n const hasSandboxBeforeSvg =\n sandboxStartIndex !== -1 &&\n svgOpenIndex !== -1 &&\n sandboxStartIndex < svgOpenIndex;\n if (svgOpenIndex !== -1 && !hasSandboxBeforeSvg) {\n const before = raw.slice(0, svgOpenIndex);\n const closeIdx = raw.indexOf(\"</svg>\", svgOpenIndex);\n const svgBlock =\n closeIdx === -1\n ? `${raw.slice(svgOpenIndex)}</svg>`\n : raw.slice(svgOpenIndex, closeIdx + \"</svg>\".length);\n const after = closeIdx === -1 ? \"\" : raw.slice(closeIdx + \"</svg>\".length);\n\n if (keepText) {\n const segments: RenderSegment[] = [];\n if (before.trim()) {\n segments.push({ type: \"text\", value: before });\n }\n segments.push({ type: \"markdown\", value: svgBlock });\n if (after.trim()) {\n segments.push(...splitContentSegments(after, true));\n }\n return finalizeSegments(segments);\n }\n\n if (closeIdx === -1) {\n return finalizeSegments([{ type: \"markdown\", value: svgBlock }]);\n }\n }\n\n const tableBlock = extractTableBlock(raw);\n if (tableBlock) {\n const segments: RenderSegment[] = [];\n const before = raw.slice(0, tableBlock.start);\n if (keepText && before.trim()) {\n segments.push({ type: \"text\", value: before });\n }\n segments.push({ type: \"markdown\", value: tableBlock.block });\n const after = raw.slice(tableBlock.end);\n const hasProgress = after.length < raw.length;\n if (after.trim() && hasProgress) {\n segments.push(\n ...(keepText\n ? splitContentSegments(after, true)\n : splitContentSegments(after))\n );\n }\n return finalizeSegments(segments);\n }\n\n const inlineMatch = findInlineSandboxMatch(raw);\n const markdownImageMatch = findMarkdownImageMatch(raw, fenceRanges);\n const inlineCandidate =\n inlineMatch && markdownImageMatch\n ? inlineMatch.start <= markdownImageMatch.start\n ? inlineMatch\n : markdownImageMatch\n : (inlineMatch ?? markdownImageMatch);\n\n if (sandboxStartIndex === -1 && !inlineCandidate) {\n if (keepText && raw.trim()) {\n return finalizeSegments([{ type: \"text\", value: raw }]);\n }\n return [];\n }\n\n const shouldUseInline =\n !!inlineCandidate &&\n (sandboxStartIndex === -1 || inlineCandidate.start < sandboxStartIndex);\n\n const startIndex = shouldUseInline\n ? inlineCandidate!.start\n : sandboxStartIndex;\n const blockEnd = shouldUseInline\n ? inlineCandidate!.end\n : findHtmlBlockEnd(raw, startIndex);\n\n const segments: RenderSegment[] = [];\n const before = raw.slice(0, startIndex);\n const matchedBlock = raw.slice(startIndex, blockEnd);\n const after = raw.slice(blockEnd);\n\n if (keepText && before.trim()) {\n segments.push({ type: \"text\", value: before });\n }\n\n segments.push({\n type: shouldUseInline ? \"markdown\" : \"sandbox\",\n value: matchedBlock,\n });\n\n if (after.trim()) {\n segments.push(...splitContentSegments(after, keepText));\n }\n\n return finalizeSegments(segments);\n};\n"],"names":["SANDBOX_START_PATTERN","INLINE_SANDBOX_PATTERNS","MARKDOWN_IMAGE_PATTERN","closingBoundary","CUSTOM_BUTTON_PATTERN","getFenceRanges","raw","ranges","fencePattern","match","start","closeMatch","isIndexInRanges","index","end","findFirstMatchOutsideFence","pattern","fenceRanges","flags","matcher","findHtmlBlockEnd","startIndex","blockEnd","splitCustomButtonsFromSandbox","segments","output","segment","lastIndex","before","rest","findInlineSandboxMatch","earliest","findMarkdownImageMatch","extractTableBlock","tableMatch","leadingSpaces","tableStart","lines","tableLines","line","block","splitContentSegments","keepText","finalizeSegments","fenceStart","sandboxStartIndex","svgOpenIndex","hasSandboxBeforeSvg","closeIdx","svgBlock","after","tableBlock","hasProgress","inlineMatch","markdownImageMatch","inlineCandidate","shouldUseInline","matchedBlock"],"mappings":"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"}
|