@antdv-next/x-markdown 0.0.1 → 0.0.2

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 (36) hide show
  1. package/dist/XMarkdown/components/AnimationText.vue.d.ts +0 -1
  2. package/dist/XMarkdown/components/DebugPanel.vue.d.ts +0 -1
  3. package/dist/XMarkdown/components/TailIndicator.vue.d.ts +0 -1
  4. package/dist/XMarkdown/components/index.d.ts +0 -1
  5. package/dist/XMarkdown/composables/useParser.d.ts +0 -1
  6. package/dist/XMarkdown/composables/useRenderer.d.ts +0 -1
  7. package/dist/XMarkdown/composables/useStreaming.d.ts +0 -1
  8. package/dist/XMarkdown/composables/useTail.d.ts +0 -1
  9. package/dist/XMarkdown/core/Parser.d.ts +5 -2
  10. package/dist/XMarkdown/core/VueRenderer.d.ts +0 -1
  11. package/dist/XMarkdown/core/detectUnclosedComponentTags.d.ts +2 -2
  12. package/dist/XMarkdown/index.vue.d.ts +0 -1
  13. package/dist/XMarkdown/interface.d.ts +0 -1
  14. package/dist/XMarkdown/utils/tail.d.ts +0 -1
  15. package/dist/index.css +251 -1
  16. package/dist/index.d.ts +0 -1
  17. package/dist/index.js +868 -470
  18. package/dist/plugins/Latex/index.d.ts +0 -1
  19. package/dist/plugins/Latex/index.js +48 -42
  20. package/package.json +3 -2
  21. package/dist/XMarkdown/components/AnimationText.vue.d.ts.map +0 -1
  22. package/dist/XMarkdown/components/DebugPanel.vue.d.ts.map +0 -1
  23. package/dist/XMarkdown/components/TailIndicator.vue.d.ts.map +0 -1
  24. package/dist/XMarkdown/components/index.d.ts.map +0 -1
  25. package/dist/XMarkdown/composables/useParser.d.ts.map +0 -1
  26. package/dist/XMarkdown/composables/useRenderer.d.ts.map +0 -1
  27. package/dist/XMarkdown/composables/useStreaming.d.ts.map +0 -1
  28. package/dist/XMarkdown/composables/useTail.d.ts.map +0 -1
  29. package/dist/XMarkdown/core/Parser.d.ts.map +0 -1
  30. package/dist/XMarkdown/core/VueRenderer.d.ts.map +0 -1
  31. package/dist/XMarkdown/core/detectUnclosedComponentTags.d.ts.map +0 -1
  32. package/dist/XMarkdown/index.vue.d.ts.map +0 -1
  33. package/dist/XMarkdown/interface.d.ts.map +0 -1
  34. package/dist/XMarkdown/utils/tail.d.ts.map +0 -1
  35. package/dist/index.d.ts.map +0 -1
  36. package/dist/plugins/Latex/index.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -1,424 +1,609 @@
1
- import { Fragment as e, computed as t, createBlock as n, createCommentVNode as r, createElementBlock as i, createElementVNode as a, createTextVNode as o, createVNode as s, defineComponent as c, h as l, normalizeClass as u, normalizeStyle as d, onMounted as f, onUnmounted as p, openBlock as m, ref as h, renderList as g, shallowRef as _, toDisplayString as v, unref as y, watch as b } from "vue";
2
- import x from "dompurify";
3
- import { Marked as S } from "marked";
1
+ import "./index.css";
2
+ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, h, normalizeClass, normalizeStyle, onMounted, onUnmounted, openBlock, ref, renderList, shallowRef, toDisplayString, unref, watch } from "vue";
3
+ import { Marked } from "marked";
4
+ import DOMPurify from "dompurify";
4
5
  //#region src/XMarkdown/components/DebugPanel.vue?vue&type=script&setup=true&lang.ts
5
- var C = { class: "xmd-debug-content" }, w = { class: "xmd-debug-stat" }, T = { class: "xmd-debug-stat" }, E = {
6
+ var _hoisted_1$1 = { class: "xmd-debug-content" };
7
+ var _hoisted_2 = { class: "xmd-debug-stat" };
8
+ var _hoisted_3 = { class: "xmd-debug-stat" };
9
+ var _hoisted_4 = {
6
10
  class: "xmd-debug-chart",
7
11
  viewBox: "0 0 200 60"
8
- }, D = ["d"], O = 60, k = /* @__PURE__ */ c({
12
+ };
13
+ var _hoisted_5 = ["d"];
14
+ var maxSnapshots = 60;
15
+ var DebugPanel_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
9
16
  __name: "DebugPanel",
10
17
  props: { className: {} },
11
- setup(e) {
12
- let t = h(!1), n = h({
18
+ setup(__props) {
19
+ const isDragging = ref(false);
20
+ const position = ref({
13
21
  x: 20,
14
22
  y: 20
15
- }), r = h({
23
+ });
24
+ const dragOffset = ref({
16
25
  x: 0,
17
26
  y: 0
18
- }), o = h(0), s = h(0), c = h([]), l = null, g = 0, _ = 0;
19
- function y() {
20
- g = performance.now(), _ = 0;
21
- function e() {
22
- _++;
23
- let t = performance.now(), n = t - g;
24
- if (n >= 1e3) {
25
- if (o.value = Math.round(_ * 1e3 / n), _ = 0, g = t, "memory" in performance) {
26
- let e = performance.memory;
27
- s.value = e ? Math.round(e.usedJSHeapSize / 1024 / 1024) : 0;
27
+ });
28
+ const fps = ref(0);
29
+ const memory = ref(0);
30
+ const snapshots = ref([]);
31
+ let animationFrameId = null;
32
+ let lastFrameTime = 0;
33
+ let frameCount = 0;
34
+ function startMonitoring() {
35
+ lastFrameTime = performance.now();
36
+ frameCount = 0;
37
+ function monitor() {
38
+ frameCount++;
39
+ const now = performance.now();
40
+ const elapsed = now - lastFrameTime;
41
+ if (elapsed >= 1e3) {
42
+ fps.value = Math.round(frameCount * 1e3 / elapsed);
43
+ frameCount = 0;
44
+ lastFrameTime = now;
45
+ if ("memory" in performance) {
46
+ const memInfo = performance.memory;
47
+ memory.value = memInfo ? Math.round(memInfo.usedJSHeapSize / 1024 / 1024) : 0;
28
48
  }
29
- c.value.push({
30
- fps: o.value,
31
- memory: s.value,
49
+ snapshots.value.push({
50
+ fps: fps.value,
51
+ memory: memory.value,
32
52
  timestamp: Date.now()
33
- }), c.value.length > O && c.value.shift();
53
+ });
54
+ if (snapshots.value.length > maxSnapshots) snapshots.value.shift();
34
55
  }
35
- l = requestAnimationFrame(e);
56
+ animationFrameId = requestAnimationFrame(monitor);
36
57
  }
37
- l = requestAnimationFrame(e);
58
+ animationFrameId = requestAnimationFrame(monitor);
38
59
  }
39
- function b() {
40
- l !== null && (cancelAnimationFrame(l), l = null);
60
+ function stopMonitoring() {
61
+ if (animationFrameId !== null) {
62
+ cancelAnimationFrame(animationFrameId);
63
+ animationFrameId = null;
64
+ }
41
65
  }
42
- function x(e) {
43
- t.value = !0, r.value = {
44
- x: e.clientX - n.value.x,
45
- y: e.clientY - n.value.y
66
+ function handleMouseDown(e) {
67
+ isDragging.value = true;
68
+ dragOffset.value = {
69
+ x: e.clientX - position.value.x,
70
+ y: e.clientY - position.value.y
46
71
  };
47
72
  }
48
- function S(e) {
49
- t.value && (n.value = {
50
- x: e.clientX - r.value.x,
51
- y: e.clientY - r.value.y
52
- });
73
+ function handleMouseMove(e) {
74
+ if (!isDragging.value) return;
75
+ position.value = {
76
+ x: e.clientX - dragOffset.value.x,
77
+ y: e.clientY - dragOffset.value.y
78
+ };
53
79
  }
54
- function k() {
55
- t.value = !1;
80
+ function handleMouseUp() {
81
+ isDragging.value = false;
56
82
  }
57
- function A(e) {
58
- return e >= 55 ? "#52c41a" : e >= 40 ? "#faad14" : "#ff4d4f";
83
+ function getFpsColor(fpsValue) {
84
+ if (fpsValue >= 55) return "#52c41a";
85
+ if (fpsValue >= 40) return "#faad14";
86
+ return "#ff4d4f";
59
87
  }
60
- function j() {
61
- return c.value.length < 2 ? "" : `M ${c.value.map((e, t) => `${t / (O - 1) * 200},${60 - e.fps / 60 * 60}`).join(" L ")}`;
88
+ function getChartPath() {
89
+ if (snapshots.value.length < 2) return "";
90
+ const width = 200;
91
+ const height = 60;
92
+ const maxFps = 60;
93
+ return `M ${snapshots.value.map((s, i) => {
94
+ return `${i / (maxSnapshots - 1) * width},${height - s.fps / maxFps * height}`;
95
+ }).join(" L ")}`;
62
96
  }
63
- return f(() => {
64
- y(), document.addEventListener("mousemove", S), document.addEventListener("mouseup", k);
65
- }), p(() => {
66
- b(), document.removeEventListener("mousemove", S), document.removeEventListener("mouseup", k);
67
- }), (t, r) => (m(), i("div", {
68
- class: u(["xmd-debug-panel", e.className]),
69
- style: d({
70
- left: `${n.value.x}px`,
71
- top: `${n.value.y}px`
72
- })
73
- }, [a("div", {
74
- class: "xmd-debug-header",
75
- onMousedown: x
76
- }, [...r[0] ||= [a("span", null, "Debug Panel", -1)]], 32), a("div", C, [
77
- a("div", w, [r[1] ||= a("span", { class: "xmd-debug-label" }, "FPS:", -1), a("span", { style: d({ color: A(o.value) }) }, v(o.value), 5)]),
78
- a("div", T, [r[2] ||= a("span", { class: "xmd-debug-label" }, "Memory:", -1), a("span", null, v(s.value) + " MB", 1)]),
79
- (m(), i("svg", E, [a("path", {
80
- d: j(),
81
- fill: "none",
82
- stroke: "#1890ff",
83
- "stroke-width": "2"
84
- }, null, 8, D)]))
85
- ])], 6));
86
- }
87
- }), A = (e, t) => {
88
- let n = e.__vccOpts || e;
89
- for (let [e, r] of t) n[e] = r;
90
- return n;
91
- }, j = /* @__PURE__ */ A(k, [["__scopeId", "data-v-d6923a13"]]), ee = { class: "xmd-tail" }, M = /* @__PURE__ */ A(/* @__PURE__ */ c({
97
+ onMounted(() => {
98
+ startMonitoring();
99
+ document.addEventListener("mousemove", handleMouseMove);
100
+ document.addEventListener("mouseup", handleMouseUp);
101
+ });
102
+ onUnmounted(() => {
103
+ stopMonitoring();
104
+ document.removeEventListener("mousemove", handleMouseMove);
105
+ document.removeEventListener("mouseup", handleMouseUp);
106
+ });
107
+ return (_ctx, _cache) => {
108
+ return openBlock(), createElementBlock("div", {
109
+ class: normalizeClass(["xmd-debug-panel", __props.className]),
110
+ style: normalizeStyle({
111
+ left: `${position.value.x}px`,
112
+ top: `${position.value.y}px`
113
+ })
114
+ }, [createElementVNode("div", {
115
+ class: "xmd-debug-header",
116
+ onMousedown: handleMouseDown
117
+ }, [..._cache[0] || (_cache[0] = [createElementVNode("span", null, "Debug Panel", -1)])], 32), createElementVNode("div", _hoisted_1$1, [
118
+ createElementVNode("div", _hoisted_2, [_cache[1] || (_cache[1] = createElementVNode("span", { class: "xmd-debug-label" }, "FPS:", -1)), createElementVNode("span", { style: normalizeStyle({ color: getFpsColor(fps.value) }) }, toDisplayString(fps.value), 5)]),
119
+ createElementVNode("div", _hoisted_3, [_cache[2] || (_cache[2] = createElementVNode("span", { class: "xmd-debug-label" }, "Memory:", -1)), createElementVNode("span", null, toDisplayString(memory.value) + " MB", 1)]),
120
+ (openBlock(), createElementBlock("svg", _hoisted_4, [createElementVNode("path", {
121
+ d: getChartPath(),
122
+ fill: "none",
123
+ stroke: "#1890ff",
124
+ "stroke-width": "2"
125
+ }, null, 8, _hoisted_5)]))
126
+ ])], 6);
127
+ };
128
+ }
129
+ });
130
+ //#endregion
131
+ //#region \0plugin-vue:export-helper
132
+ var _plugin_vue_export_helper_default = (sfc, props) => {
133
+ const target = sfc.__vccOpts || sfc;
134
+ for (const [key, val] of props) target[key] = val;
135
+ return target;
136
+ };
137
+ //#endregion
138
+ //#region src/XMarkdown/components/DebugPanel.vue
139
+ var DebugPanel_default = /* @__PURE__ */ _plugin_vue_export_helper_default(DebugPanel_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-d6923a13"]]);
140
+ //#endregion
141
+ //#region src/XMarkdown/components/TailIndicator.vue?vue&type=script&setup=true&lang.ts
142
+ var _hoisted_1 = { class: "xmd-tail" };
143
+ //#endregion
144
+ //#region src/XMarkdown/components/TailIndicator.vue
145
+ var TailIndicator_default = /* @__PURE__ */ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
92
146
  __name: "TailIndicator",
93
147
  props: { content: { default: "▋" } },
94
- setup(e) {
95
- return (t, n) => (m(), i("span", ee, v(e.content), 1));
148
+ setup(__props) {
149
+ return (_ctx, _cache) => {
150
+ return openBlock(), createElementBlock("span", _hoisted_1, toDisplayString(__props.content), 1);
151
+ };
96
152
  }
97
- }), [["__scopeId", "data-v-802ace82"]]), N = /* @__PURE__ */ function(e) {
98
- return e.Text = "text", e.Link = "link", e.Image = "image", e.Html = "html", e.Emphasis = "emphasis", e.List = "list", e.Table = "table", e.InlineCode = "inline-code", e;
99
- }({}), P = {
153
+ }), [["__scopeId", "data-v-802ace82"]]);
154
+ //#endregion
155
+ //#region src/XMarkdown/interface.ts
156
+ var StreamCacheTokenType = /* @__PURE__ */ function(StreamCacheTokenType) {
157
+ StreamCacheTokenType["Text"] = "text";
158
+ StreamCacheTokenType["Link"] = "link";
159
+ StreamCacheTokenType["Image"] = "image";
160
+ StreamCacheTokenType["Html"] = "html";
161
+ StreamCacheTokenType["Emphasis"] = "emphasis";
162
+ StreamCacheTokenType["List"] = "list";
163
+ StreamCacheTokenType["Table"] = "table";
164
+ StreamCacheTokenType["InlineCode"] = "inline-code";
165
+ return StreamCacheTokenType;
166
+ }({});
167
+ //#endregion
168
+ //#region src/XMarkdown/composables/useStreaming.ts
169
+ var STREAM_INCOMPLETE_REGEX = {
100
170
  image: [/^!\[[^\]\r\n]{0,1000}$/, /^!\[[^\r\n]{0,1000}\]\(*[^)\r\n]{0,1000}$/],
101
171
  link: [/^\[[^\]\r\n]{0,1000}$/, /^\[[^\r\n]{0,1000}\]\(*[^)\r\n]{0,1000}$/],
102
172
  html: [/^<\/$/, /^<\/?[a-zA-Z][a-zA-Z0-9-]{0,100}[^>\r\n]{0,1000}$/],
103
173
  commonEmphasis: [/^(\*{1,3}|_{1,3})(?!\s)(?!.*\1$)[^\r\n]{0,1000}$/],
104
174
  list: [/^[-+*]\s{0,3}$/, /^[-+*]\s{1,3}(\*{1,3}|_{1,3})(?!\s)(?!.*\1$)[^\r\n]{0,1000}$/],
105
175
  "inline-code": [/^`[^`\r\n]{0,300}$/]
106
- }, F = (e) => {
107
- if (e.includes("\n\n")) return !1;
108
- let t = e.split("\n");
109
- if (t.length <= 1) return !0;
110
- let [n, r] = t, i = n.trim();
111
- if (!/^\|.*\|$/.test(i)) return !1;
112
- let a = r.trim().split("|").map((e) => e.trim()).filter(Boolean), o = /^:?-+:?$/;
113
- return a.every((e, t) => t === a.length - 1 && e === ":" || o.test(e));
114
- }, I = {
115
- [N.Link]: {
116
- tokenType: N.Link,
117
- isStartOfToken: (e) => e.startsWith("["),
118
- isStreamingValid: (e) => P.link.some((t) => t.test(e))
176
+ };
177
+ var isTableInComplete = (markdown) => {
178
+ if (markdown.includes("\n\n")) return false;
179
+ const lines = markdown.split("\n");
180
+ if (lines.length <= 1) return true;
181
+ const [header, separator] = lines;
182
+ const trimmedHeader = header.trim();
183
+ if (!/^\|.*\|$/.test(trimmedHeader)) return false;
184
+ const columns = separator.trim().split("|").map((col) => col.trim()).filter(Boolean);
185
+ const separatorRegex = /^:?-+:?$/;
186
+ return columns.every((col, index) => index === columns.length - 1 ? col === ":" || separatorRegex.test(col) : separatorRegex.test(col));
187
+ };
188
+ var tokenRecognizerMap = {
189
+ [StreamCacheTokenType.Link]: {
190
+ tokenType: StreamCacheTokenType.Link,
191
+ isStartOfToken: (markdown) => markdown.startsWith("["),
192
+ isStreamingValid: (markdown) => STREAM_INCOMPLETE_REGEX.link.some((re) => re.test(markdown))
119
193
  },
120
- [N.Image]: {
121
- tokenType: N.Image,
122
- isStartOfToken: (e) => e.startsWith("!"),
123
- isStreamingValid: (e) => P.image.some((t) => t.test(e))
194
+ [StreamCacheTokenType.Image]: {
195
+ tokenType: StreamCacheTokenType.Image,
196
+ isStartOfToken: (markdown) => markdown.startsWith("!"),
197
+ isStreamingValid: (markdown) => STREAM_INCOMPLETE_REGEX.image.some((re) => re.test(markdown))
124
198
  },
125
- [N.Html]: {
126
- tokenType: N.Html,
127
- isStartOfToken: (e) => e.startsWith("<"),
128
- isStreamingValid: (e) => P.html.some((t) => t.test(e))
199
+ [StreamCacheTokenType.Html]: {
200
+ tokenType: StreamCacheTokenType.Html,
201
+ isStartOfToken: (markdown) => markdown.startsWith("<"),
202
+ isStreamingValid: (markdown) => STREAM_INCOMPLETE_REGEX.html.some((re) => re.test(markdown))
129
203
  },
130
- [N.Emphasis]: {
131
- tokenType: N.Emphasis,
132
- isStartOfToken: (e) => e.startsWith("*") || e.startsWith("_"),
133
- isStreamingValid: (e) => P.commonEmphasis.some((t) => t.test(e))
204
+ [StreamCacheTokenType.Emphasis]: {
205
+ tokenType: StreamCacheTokenType.Emphasis,
206
+ isStartOfToken: (markdown) => markdown.startsWith("*") || markdown.startsWith("_"),
207
+ isStreamingValid: (markdown) => STREAM_INCOMPLETE_REGEX.commonEmphasis.some((re) => re.test(markdown))
134
208
  },
135
- [N.List]: {
136
- tokenType: N.List,
137
- isStartOfToken: (e) => /^[-+*]/.test(e),
138
- isStreamingValid: (e) => P.list.some((t) => t.test(e)),
139
- getCommitPrefix: (e) => {
140
- let t = e.match(/^([-+*]\s{0,3})/)?.[1], n = t ? e.slice(t.length) : "";
141
- return t && n.startsWith("`") ? t : null;
209
+ [StreamCacheTokenType.List]: {
210
+ tokenType: StreamCacheTokenType.List,
211
+ isStartOfToken: (markdown) => /^[-+*]/.test(markdown),
212
+ isStreamingValid: (markdown) => STREAM_INCOMPLETE_REGEX.list.some((re) => re.test(markdown)),
213
+ getCommitPrefix: (pending) => {
214
+ const listPrefix = pending.match(/^([-+*]\s{0,3})/)?.[1];
215
+ const rest = listPrefix ? pending.slice(listPrefix.length) : "";
216
+ return listPrefix && rest.startsWith("`") ? listPrefix : null;
142
217
  }
143
218
  },
144
- [N.Table]: {
145
- tokenType: N.Table,
146
- isStartOfToken: (e) => e.startsWith("|"),
147
- isStreamingValid: F
219
+ [StreamCacheTokenType.Table]: {
220
+ tokenType: StreamCacheTokenType.Table,
221
+ isStartOfToken: (markdown) => markdown.startsWith("|"),
222
+ isStreamingValid: isTableInComplete
148
223
  },
149
- [N.InlineCode]: {
150
- tokenType: N.InlineCode,
151
- isStartOfToken: (e) => e.startsWith("`"),
152
- isStreamingValid: (e) => P["inline-code"].some((t) => t.test(e))
153
- }
154
- }, L = (e, t) => {
155
- let n = I[t];
156
- if (!n) return;
157
- let { token: r, pending: i } = e;
158
- if (r === N.Text && n.isStartOfToken(i)) {
159
- e.token = t;
224
+ [StreamCacheTokenType.InlineCode]: {
225
+ tokenType: StreamCacheTokenType.InlineCode,
226
+ isStartOfToken: (markdown) => markdown.startsWith("`"),
227
+ isStreamingValid: (markdown) => STREAM_INCOMPLETE_REGEX["inline-code"].some((re) => re.test(markdown))
228
+ }
229
+ };
230
+ var recognize = (cache, tokenType) => {
231
+ const recognizer = tokenRecognizerMap[tokenType];
232
+ if (!recognizer) return;
233
+ const { token, pending } = cache;
234
+ if (token === StreamCacheTokenType.Text && recognizer.isStartOfToken(pending)) {
235
+ cache.token = tokenType;
160
236
  return;
161
237
  }
162
- if (r === t && !n.isStreamingValid(i)) {
163
- let t = n.getCommitPrefix?.(i);
164
- if (t) {
165
- e.completeMarkdown += t, e.pending = i.slice(t.length), e.token = N.Text;
238
+ if (token === tokenType && !recognizer.isStreamingValid(pending)) {
239
+ const prefix = recognizer.getCommitPrefix?.(pending);
240
+ if (prefix) {
241
+ cache.completeMarkdown += prefix;
242
+ cache.pending = pending.slice(prefix.length);
243
+ cache.token = StreamCacheTokenType.Text;
166
244
  return;
167
245
  }
168
- B(e);
246
+ commitCache(cache);
169
247
  }
170
- }, R = Object.values(I).filter((e) => !!e), z = () => ({
248
+ };
249
+ var recognizeHandlers = Object.values(tokenRecognizerMap).filter((recognizer) => Boolean(recognizer));
250
+ var getInitialCache = () => ({
171
251
  pending: "",
172
- token: N.Text,
252
+ token: StreamCacheTokenType.Text,
173
253
  processedLength: 0,
174
254
  completeMarkdown: ""
175
- }), B = (e) => {
176
- e.pending &&= (e.completeMarkdown += e.pending, ""), e.token = N.Text;
177
- }, te = (e, t = !1) => {
178
- let n = e.split("\n"), r = !1, i = "", a = 0;
179
- for (let e = 0; e < n.length; e++) {
180
- let o = n[e], s = (o.endsWith("\r") ? o.slice(0, -1) : o).match(/^(`{3,}|~{3,})(.*)$/);
181
- if (!s) continue;
182
- let c = s[1], l = s[2], u = c[0], d = c.length;
183
- if (!r) {
184
- r = !0, i = u, a = d;
255
+ });
256
+ var commitCache = (cache) => {
257
+ if (cache.pending) {
258
+ cache.completeMarkdown += cache.pending;
259
+ cache.pending = "";
260
+ }
261
+ cache.token = StreamCacheTokenType.Text;
262
+ };
263
+ var isInCodeBlock = (text, isFinalChunk = false) => {
264
+ const lines = text.split("\n");
265
+ let inFenced = false;
266
+ let fenceChar = "";
267
+ let fenceLen = 0;
268
+ for (let i = 0; i < lines.length; i++) {
269
+ const rawLine = lines[i];
270
+ const match = (rawLine.endsWith("\r") ? rawLine.slice(0, -1) : rawLine).match(/^(`{3,}|~{3,})(.*)$/);
271
+ if (!match) continue;
272
+ const fence = match[1];
273
+ const after = match[2];
274
+ const char = fence[0];
275
+ const len = fence.length;
276
+ if (!inFenced) {
277
+ inFenced = true;
278
+ fenceChar = char;
279
+ fenceLen = len;
185
280
  continue;
186
281
  }
187
- u === i && d >= a && /^\s*$/.test(l) && (t || e < n.length - 1) && (r = !1, i = "", a = 0);
282
+ if (char === fenceChar && len >= fenceLen && /^\s*$/.test(after) && (isFinalChunk || i < lines.length - 1)) {
283
+ inFenced = false;
284
+ fenceChar = "";
285
+ fenceLen = 0;
286
+ }
188
287
  }
189
- return r;
190
- }, ne = (e) => {
191
- let t = "";
192
- for (let n = 0; n < e.length; n++) {
193
- let r = e.charCodeAt(n);
194
- r >= 55296 && r <= 56319 ? n + 1 < e.length && e.charCodeAt(n + 1) >= 56320 && e.charCodeAt(n + 1) <= 57343 && (t += e[n] + e[n + 1], n++) : (r < 56320 || r > 57343) && (t += e[n]);
288
+ return inFenced;
289
+ };
290
+ var sanitizeForURIComponent = (input) => {
291
+ let result = "";
292
+ for (let i = 0; i < input.length; i++) {
293
+ const charCode = input.charCodeAt(i);
294
+ if (charCode >= 55296 && charCode <= 56319) {
295
+ if (i + 1 < input.length && input.charCodeAt(i + 1) >= 56320 && input.charCodeAt(i + 1) <= 57343) {
296
+ result += input[i] + input[i + 1];
297
+ i++;
298
+ }
299
+ } else if (charCode < 56320 || charCode > 57343) result += input[i];
195
300
  }
196
- return t;
197
- }, V = (e) => {
301
+ return result;
302
+ };
303
+ var safeEncodeURIComponent = (str) => {
198
304
  try {
199
- return encodeURIComponent(e);
200
- } catch (t) {
201
- return t instanceof URIError ? encodeURIComponent(ne(e)) : "";
305
+ return encodeURIComponent(str);
306
+ } catch (error) {
307
+ if (error instanceof URIError) return encodeURIComponent(sanitizeForURIComponent(str));
308
+ return "";
202
309
  }
203
310
  };
204
- function H(e, t, n) {
205
- let r = h(z()), i = h("");
206
- function a(e, t) {
207
- let { token: r, pending: i } = e;
208
- if (r === N.Text || r === N.Image && i === "!") return;
209
- if (r === N.Table && i.split("\n").length > 2) return i;
210
- let a = t?.incompleteMarkdownComponentMap?.[r] ?? `incomplete-${r}`;
211
- if (n?.value?.[a]) return `<${a} data-raw="${V(i)}" />`;
212
- }
213
- function o(e, t) {
214
- if (!e) {
215
- i.value = "", r.value = z();
311
+ function useStreaming(content, streaming, components) {
312
+ const streamCache = ref(getInitialCache());
313
+ const processedContent = ref("");
314
+ function handleIncompleteMarkdown(cache, opts) {
315
+ const { token, pending } = cache;
316
+ if (token === StreamCacheTokenType.Text) return void 0;
317
+ if (token === StreamCacheTokenType.Image && pending === "!") return;
318
+ if (token === StreamCacheTokenType.Table && pending.split("\n").length > 2) return pending;
319
+ const componentName = opts?.incompleteMarkdownComponentMap?.[token] ?? `incomplete-${token}`;
320
+ if (!components?.value?.[componentName]) return;
321
+ return `<${componentName} data-raw="${safeEncodeURIComponent(pending)}" />`;
322
+ }
323
+ function processStreaming(text, opts) {
324
+ if (!text) {
325
+ processedContent.value = "";
326
+ streamCache.value = getInitialCache();
216
327
  return;
217
328
  }
218
- let n = r.value.completeMarkdown + r.value.pending;
219
- e.startsWith(n) || (r.value = z());
220
- let o = r.value, s = e.slice(o.processedLength);
221
- if (!s) {
222
- let e = a(o, t);
223
- i.value = o.completeMarkdown + (e || "");
329
+ const expectedPrefix = streamCache.value.completeMarkdown + streamCache.value.pending;
330
+ if (!text.startsWith(expectedPrefix)) streamCache.value = getInitialCache();
331
+ const cache = streamCache.value;
332
+ const chunk = text.slice(cache.processedLength);
333
+ if (!chunk) {
334
+ const incompletePlaceholder = handleIncompleteMarkdown(cache, opts);
335
+ processedContent.value = cache.completeMarkdown + (incompletePlaceholder || "");
224
336
  return;
225
337
  }
226
- o.processedLength += s.length;
227
- for (let e of s) {
228
- if (o.pending += e, te(o.completeMarkdown + o.pending)) {
229
- B(o);
338
+ cache.processedLength += chunk.length;
339
+ for (const char of chunk) {
340
+ cache.pending += char;
341
+ if (isInCodeBlock(cache.completeMarkdown + cache.pending)) {
342
+ commitCache(cache);
230
343
  continue;
231
344
  }
232
- if (o.token === N.Text) for (let e of R) L(o, e.tokenType);
345
+ if (cache.token === StreamCacheTokenType.Text) for (const handler of recognizeHandlers) recognize(cache, handler.tokenType);
233
346
  else {
234
- let e = R.find((e) => e.tokenType === o.token);
235
- if (e && L(o, e.tokenType), o.token === N.Text) for (let e of R) L(o, e.tokenType);
347
+ const currentHandler = recognizeHandlers.find((handler) => handler.tokenType === cache.token);
348
+ if (currentHandler) recognize(cache, currentHandler.tokenType);
349
+ if (cache.token === StreamCacheTokenType.Text) for (const handler of recognizeHandlers) recognize(cache, handler.tokenType);
236
350
  }
237
- o.token === N.Text && B(o);
351
+ if (cache.token === StreamCacheTokenType.Text) commitCache(cache);
238
352
  }
239
- let c = a(o, t);
240
- i.value = o.completeMarkdown + (c || "");
353
+ const incompletePlaceholder = handleIncompleteMarkdown(cache, opts);
354
+ processedContent.value = cache.completeMarkdown + (incompletePlaceholder || "");
241
355
  }
242
- function s() {
243
- r.value = z(), i.value = "";
356
+ function reset() {
357
+ streamCache.value = getInitialCache();
358
+ processedContent.value = "";
244
359
  }
245
- return b([e, () => t.value?.hasNextChunk], ([e, n]) => {
246
- let a = t.value;
247
- if (!n) {
248
- i.value = e, r.value = {
360
+ watch([content, () => streaming.value?.hasNextChunk], ([newContent, hasNextChunk]) => {
361
+ const opts = streaming.value;
362
+ if (!Boolean(hasNextChunk)) {
363
+ processedContent.value = newContent;
364
+ streamCache.value = {
249
365
  pending: "",
250
- token: N.Text,
251
- processedLength: e.length,
252
- completeMarkdown: e
366
+ token: StreamCacheTokenType.Text,
367
+ processedLength: newContent.length,
368
+ completeMarkdown: newContent
253
369
  };
254
370
  return;
255
371
  }
256
- o(e, a);
257
- }, { immediate: !0 }), {
258
- processedContent: i,
259
- reset: s
372
+ processStreaming(newContent, opts);
373
+ }, { immediate: true });
374
+ return {
375
+ processedContent,
376
+ reset
260
377
  };
261
378
  }
262
379
  //#endregion
263
380
  //#region src/XMarkdown/composables/useTail.ts
264
- var U = "▋";
265
- function W(e) {
266
- let n = t(() => {
267
- let t = e.value?.tail;
268
- return t ? typeof t == "boolean" ? U : t.content || U : null;
381
+ var DEFAULT_TAIL_CONTENT$1 = "▋";
382
+ function useTail(streaming) {
383
+ const tailContent = computed(() => {
384
+ const tail = streaming.value?.tail;
385
+ if (!tail) return null;
386
+ if (typeof tail === "boolean") return DEFAULT_TAIL_CONTENT$1;
387
+ return tail.content || DEFAULT_TAIL_CONTENT$1;
269
388
  });
270
389
  return {
271
- tailContent: n,
272
- tailComponent: t(() => {
273
- let t = e.value?.tail;
274
- return !t || typeof t == "boolean" ? null : t.component || null;
390
+ tailContent,
391
+ tailComponent: computed(() => {
392
+ const tail = streaming.value?.tail;
393
+ if (!tail) return null;
394
+ if (typeof tail === "boolean") return null;
395
+ return tail.component || null;
275
396
  }),
276
- showTail: t(() => e.value?.hasNextChunk && n.value !== null)
397
+ showTail: computed(() => {
398
+ return streaming.value?.hasNextChunk && tailContent.value !== null;
399
+ })
277
400
  };
278
401
  }
279
402
  //#endregion
280
403
  //#region src/XMarkdown/core/Parser.ts
281
- var re = {
404
+ var escapeReplacements = {
282
405
  "&": "&amp;",
283
406
  "<": "&lt;",
284
407
  ">": "&gt;",
285
408
  "\"": "&quot;",
286
409
  "'": "&#39;"
287
410
  };
288
- function G(e) {
289
- return /[&<>"']/.test(e) ? e.replace(/[&<>"']/g, (e) => re[e] || e) : e;
411
+ function escapeHtml(html) {
412
+ if (/[&<>"']/.test(html)) return html.replace(/[&<>"']/g, (ch) => escapeReplacements[ch] || ch);
413
+ return html;
290
414
  }
291
- var K = class {
415
+ var Parser = class Parser {
416
+ static COMPLETE_FENCED_CODE = /^ {0,3}(`{3,}|~{3,})([\s\S]*?)\n {0,3}\1[ \n\t]*$/;
292
417
  options;
293
418
  markdownInstance;
294
- injectTail = !1;
295
- constructor(e = {}) {
419
+ injectTail = false;
420
+ codeBlockStates = [];
421
+ codeBlockStateIndex = 0;
422
+ constructor(options = {}) {
296
423
  this.options = {
297
- openLinksInNewTab: e.openLinksInNewTab ?? !0,
298
- paragraphTag: e.paragraphTag ?? "p",
299
- injectTail: e.injectTail ?? !1,
300
- protectCustomTags: e.protectCustomTags ?? !0,
301
- escapeRawHtml: e.escapeRawHtml ?? !1,
424
+ openLinksInNewTab: options.openLinksInNewTab ?? true,
425
+ paragraphTag: options.paragraphTag ?? "p",
426
+ injectTail: options.injectTail ?? false,
427
+ protectCustomTags: options.protectCustomTags ?? true,
428
+ escapeRawHtml: options.escapeRawHtml ?? false,
302
429
  config: {
303
- gfm: !0,
304
- ...e.config
430
+ gfm: true,
431
+ ...options.config
305
432
  },
306
- components: e.components ?? {},
307
- streamStatus: e.streamStatus ?? "done",
308
- codeBlockStatus: e.codeBlockStatus ?? {}
309
- }, this.markdownInstance = new S(this.options.config), this.configureRenderers();
433
+ components: options.components ?? {},
434
+ streamStatus: options.streamStatus ?? "done",
435
+ codeBlockStatus: options.codeBlockStatus ?? {}
436
+ };
437
+ this.markdownInstance = new Marked(this.options.config);
438
+ this.configureRenderers();
310
439
  }
311
- updateMarkedConfig(e) {
440
+ updateMarkedConfig(config) {
312
441
  this.options.config = {
313
442
  ...this.options.config,
314
- ...e
315
- }, this.markdownInstance = new S(this.options.config), this.configureRenderers();
443
+ ...config
444
+ };
445
+ this.markdownInstance = new Marked(this.options.config);
446
+ this.configureRenderers();
316
447
  }
317
448
  configureRenderers() {
318
449
  this.markdownInstance.use({ renderer: {
319
- html: (e) => this.options.escapeRawHtml ? G(e) : e,
320
- link: (e, t, n) => `<a href="${e}"${t ? ` title="${t}"` : ""}${this.options.openLinksInNewTab ? " target=\"_blank\" rel=\"noopener noreferrer\"" : ""}>${n}</a>`,
321
- paragraph: (e) => this.options.paragraphTag === "p" ? `<p>${e}</p>` : `<${this.options.paragraphTag}>${e}</${this.options.paragraphTag}>`,
322
- code: (e, t, n) => {
323
- let r = t || "";
324
- return `<pre><code class="language-${r}"${r ? ` data-lang="${r}"` : ""} data-block="true"${` data-state="${this.getCodeBlockState(r)}"`}>${n ? e : G(e)}</code></pre>`;
450
+ html: (html) => {
451
+ if (this.options.escapeRawHtml) return escapeHtml(html);
452
+ return html;
453
+ },
454
+ link: (href, title, text) => {
455
+ return `<a href="${href}"${title ? ` title="${title}"` : ""}${this.options.openLinksInNewTab ? ` target="_blank" rel="noopener noreferrer"` : ""}>${text}</a>`;
456
+ },
457
+ paragraph: (text) => {
458
+ if (this.options.paragraphTag === "p") return `<p>${text}</p>`;
459
+ return `<${this.options.paragraphTag}>${text}</${this.options.paragraphTag}>`;
460
+ },
461
+ code: (code, infostring, escaped) => {
462
+ const lang = infostring || "";
463
+ return `<pre><code class="language-${lang}"${lang ? ` data-lang="${lang}"` : ""} data-block="true"${` data-state="${this.consumeCodeBlockState(lang)}"`}>${escaped ? code : escapeHtml(code)}</code></pre>`;
325
464
  }
326
465
  } });
327
466
  }
328
- getCodeBlockState(e) {
329
- return this.options.codeBlockStatus[e] ?? this.options.streamStatus;
467
+ prepareCodeBlockStates(markdown) {
468
+ this.codeBlockStates = [];
469
+ this.codeBlockStateIndex = 0;
470
+ const tokens = this.markdownInstance.lexer(markdown);
471
+ const walkTokens = (nodes) => {
472
+ for (const node of nodes) {
473
+ if (!node || typeof node !== "object") continue;
474
+ const token = node;
475
+ if (token.type === "code") {
476
+ const lang = typeof token.lang === "string" ? token.lang : "";
477
+ const codeBlockStyle = typeof token.codeBlockStyle === "string" ? token.codeBlockStyle : "";
478
+ const raw = typeof token.raw === "string" ? token.raw : "";
479
+ const inferredState = codeBlockStyle === "indented" || Parser.COMPLETE_FENCED_CODE.test(raw) ? "done" : "loading";
480
+ this.codeBlockStates.push(this.options.codeBlockStatus[lang] ?? inferredState);
481
+ }
482
+ const childTokens = token.tokens;
483
+ if (Array.isArray(childTokens)) walkTokens(childTokens);
484
+ const items = token.items;
485
+ if (Array.isArray(items)) for (const item of items) {
486
+ if (!item || typeof item !== "object") continue;
487
+ const itemTokens = item.tokens;
488
+ if (Array.isArray(itemTokens)) walkTokens(itemTokens);
489
+ }
490
+ }
491
+ };
492
+ walkTokens(tokens);
330
493
  }
331
- parse(e, t) {
332
- this.injectTail = t?.injectTail ?? !1;
333
- let n = e;
334
- this.options.protectCustomTags && (n = this.protectCustomTags(n)), this.options.escapeRawHtml && (n = this.escapeRawHtml(n));
335
- let r = this.markedParse(n), i = this.sanitize(r);
336
- return this.injectTail ? this.injectTailMarker(i) : i;
494
+ consumeCodeBlockState(lang) {
495
+ const nextState = this.codeBlockStates[this.codeBlockStateIndex];
496
+ this.codeBlockStateIndex += 1;
497
+ return nextState ?? this.getCodeBlockState(lang);
337
498
  }
338
- markedParse(e) {
339
- return this.markdownInstance.parse(e);
499
+ getCodeBlockState(lang) {
500
+ return this.options.codeBlockStatus[lang] ?? this.options.streamStatus;
340
501
  }
341
- sanitize(e) {
342
- let t = Object.keys(this.options.components);
343
- return x.sanitize(e, {
344
- ADD_ATTR: [
345
- "target",
346
- "data-lang",
347
- "data-block",
348
- "data-state",
349
- "data-raw",
350
- "data-icon",
351
- "data-description",
352
- "icon",
353
- "description",
354
- "rel"
355
- ],
356
- ADD_TAGS: ["xmd-tail", ...t]
502
+ parse(markdown, parseOptions) {
503
+ this.injectTail = parseOptions?.injectTail ?? false;
504
+ let processed = markdown;
505
+ if (this.options.protectCustomTags) processed = this.protectCustomTags(processed);
506
+ if (this.options.escapeRawHtml) processed = this.escapeRawHtml(processed);
507
+ this.prepareCodeBlockStates(processed);
508
+ const html = this.markedParse(processed);
509
+ if (this.injectTail) return this.injectTailMarker(html);
510
+ return html;
511
+ }
512
+ markedParse(markdown) {
513
+ return this.markdownInstance.parse(markdown);
514
+ }
515
+ protectCustomTags(markdown) {
516
+ const customTagPattern = /<[A-Z][a-zA-Z0-9]*[^>]*>[\s\S]*?<\/[A-Z][a-zA-Z0-9]*>/g;
517
+ let result = markdown;
518
+ let placeholderIndex = 0;
519
+ result = result.replace(customTagPattern, () => {
520
+ const placeholder = `__CUSTOM_TAG_${placeholderIndex}__`;
521
+ placeholderIndex++;
522
+ return placeholder;
523
+ });
524
+ return result;
525
+ }
526
+ escapeRawHtml(markdown) {
527
+ return markdown.replace(/<[^>]+>/g, (match) => {
528
+ return escapeHtml(match);
357
529
  });
358
530
  }
359
- protectCustomTags(e) {
360
- let t = /<[A-Z][a-zA-Z0-9]*[^>]*>[\s\S]*?<\/[A-Z][a-zA-Z0-9]*>/g, n = e, r = 0;
361
- return n = n.replace(t, () => {
362
- let e = `__CUSTOM_TAG_${r}__`;
363
- return r++, e;
364
- }), n;
365
- }
366
- escapeRawHtml(e) {
367
- return e.replace(/<[^>]+>/g, (e) => G(e));
368
- }
369
- injectTailMarker(e) {
370
- if (e.includes("<xmd-tail></xmd-tail>")) return e;
371
- let t = document.createElement("div");
372
- t.innerHTML = e;
373
- let n = (e) => {
374
- let t = Array.from(e.childNodes);
375
- for (let e = t.length - 1; e >= 0; e--) {
376
- let r = t[e];
377
- if (r.nodeType === Node.TEXT_NODE) {
378
- if ((r.textContent || "").trim()) return r;
531
+ injectTailMarker(html) {
532
+ if (html.includes("<xmd-tail></xmd-tail>")) return html;
533
+ const container = document.createElement("div");
534
+ container.innerHTML = html;
535
+ const findLastMeaningfulNode = (root) => {
536
+ const children = Array.from(root.childNodes);
537
+ for (let i = children.length - 1; i >= 0; i--) {
538
+ const node = children[i];
539
+ if (node.nodeType === Node.TEXT_NODE) {
540
+ if ((node.textContent || "").trim()) return node;
379
541
  continue;
380
542
  }
381
- if (r.nodeType === Node.ELEMENT_NODE) return n(r) || r;
543
+ if (node.nodeType !== Node.ELEMENT_NODE) continue;
544
+ const nested = findLastMeaningfulNode(node);
545
+ if (nested) return nested;
546
+ return node;
382
547
  }
383
548
  return null;
384
- }, r = n(t);
385
- if (!r || r.nodeType !== Node.TEXT_NODE) return e;
386
- let i = document.createElement("xmd-tail");
387
- return r.parentNode?.insertBefore(i, r.nextSibling), t.innerHTML;
549
+ };
550
+ const lastMeaningfulNode = findLastMeaningfulNode(container);
551
+ if (!lastMeaningfulNode || lastMeaningfulNode.nodeType !== Node.TEXT_NODE) return html;
552
+ const marker = document.createElement("xmd-tail");
553
+ lastMeaningfulNode.parentNode?.insertBefore(marker, lastMeaningfulNode.nextSibling);
554
+ return container.innerHTML;
388
555
  }
389
- setOptions(e) {
390
- let { config: t, ...n } = e;
391
- Object.assign(this.options, n), t && this.updateMarkedConfig(t);
556
+ setOptions(options) {
557
+ const { config, ...rest } = options;
558
+ Object.assign(this.options, rest);
559
+ if (config) this.updateMarkedConfig(config);
392
560
  }
393
- }, q = /* @__PURE__ */ c({
561
+ };
562
+ //#endregion
563
+ //#region src/XMarkdown/components/AnimationText.vue
564
+ var AnimationText_default = /* @__PURE__ */ defineComponent({
394
565
  __name: "AnimationText",
395
566
  props: {
396
567
  text: {},
397
568
  fadeDuration: { default: 200 },
398
569
  easing: { default: "ease-in-out" }
399
570
  },
400
- setup(n) {
401
- let r = n, a = h([]), o = h("");
402
- function s(e) {
403
- if (e === o.value) return;
404
- if (!(o.value && e.startsWith(o.value))) {
405
- a.value = [e], o.value = e;
571
+ setup(__props) {
572
+ const props = __props;
573
+ const chunks = ref([]);
574
+ const previousText = ref("");
575
+ function updateChunks(nextText) {
576
+ if (nextText === previousText.value) return;
577
+ if (!Boolean(previousText.value && nextText.startsWith(previousText.value))) {
578
+ chunks.value = [nextText];
579
+ previousText.value = nextText;
406
580
  return;
407
581
  }
408
- let t = e.slice(o.value.length);
409
- t && (a.value = [...a.value, t], o.value = e);
582
+ const delta = nextText.slice(previousText.value.length);
583
+ if (!delta) return;
584
+ chunks.value = [...chunks.value, delta];
585
+ previousText.value = nextText;
410
586
  }
411
- b(() => r.text, s, { immediate: !0 });
412
- let c = t(() => ({
413
- animation: `x-markdown-fade-in ${r.fadeDuration}ms ${r.easing} forwards`,
587
+ watch(() => props.text, updateChunks, { immediate: true });
588
+ const animationStyle = computed(() => ({
589
+ animation: `x-markdown-fade-in ${props.fadeDuration}ms ${props.easing} forwards`,
414
590
  color: "inherit"
415
591
  }));
416
- return (t, n) => (m(!0), i(e, null, g(a.value, (e, t) => (m(), i("span", {
417
- key: `animation-text-${t}`,
418
- style: d(c.value)
419
- }, v(e), 5))), 128));
592
+ return (_ctx, _cache) => {
593
+ return openBlock(true), createElementBlock(Fragment, null, renderList(chunks.value, (chunk, index) => {
594
+ return openBlock(), createElementBlock("span", {
595
+ key: `animation-text-${index}`,
596
+ style: normalizeStyle(animationStyle.value)
597
+ }, toDisplayString(chunk), 5);
598
+ }), 128);
599
+ };
420
600
  }
421
- }), J = new Set([
601
+ });
602
+ //#endregion
603
+ //#region src/XMarkdown/core/detectUnclosedComponentTags.ts
604
+ var WHITESPACE_REGEX = /\s/;
605
+ var TAG_NAME_CHAR_REGEX = /[a-zA-Z0-9-]/;
606
+ var VOID_ELEMENTS = new Set([
422
607
  "area",
423
608
  "base",
424
609
  "br",
@@ -433,56 +618,198 @@ var K = class {
433
618
  "source",
434
619
  "track",
435
620
  "wbr"
436
- ]), Y = /\/\s*>$/;
437
- function X(e, t) {
438
- let n = /* @__PURE__ */ new Set(), r = [], i = {};
439
- t.forEach((e) => {
440
- i[e] = 0;
441
- });
442
- let a = /<\/?([a-zA-Z][a-zA-Z0-9-]*)[^>]*>/g, o;
443
- for (; (o = a.exec(e)) !== null;) {
444
- let e = o[0], n = o[1].toLowerCase();
445
- if (!t.includes(n) || e.includes("<!--") || e.includes("<![CDATA[")) continue;
446
- let a = Y.test(e), s = !e.startsWith("</");
447
- if (!(a || !s) && !J.has(n)) if (s) {
448
- i[n] = (i[n] || 0) + 1;
449
- let e = `${n}-${i[n]}`;
450
- r.push({
451
- name: n,
452
- instanceId: e
453
- });
454
- } else {
455
- let e = r.findLast((e) => e.name === n);
456
- if (e) {
457
- let t = r.lastIndexOf(e);
458
- r.splice(t, 1);
621
+ ]);
622
+ var COMMENT_START = "<!--";
623
+ var COMMENT_END = "-->";
624
+ var CDATA_START = "<![CDATA[";
625
+ var CDATA_END = "]]>";
626
+ var getTagInstanceId = (tagName, instance) => `${tagName}-${instance}`;
627
+ var skipComment = (html, pos) => {
628
+ if (!html.startsWith(COMMENT_START, pos)) return pos;
629
+ const endPos = html.indexOf(COMMENT_END, pos + 4);
630
+ return endPos === -1 ? html.length : endPos + 3;
631
+ };
632
+ var skipCDATA = (html, pos) => {
633
+ if (!html.startsWith(CDATA_START, pos)) return pos;
634
+ const endPos = html.indexOf(CDATA_END, pos + 9);
635
+ return endPos === -1 ? html.length : endPos + 3;
636
+ };
637
+ var parseClosingTag = (html, pos) => {
638
+ if (html[pos + 1] !== "/") return null;
639
+ let scanPos = pos + 2;
640
+ let tagName = "";
641
+ while (scanPos < html.length && WHITESPACE_REGEX.test(html[scanPos])) scanPos++;
642
+ while (scanPos < html.length && TAG_NAME_CHAR_REGEX.test(html[scanPos])) {
643
+ tagName += html[scanPos];
644
+ scanPos++;
645
+ }
646
+ while (scanPos < html.length && WHITESPACE_REGEX.test(html[scanPos])) scanPos++;
647
+ if (!tagName || html[scanPos] !== ">") return null;
648
+ return {
649
+ tagName: tagName.toLowerCase(),
650
+ endPos: scanPos + 1
651
+ };
652
+ };
653
+ var parseOpeningTag = (html, pos) => {
654
+ let scanPos = pos + 1;
655
+ let tagName = "";
656
+ while (scanPos < html.length && TAG_NAME_CHAR_REGEX.test(html[scanPos])) {
657
+ tagName += html[scanPos];
658
+ scanPos++;
659
+ }
660
+ if (!tagName) return null;
661
+ let foundEnd = false;
662
+ let isSelfClosing = false;
663
+ while (scanPos < html.length) {
664
+ if (html[scanPos] === ">") {
665
+ foundEnd = true;
666
+ isSelfClosing = html[scanPos - 1] === "/";
667
+ break;
668
+ }
669
+ if (html[scanPos] === "\"" || html[scanPos] === "'") {
670
+ const quoteChar = html[scanPos];
671
+ scanPos++;
672
+ while (scanPos < html.length) {
673
+ if (html[scanPos] === "\\" && scanPos + 1 < html.length) {
674
+ scanPos += 2;
675
+ continue;
676
+ }
677
+ if (html[scanPos] === quoteChar) {
678
+ scanPos++;
679
+ break;
680
+ }
681
+ scanPos++;
459
682
  }
683
+ continue;
684
+ }
685
+ scanPos++;
686
+ }
687
+ return {
688
+ tagName: tagName.toLowerCase(),
689
+ endPos: foundEnd ? scanPos + 1 : html.length,
690
+ foundEnd,
691
+ isSelfClosing
692
+ };
693
+ };
694
+ function detectUnclosedComponentTags(html, componentNames) {
695
+ const trackedTags = new Set(Array.from(componentNames, (tagName) => tagName.toLowerCase()));
696
+ if (trackedTags.size === 0 || html.length === 0) return /* @__PURE__ */ new Set();
697
+ const unclosedTags = /* @__PURE__ */ new Set();
698
+ const tagCounts = {};
699
+ const openTagIndexes = {};
700
+ let pos = 0;
701
+ while (pos < html.length) {
702
+ const afterComment = skipComment(html, pos);
703
+ if (afterComment !== pos) {
704
+ pos = afterComment;
705
+ continue;
706
+ }
707
+ const afterCDATA = skipCDATA(html, pos);
708
+ if (afterCDATA !== pos) {
709
+ pos = afterCDATA;
710
+ continue;
711
+ }
712
+ if (html[pos] !== "<") {
713
+ pos++;
714
+ continue;
715
+ }
716
+ const closingTag = parseClosingTag(html, pos);
717
+ if (closingTag) {
718
+ const pendingIndexes = openTagIndexes[closingTag.tagName];
719
+ if (trackedTags.has(closingTag.tagName) && pendingIndexes?.length) pendingIndexes.pop();
720
+ pos = closingTag.endPos;
721
+ continue;
722
+ }
723
+ const openingTag = parseOpeningTag(html, pos);
724
+ if (!openingTag || !trackedTags.has(openingTag.tagName)) {
725
+ pos++;
726
+ continue;
727
+ }
728
+ tagCounts[openingTag.tagName] = (tagCounts[openingTag.tagName] ?? 0) + 1;
729
+ const instance = tagCounts[openingTag.tagName];
730
+ if (!openingTag.foundEnd) unclosedTags.add(getTagInstanceId(openingTag.tagName, instance));
731
+ else if (!openingTag.isSelfClosing && !VOID_ELEMENTS.has(openingTag.tagName)) {
732
+ openTagIndexes[openingTag.tagName] ??= [];
733
+ openTagIndexes[openingTag.tagName].push(instance);
460
734
  }
735
+ pos = openingTag.endPos;
461
736
  }
462
- return r.forEach((e) => {
463
- n.add(e.instanceId);
464
- }), n;
737
+ for (const [tagName, pendingIndexes] of Object.entries(openTagIndexes)) pendingIndexes.forEach((instance) => {
738
+ unclosedTags.add(getTagInstanceId(tagName, instance));
739
+ });
740
+ return unclosedTags;
465
741
  }
466
742
  //#endregion
467
743
  //#region src/XMarkdown/core/VueRenderer.ts
468
- var ie = 200, ae = /[^\r\n\s]+/, oe = /* @__PURE__ */ "math.maction.maligngroup.malignmark.menclose.merror.mfenced.mfrac.mglyph.mi.mlabeledtr.mlongdiv.mmultiscripts.mn.mo.mover.mpadded.mphantom.mprescripts.mroot.mrow.ms.mscarries.mscarry.msgroup.msline.mspace.msqrt.msrow.mstack.mstyle.msub.msup.msubsup.mtable.mtd.mtext.mtr.munder.munderover.semantics.annotation.annotation-xml".split("."), Z = class {
744
+ var DEFAULT_ANIMATION_DURATION = 200;
745
+ var NON_WHITESPACE_REGEX = /[^\r\n\s]+/;
746
+ var MATHML_TAGS = [
747
+ "math",
748
+ "maction",
749
+ "maligngroup",
750
+ "malignmark",
751
+ "menclose",
752
+ "merror",
753
+ "mfenced",
754
+ "mfrac",
755
+ "mglyph",
756
+ "mi",
757
+ "mlabeledtr",
758
+ "mlongdiv",
759
+ "mmultiscripts",
760
+ "mn",
761
+ "mo",
762
+ "mover",
763
+ "mpadded",
764
+ "mphantom",
765
+ "mprescripts",
766
+ "mroot",
767
+ "mrow",
768
+ "ms",
769
+ "mscarries",
770
+ "mscarry",
771
+ "msgroup",
772
+ "msline",
773
+ "mspace",
774
+ "msqrt",
775
+ "msrow",
776
+ "mstack",
777
+ "mstyle",
778
+ "msub",
779
+ "msup",
780
+ "msubsup",
781
+ "mtable",
782
+ "mtd",
783
+ "mtext",
784
+ "mtr",
785
+ "munder",
786
+ "munderover",
787
+ "semantics",
788
+ "annotation",
789
+ "annotation-xml"
790
+ ];
791
+ var VueRenderer = class {
469
792
  options;
470
- constructor(e = {}) {
793
+ constructor(options = {}) {
471
794
  this.options = {
472
- components: e.components ?? {},
473
- enableAnimation: e.enableAnimation ?? !0,
795
+ components: options.components ?? {},
796
+ enableAnimation: options.enableAnimation ?? true,
474
797
  animationConfig: {
475
- fadeDuration: e.animationConfig?.fadeDuration ?? ie,
476
- easing: e.animationConfig?.easing ?? "ease-in-out"
798
+ fadeDuration: options.animationConfig?.fadeDuration ?? DEFAULT_ANIMATION_DURATION,
799
+ easing: options.animationConfig?.easing ?? "ease-in-out"
477
800
  }
478
801
  };
479
802
  }
480
- render(t) {
481
- let n = this.sanitize(t), r = X(n, Object.keys(this.options.components)), i = this.parseToVNodes(n, r);
482
- return i.length === 0 ? l("span", "") : i.length === 1 ? i[0] : l(e, i);
803
+ render(html) {
804
+ const unclosedTags = detectUnclosedComponentTags(html, Object.keys(this.options.components));
805
+ const sanitized = this.sanitize(html);
806
+ const nodes = this.parseToVNodes(sanitized, unclosedTags);
807
+ if (nodes.length === 0) return h("span", "");
808
+ if (nodes.length === 1) return nodes[0];
809
+ return h(Fragment, nodes);
483
810
  }
484
- sanitize(e) {
485
- let t = [...new Set([
811
+ sanitize(html) {
812
+ const allowedTags = [...new Set([
486
813
  ...Object.keys(this.options.components),
487
814
  "p",
488
815
  "br",
@@ -514,10 +841,10 @@ var ie = 200, ae = /[^\r\n\s]+/, oe = /* @__PURE__ */ "math.maction.maligngroup.
514
841
  "td",
515
842
  "hr",
516
843
  "xmd-tail",
517
- ...oe
844
+ ...MATHML_TAGS
518
845
  ])];
519
- return x.sanitize(e, {
520
- ALLOWED_TAGS: t,
846
+ return DOMPurify.sanitize(html, {
847
+ ALLOWED_TAGS: allowedTags,
521
848
  ALLOWED_ATTR: [
522
849
  "class",
523
850
  "style",
@@ -543,198 +870,269 @@ var ie = 200, ae = /[^\r\n\s]+/, oe = /* @__PURE__ */ "math.maction.maligngroup.
543
870
  ]
544
871
  });
545
872
  }
546
- parseToVNodes(e, t) {
547
- let n = `<div>${e}</div>`, r = document.createElement("div");
548
- r.innerHTML = n;
549
- let i = [];
550
- return Array.from(r.childNodes).forEach((e) => {
551
- let n = this.convertNode(e, t);
552
- n && i.push(n);
553
- }), i;
554
- }
555
- convertNode(e, t) {
556
- if (e.nodeType === Node.TEXT_NODE) {
557
- let t = e.textContent || "", n = e.parentNode instanceof Element ? e.parentNode.tagName.toLowerCase() : "", r = !!(n && this.options.components[n]);
558
- return this.options.enableAnimation && ae.test(t) && !r ? this.wrapWithAnimation(t) : o(t);
873
+ parseToVNodes(html, unclosedTags) {
874
+ const template = `<div>${html}</div>`;
875
+ const container = document.createElement("div");
876
+ container.innerHTML = template;
877
+ const cidRef = { tagIndexes: {} };
878
+ const nodes = [];
879
+ Array.from(container.childNodes).forEach((node) => {
880
+ const vnode = this.convertNode(node, unclosedTags, cidRef);
881
+ if (vnode) nodes.push(vnode);
882
+ });
883
+ return nodes;
884
+ }
885
+ convertNode(domNode, unclosedTags, cidRef) {
886
+ if (domNode.nodeType === Node.TEXT_NODE) {
887
+ const text = domNode.textContent || "";
888
+ const parentTagName = domNode.parentNode instanceof Element ? domNode.parentNode.tagName.toLowerCase() : "";
889
+ const isParentCustomComponent = Boolean(parentTagName && this.options.components[parentTagName]);
890
+ if (this.options.enableAnimation && NON_WHITESPACE_REGEX.test(text) && !isParentCustomComponent) return this.wrapWithAnimation(text);
891
+ return createTextVNode(text);
559
892
  }
560
- if (e.nodeType !== Node.ELEMENT_NODE) return null;
561
- let n = e, r = n.tagName.toLowerCase(), i = this.options.components[r];
562
- if (i) {
563
- let e = this.extractComponentProps(n, r, t), a = [];
564
- return Array.from(n.childNodes).forEach((e) => {
565
- let n = this.convertNode(e, t);
566
- n && a.push(n);
567
- }), a.length === 0 ? l(i, e) : l(i, e, { default: () => a });
893
+ if (domNode.nodeType !== Node.ELEMENT_NODE) return null;
894
+ const element = domNode;
895
+ const tagName = element.tagName.toLowerCase();
896
+ const customComponent = this.options.components[tagName];
897
+ if (customComponent) {
898
+ const componentProps = this.extractComponentProps(element, tagName, unclosedTags, cidRef);
899
+ const children = [];
900
+ Array.from(element.childNodes).forEach((child) => {
901
+ const childVNode = this.convertNode(child, unclosedTags, cidRef);
902
+ if (childVNode) children.push(childVNode);
903
+ });
904
+ if (children.length === 0) return h(customComponent, componentProps);
905
+ return h(customComponent, componentProps, { default: () => children });
568
906
  }
569
- return r === "xmd-tail" ? l("span", { class: "xmd-tail" }, "▋") : this.convertNativeElement(n, r, t);
570
- }
571
- convertNativeElement(e, t, n) {
572
- let r = [], i = {};
573
- return Array.from(e.attributes).forEach((e) => {
574
- i[e.name] = e.value;
575
- }), Array.from(e.childNodes).forEach((e) => {
576
- let t = this.convertNode(e, n);
577
- t && r.push(t);
578
- }), l(t, i, r);
579
- }
580
- extractComponentProps(e, t, n) {
581
- let r = {};
582
- return r.streamStatus = Array.from(n).find((e) => e.startsWith(t)) ? "loading" : "done", Array.from(e.attributes).forEach((e) => {
583
- r[e.name] = e.value;
584
- }), r;
585
- }
586
- wrapWithAnimation(e) {
587
- return l(q, {
588
- text: e,
907
+ if (tagName === "xmd-tail") return h("span", { class: "xmd-tail" }, "▋");
908
+ return this.convertNativeElement(element, tagName, unclosedTags, cidRef);
909
+ }
910
+ convertNativeElement(element, tagName, unclosedTags, cidRef) {
911
+ const children = [];
912
+ const props = {};
913
+ Array.from(element.attributes).forEach((attr) => {
914
+ props[attr.name] = attr.value;
915
+ });
916
+ Array.from(element.childNodes).forEach((child) => {
917
+ const childVNode = this.convertNode(child, unclosedTags, cidRef);
918
+ if (childVNode) children.push(childVNode);
919
+ });
920
+ return h(tagName, props, children);
921
+ }
922
+ extractComponentProps(element, tagName, unclosedTags, cidRef) {
923
+ const props = {};
924
+ cidRef.tagIndexes[tagName] = (cidRef.tagIndexes[tagName] ?? 0) + 1;
925
+ const instanceId = getTagInstanceId(tagName, cidRef.tagIndexes[tagName]);
926
+ props.streamStatus = unclosedTags.has(instanceId) ? "loading" : "done";
927
+ Array.from(element.attributes).forEach((attr) => {
928
+ props[attr.name] = attr.value;
929
+ });
930
+ if (tagName === "code") {
931
+ props.block = element.getAttribute("data-block") === "true";
932
+ props.streamStatus = element.getAttribute("data-state") === "loading" ? "loading" : "done";
933
+ const langFromData = element.getAttribute("data-lang") || "";
934
+ const className = element.getAttribute("class") || "";
935
+ const langFromClass = className.match(/(?:^|\s)language-([^\s]+)/)?.[1] ?? className.match(/(?:^|\s)lang-([^\s]+)/)?.[1] ?? "";
936
+ const lang = langFromData || langFromClass;
937
+ if (lang) props.lang = lang;
938
+ }
939
+ return props;
940
+ }
941
+ wrapWithAnimation(text) {
942
+ return h(AnimationText_default, {
943
+ text,
589
944
  fadeDuration: this.options.animationConfig.fadeDuration,
590
945
  easing: this.options.animationConfig.easing
591
946
  });
592
947
  }
593
- setOptions(e) {
594
- e.components && (this.options.components = {
948
+ setOptions(options) {
949
+ if (options.components) this.options.components = {
595
950
  ...this.options.components,
596
- ...e.components
597
- }), e.enableAnimation !== void 0 && (this.options.enableAnimation = e.enableAnimation), e.animationConfig && (this.options.animationConfig = {
951
+ ...options.components
952
+ };
953
+ if (options.enableAnimation !== void 0) this.options.enableAnimation = options.enableAnimation;
954
+ if (options.animationConfig) this.options.animationConfig = {
598
955
  ...this.options.animationConfig,
599
- ...e.animationConfig
600
- });
956
+ ...options.animationConfig
957
+ };
601
958
  }
602
- }, se = /* @__PURE__ */ c({
959
+ };
960
+ //#endregion
961
+ //#region src/XMarkdown/index.vue
962
+ var XMarkdown_default = /* @__PURE__ */ defineComponent({
603
963
  __name: "index",
604
964
  props: {
605
965
  content: { default: "" },
606
966
  components: { default: () => ({}) },
607
967
  streaming: { default: void 0 },
608
- config: { default: () => ({ gfm: !0 }) },
968
+ config: { default: () => ({ gfm: true }) },
609
969
  debug: {
610
970
  type: Boolean,
611
- default: !1
971
+ default: false
612
972
  },
613
973
  protectCustomTagNewlines: {
614
974
  type: Boolean,
615
- default: !0
975
+ default: true
616
976
  },
617
977
  escapeRawHtml: {
618
978
  type: Boolean,
619
- default: !1
979
+ default: false
620
980
  },
621
981
  className: {},
622
982
  style: {},
623
983
  openLinksInNewTab: {
624
984
  type: Boolean,
625
- default: !0
985
+ default: true
626
986
  },
627
987
  paragraphTag: { default: "p" }
628
988
  },
629
- setup(e) {
630
- let a = e, o = t(() => a.content || ""), f = t(() => a.streaming), { processedContent: p } = H(o, f, t(() => a.components)), { tailContent: g, tailComponent: v, showTail: x } = W(f), S = t(() => {
631
- let e = { ...a.components };
632
- if (!x.value || !g.value) return e;
633
- let t = v.value || M, n = g.value, r = c({
989
+ setup(__props) {
990
+ const props = __props;
991
+ const contentRef = computed(() => props.content || "");
992
+ const streamingRef = computed(() => props.streaming);
993
+ const { processedContent } = useStreaming(contentRef, streamingRef, computed(() => props.components));
994
+ const { tailContent, tailComponent, showTail } = useTail(streamingRef);
995
+ const mergedComponents = computed(() => {
996
+ const baseComponents = { ...props.components };
997
+ if (!showTail.value || !tailContent.value) return baseComponents;
998
+ const resolvedTailComponent = tailComponent.value || TailIndicator_default;
999
+ const content = tailContent.value;
1000
+ const TailBridge = defineComponent({
634
1001
  name: "XmdTailBridge",
635
1002
  setup() {
636
- return () => l(t, { content: n });
1003
+ return () => h(resolvedTailComponent, { content });
637
1004
  }
638
1005
  });
639
1006
  return {
640
- ...e,
641
- "xmd-tail": r
1007
+ ...baseComponents,
1008
+ "xmd-tail": TailBridge
642
1009
  };
643
- }), C = c({
1010
+ });
1011
+ const VNodeRenderer = defineComponent({
644
1012
  name: "XmdVNodeRenderer",
645
1013
  props: { node: {
646
1014
  type: Object,
647
- required: !0
1015
+ required: true
648
1016
  } },
649
- setup(e) {
650
- return () => e.node;
1017
+ setup(props) {
1018
+ return () => props.node;
651
1019
  }
652
- }), w = _(new K({
653
- openLinksInNewTab: a.openLinksInNewTab,
654
- paragraphTag: a.paragraphTag,
655
- protectCustomTags: a.protectCustomTagNewlines,
656
- escapeRawHtml: a.escapeRawHtml,
657
- config: a.config,
658
- components: a.components
659
- })), T = _(new Z({
660
- components: S.value,
661
- enableAnimation: a.streaming?.enableAnimation ?? !0,
662
- animationConfig: a.streaming?.animationConfig
663
- })), E = h(0), D = () => {
664
- E.value += 1;
665
- }, O = t(() => (E.value, w.value.parse(p.value, { injectTail: x.value }))), k = t(() => (E.value, T.value.render(O.value)));
666
- return b(() => [
667
- a.openLinksInNewTab,
668
- a.paragraphTag,
669
- a.protectCustomTagNewlines,
670
- a.escapeRawHtml
1020
+ });
1021
+ const parser = shallowRef(new Parser({
1022
+ openLinksInNewTab: props.openLinksInNewTab,
1023
+ paragraphTag: props.paragraphTag,
1024
+ protectCustomTags: props.protectCustomTagNewlines,
1025
+ escapeRawHtml: props.escapeRawHtml,
1026
+ config: props.config,
1027
+ components: props.components
1028
+ }));
1029
+ const renderer = shallowRef(new VueRenderer({
1030
+ components: mergedComponents.value,
1031
+ enableAnimation: props.streaming?.enableAnimation ?? true,
1032
+ animationConfig: props.streaming?.animationConfig
1033
+ }));
1034
+ const optionsVersion = ref(0);
1035
+ const bumpOptionsVersion = () => {
1036
+ optionsVersion.value += 1;
1037
+ };
1038
+ const htmlOutput = computed(() => {
1039
+ optionsVersion.value;
1040
+ return parser.value.parse(processedContent.value, { injectTail: showTail.value });
1041
+ });
1042
+ const vNode = computed(() => {
1043
+ optionsVersion.value;
1044
+ return renderer.value.render(htmlOutput.value);
1045
+ });
1046
+ watch(() => [
1047
+ props.openLinksInNewTab,
1048
+ props.paragraphTag,
1049
+ props.protectCustomTagNewlines,
1050
+ props.escapeRawHtml
671
1051
  ], () => {
672
- w.value.setOptions({
673
- openLinksInNewTab: a.openLinksInNewTab,
674
- paragraphTag: a.paragraphTag,
675
- protectCustomTags: a.protectCustomTagNewlines,
676
- escapeRawHtml: a.escapeRawHtml
677
- }), D();
678
- }), b(() => a.config, (e) => {
679
- w.value.setOptions({ config: e }), D();
680
- }, { deep: !0 }), b(() => a.components, (e) => {
681
- w.value.setOptions({ components: e }), D();
682
- }, { deep: !0 }), b(S, (e) => {
683
- T.value.setOptions({ components: e }), D();
684
- }, { deep: !0 }), b(() => a.streaming, (e) => {
685
- T.value.setOptions({
686
- enableAnimation: e?.enableAnimation ?? !0,
687
- animationConfig: e?.animationConfig
688
- }), D();
689
- }, { deep: !0 }), (t, a) => (m(), i("div", {
690
- class: u(["x-markdown", e.className]),
691
- style: d(e.style)
692
- }, [s(y(C), { node: k.value }, null, 8, ["node"]), e.debug ? (m(), n(j, { key: 0 })) : r("", !0)], 6));
1052
+ parser.value.setOptions({
1053
+ openLinksInNewTab: props.openLinksInNewTab,
1054
+ paragraphTag: props.paragraphTag,
1055
+ protectCustomTags: props.protectCustomTagNewlines,
1056
+ escapeRawHtml: props.escapeRawHtml
1057
+ });
1058
+ bumpOptionsVersion();
1059
+ });
1060
+ watch(() => props.config, (newConfig) => {
1061
+ parser.value.setOptions({ config: newConfig });
1062
+ bumpOptionsVersion();
1063
+ }, { deep: true });
1064
+ watch(() => props.components, (newComponents) => {
1065
+ parser.value.setOptions({ components: newComponents });
1066
+ bumpOptionsVersion();
1067
+ }, { deep: true });
1068
+ watch(mergedComponents, (newComponents) => {
1069
+ renderer.value.setOptions({ components: newComponents });
1070
+ bumpOptionsVersion();
1071
+ }, { deep: true });
1072
+ watch(() => props.streaming, (newStreaming) => {
1073
+ renderer.value.setOptions({
1074
+ enableAnimation: newStreaming?.enableAnimation ?? true,
1075
+ animationConfig: newStreaming?.animationConfig
1076
+ });
1077
+ bumpOptionsVersion();
1078
+ }, { deep: true });
1079
+ return (_ctx, _cache) => {
1080
+ return openBlock(), createElementBlock("div", {
1081
+ class: normalizeClass(["x-markdown", __props.className]),
1082
+ style: normalizeStyle(__props.style)
1083
+ }, [createVNode(unref(VNodeRenderer), { node: vNode.value }, null, 8, ["node"]), __props.debug ? (openBlock(), createBlock(DebugPanel_default, { key: 0 })) : createCommentVNode("", true)], 6);
1084
+ };
693
1085
  }
694
1086
  });
695
1087
  //#endregion
696
1088
  //#region src/XMarkdown/composables/useParser.ts
697
- function Q(e) {
698
- let t = _(null);
699
- function n(e) {
700
- return new K(e);
1089
+ function useParser(initialOptions) {
1090
+ const parser = shallowRef(null);
1091
+ function createParser(options) {
1092
+ return new Parser(options);
701
1093
  }
702
- function r(r, i) {
703
- return t.value ||= n(i || e), i && t.value.setOptions(i), t.value.parse(r);
1094
+ function parse(markdown, options) {
1095
+ if (!parser.value) parser.value = createParser(options || initialOptions);
1096
+ if (options) parser.value.setOptions(options);
1097
+ return parser.value.parse(markdown);
704
1098
  }
705
- function i(e) {
706
- t.value = n(e);
1099
+ function resetParser(options) {
1100
+ parser.value = createParser(options);
707
1101
  }
708
1102
  return {
709
- parser: t,
710
- parse: r,
711
- resetParser: i
1103
+ parser,
1104
+ parse,
1105
+ resetParser
712
1106
  };
713
1107
  }
714
1108
  //#endregion
715
1109
  //#region src/XMarkdown/composables/useRenderer.ts
716
- function ce(e) {
717
- let t = _(null);
718
- function n(e) {
719
- return new Z(e);
1110
+ function useRenderer(initialOptions) {
1111
+ const renderer = shallowRef(null);
1112
+ function createRenderer(options) {
1113
+ return new VueRenderer(options);
720
1114
  }
721
- function r(r, i) {
722
- return t.value ||= n(i || e), i && t.value.setOptions(i), t.value.render(r);
1115
+ function render(html, options) {
1116
+ if (!renderer.value) renderer.value = createRenderer(options || initialOptions);
1117
+ if (options) renderer.value.setOptions(options);
1118
+ return renderer.value.render(html);
723
1119
  }
724
- function i(e) {
725
- t.value = n(e);
1120
+ function resetRenderer(options) {
1121
+ renderer.value = createRenderer(options);
726
1122
  }
727
1123
  return {
728
- renderer: t,
729
- render: r,
730
- resetRenderer: i
1124
+ renderer,
1125
+ render,
1126
+ resetRenderer
731
1127
  };
732
1128
  }
733
1129
  //#endregion
734
1130
  //#region src/XMarkdown/utils/tail.ts
735
- var $ = "▋";
736
- function le(e) {
737
- return e ? e === !0 ? $ : e.content || $ : null;
1131
+ var DEFAULT_TAIL_CONTENT = "▋";
1132
+ function resolveTailContent(tail) {
1133
+ if (!tail) return null;
1134
+ if (tail === true) return DEFAULT_TAIL_CONTENT;
1135
+ return tail.content || DEFAULT_TAIL_CONTENT;
738
1136
  }
739
1137
  //#endregion
740
- export { q as AnimationText, j as DebugPanel, K as Parser, M as TailIndicator, Z as VueRenderer, se as XMarkdown, X as detectUnclosedComponentTags, le as resolveTailContent, Q as useParser, ce as useRenderer, H as useStreaming, W as useTail };
1138
+ export { AnimationText_default as AnimationText, DebugPanel_default as DebugPanel, Parser, TailIndicator_default as TailIndicator, VueRenderer, XMarkdown_default as XMarkdown, detectUnclosedComponentTags, resolveTailContent, useParser, useRenderer, useStreaming, useTail };