@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.
- package/dist/XMarkdown/components/AnimationText.vue.d.ts +0 -1
- package/dist/XMarkdown/components/DebugPanel.vue.d.ts +0 -1
- package/dist/XMarkdown/components/TailIndicator.vue.d.ts +0 -1
- package/dist/XMarkdown/components/index.d.ts +0 -1
- package/dist/XMarkdown/composables/useParser.d.ts +0 -1
- package/dist/XMarkdown/composables/useRenderer.d.ts +0 -1
- package/dist/XMarkdown/composables/useStreaming.d.ts +0 -1
- package/dist/XMarkdown/composables/useTail.d.ts +0 -1
- package/dist/XMarkdown/core/Parser.d.ts +5 -2
- package/dist/XMarkdown/core/VueRenderer.d.ts +0 -1
- package/dist/XMarkdown/core/detectUnclosedComponentTags.d.ts +2 -2
- package/dist/XMarkdown/index.vue.d.ts +0 -1
- package/dist/XMarkdown/interface.d.ts +0 -1
- package/dist/XMarkdown/utils/tail.d.ts +0 -1
- package/dist/index.css +251 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +868 -470
- package/dist/plugins/Latex/index.d.ts +0 -1
- package/dist/plugins/Latex/index.js +48 -42
- package/package.json +3 -2
- package/dist/XMarkdown/components/AnimationText.vue.d.ts.map +0 -1
- package/dist/XMarkdown/components/DebugPanel.vue.d.ts.map +0 -1
- package/dist/XMarkdown/components/TailIndicator.vue.d.ts.map +0 -1
- package/dist/XMarkdown/components/index.d.ts.map +0 -1
- package/dist/XMarkdown/composables/useParser.d.ts.map +0 -1
- package/dist/XMarkdown/composables/useRenderer.d.ts.map +0 -1
- package/dist/XMarkdown/composables/useStreaming.d.ts.map +0 -1
- package/dist/XMarkdown/composables/useTail.d.ts.map +0 -1
- package/dist/XMarkdown/core/Parser.d.ts.map +0 -1
- package/dist/XMarkdown/core/VueRenderer.d.ts.map +0 -1
- package/dist/XMarkdown/core/detectUnclosedComponentTags.d.ts.map +0 -1
- package/dist/XMarkdown/index.vue.d.ts.map +0 -1
- package/dist/XMarkdown/interface.d.ts.map +0 -1
- package/dist/XMarkdown/utils/tail.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/plugins/Latex/index.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,424 +1,609 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { 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
|
|
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
|
-
}
|
|
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(
|
|
12
|
-
|
|
18
|
+
setup(__props) {
|
|
19
|
+
const isDragging = ref(false);
|
|
20
|
+
const position = ref({
|
|
13
21
|
x: 20,
|
|
14
22
|
y: 20
|
|
15
|
-
})
|
|
23
|
+
});
|
|
24
|
+
const dragOffset = ref({
|
|
16
25
|
x: 0,
|
|
17
26
|
y: 0
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
30
|
-
fps:
|
|
31
|
-
memory:
|
|
49
|
+
snapshots.value.push({
|
|
50
|
+
fps: fps.value,
|
|
51
|
+
memory: memory.value,
|
|
32
52
|
timestamp: Date.now()
|
|
33
|
-
})
|
|
53
|
+
});
|
|
54
|
+
if (snapshots.value.length > maxSnapshots) snapshots.value.shift();
|
|
34
55
|
}
|
|
35
|
-
|
|
56
|
+
animationFrameId = requestAnimationFrame(monitor);
|
|
36
57
|
}
|
|
37
|
-
|
|
58
|
+
animationFrameId = requestAnimationFrame(monitor);
|
|
38
59
|
}
|
|
39
|
-
function
|
|
40
|
-
|
|
60
|
+
function stopMonitoring() {
|
|
61
|
+
if (animationFrameId !== null) {
|
|
62
|
+
cancelAnimationFrame(animationFrameId);
|
|
63
|
+
animationFrameId = null;
|
|
64
|
+
}
|
|
41
65
|
}
|
|
42
|
-
function
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
|
55
|
-
|
|
80
|
+
function handleMouseUp() {
|
|
81
|
+
isDragging.value = false;
|
|
56
82
|
}
|
|
57
|
-
function
|
|
58
|
-
|
|
83
|
+
function getFpsColor(fpsValue) {
|
|
84
|
+
if (fpsValue >= 55) return "#52c41a";
|
|
85
|
+
if (fpsValue >= 40) return "#faad14";
|
|
86
|
+
return "#ff4d4f";
|
|
59
87
|
}
|
|
60
|
-
function
|
|
61
|
-
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
},
|
|
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(
|
|
95
|
-
return (
|
|
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"]])
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
[
|
|
121
|
-
tokenType:
|
|
122
|
-
isStartOfToken: (
|
|
123
|
-
isStreamingValid: (
|
|
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
|
-
[
|
|
126
|
-
tokenType:
|
|
127
|
-
isStartOfToken: (
|
|
128
|
-
isStreamingValid: (
|
|
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
|
-
[
|
|
131
|
-
tokenType:
|
|
132
|
-
isStartOfToken: (
|
|
133
|
-
isStreamingValid: (
|
|
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
|
-
[
|
|
136
|
-
tokenType:
|
|
137
|
-
isStartOfToken: (
|
|
138
|
-
isStreamingValid: (
|
|
139
|
-
getCommitPrefix: (
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
[
|
|
145
|
-
tokenType:
|
|
146
|
-
isStartOfToken: (
|
|
147
|
-
isStreamingValid:
|
|
219
|
+
[StreamCacheTokenType.Table]: {
|
|
220
|
+
tokenType: StreamCacheTokenType.Table,
|
|
221
|
+
isStartOfToken: (markdown) => markdown.startsWith("|"),
|
|
222
|
+
isStreamingValid: isTableInComplete
|
|
148
223
|
},
|
|
149
|
-
[
|
|
150
|
-
tokenType:
|
|
151
|
-
isStartOfToken: (
|
|
152
|
-
isStreamingValid: (
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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 (
|
|
163
|
-
|
|
164
|
-
if (
|
|
165
|
-
|
|
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
|
-
|
|
246
|
+
commitCache(cache);
|
|
169
247
|
}
|
|
170
|
-
}
|
|
248
|
+
};
|
|
249
|
+
var recognizeHandlers = Object.values(tokenRecognizerMap).filter((recognizer) => Boolean(recognizer));
|
|
250
|
+
var getInitialCache = () => ({
|
|
171
251
|
pending: "",
|
|
172
|
-
token:
|
|
252
|
+
token: StreamCacheTokenType.Text,
|
|
173
253
|
processedLength: 0,
|
|
174
254
|
completeMarkdown: ""
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
-
|
|
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
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
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
|
|
197
|
-
}
|
|
301
|
+
return result;
|
|
302
|
+
};
|
|
303
|
+
var safeEncodeURIComponent = (str) => {
|
|
198
304
|
try {
|
|
199
|
-
return encodeURIComponent(
|
|
200
|
-
} catch (
|
|
201
|
-
|
|
305
|
+
return encodeURIComponent(str);
|
|
306
|
+
} catch (error) {
|
|
307
|
+
if (error instanceof URIError) return encodeURIComponent(sanitizeForURIComponent(str));
|
|
308
|
+
return "";
|
|
202
309
|
}
|
|
203
310
|
};
|
|
204
|
-
function
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if (
|
|
210
|
-
|
|
211
|
-
if (
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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
|
-
|
|
227
|
-
for (
|
|
228
|
-
|
|
229
|
-
|
|
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 (
|
|
345
|
+
if (cache.token === StreamCacheTokenType.Text) for (const handler of recognizeHandlers) recognize(cache, handler.tokenType);
|
|
233
346
|
else {
|
|
234
|
-
|
|
235
|
-
if (
|
|
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
|
-
|
|
351
|
+
if (cache.token === StreamCacheTokenType.Text) commitCache(cache);
|
|
238
352
|
}
|
|
239
|
-
|
|
240
|
-
|
|
353
|
+
const incompletePlaceholder = handleIncompleteMarkdown(cache, opts);
|
|
354
|
+
processedContent.value = cache.completeMarkdown + (incompletePlaceholder || "");
|
|
241
355
|
}
|
|
242
|
-
function
|
|
243
|
-
|
|
356
|
+
function reset() {
|
|
357
|
+
streamCache.value = getInitialCache();
|
|
358
|
+
processedContent.value = "";
|
|
244
359
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
if (!
|
|
248
|
-
|
|
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:
|
|
251
|
-
processedLength:
|
|
252
|
-
completeMarkdown:
|
|
366
|
+
token: StreamCacheTokenType.Text,
|
|
367
|
+
processedLength: newContent.length,
|
|
368
|
+
completeMarkdown: newContent
|
|
253
369
|
};
|
|
254
370
|
return;
|
|
255
371
|
}
|
|
256
|
-
|
|
257
|
-
}, { immediate:
|
|
258
|
-
|
|
259
|
-
|
|
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
|
|
265
|
-
function
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
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
|
|
272
|
-
tailComponent:
|
|
273
|
-
|
|
274
|
-
|
|
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:
|
|
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
|
|
404
|
+
var escapeReplacements = {
|
|
282
405
|
"&": "&",
|
|
283
406
|
"<": "<",
|
|
284
407
|
">": ">",
|
|
285
408
|
"\"": """,
|
|
286
409
|
"'": "'"
|
|
287
410
|
};
|
|
288
|
-
function
|
|
289
|
-
|
|
411
|
+
function escapeHtml(html) {
|
|
412
|
+
if (/[&<>"']/.test(html)) return html.replace(/[&<>"']/g, (ch) => escapeReplacements[ch] || ch);
|
|
413
|
+
return html;
|
|
290
414
|
}
|
|
291
|
-
var
|
|
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 =
|
|
295
|
-
|
|
419
|
+
injectTail = false;
|
|
420
|
+
codeBlockStates = [];
|
|
421
|
+
codeBlockStateIndex = 0;
|
|
422
|
+
constructor(options = {}) {
|
|
296
423
|
this.options = {
|
|
297
|
-
openLinksInNewTab:
|
|
298
|
-
paragraphTag:
|
|
299
|
-
injectTail:
|
|
300
|
-
protectCustomTags:
|
|
301
|
-
escapeRawHtml:
|
|
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:
|
|
304
|
-
...
|
|
430
|
+
gfm: true,
|
|
431
|
+
...options.config
|
|
305
432
|
},
|
|
306
|
-
components:
|
|
307
|
-
streamStatus:
|
|
308
|
-
codeBlockStatus:
|
|
309
|
-
}
|
|
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(
|
|
440
|
+
updateMarkedConfig(config) {
|
|
312
441
|
this.options.config = {
|
|
313
442
|
...this.options.config,
|
|
314
|
-
...
|
|
315
|
-
}
|
|
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: (
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
return `<
|
|
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
|
-
|
|
329
|
-
|
|
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
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
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
|
-
|
|
339
|
-
return this.
|
|
499
|
+
getCodeBlockState(lang) {
|
|
500
|
+
return this.options.codeBlockStatus[lang] ?? this.options.streamStatus;
|
|
340
501
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
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
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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 (
|
|
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
|
-
}
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
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(
|
|
390
|
-
|
|
391
|
-
Object.assign(this.options,
|
|
556
|
+
setOptions(options) {
|
|
557
|
+
const { config, ...rest } = options;
|
|
558
|
+
Object.assign(this.options, rest);
|
|
559
|
+
if (config) this.updateMarkedConfig(config);
|
|
392
560
|
}
|
|
393
|
-
}
|
|
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(
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
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
|
-
|
|
409
|
-
|
|
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
|
-
|
|
412
|
-
|
|
413
|
-
animation: `x-markdown-fade-in ${
|
|
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 (
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
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
|
-
})
|
|
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
|
-
])
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
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
|
-
|
|
463
|
-
|
|
464
|
-
})
|
|
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
|
|
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(
|
|
793
|
+
constructor(options = {}) {
|
|
471
794
|
this.options = {
|
|
472
|
-
components:
|
|
473
|
-
enableAnimation:
|
|
795
|
+
components: options.components ?? {},
|
|
796
|
+
enableAnimation: options.enableAnimation ?? true,
|
|
474
797
|
animationConfig: {
|
|
475
|
-
fadeDuration:
|
|
476
|
-
easing:
|
|
798
|
+
fadeDuration: options.animationConfig?.fadeDuration ?? DEFAULT_ANIMATION_DURATION,
|
|
799
|
+
easing: options.animationConfig?.easing ?? "ease-in-out"
|
|
477
800
|
}
|
|
478
801
|
};
|
|
479
802
|
}
|
|
480
|
-
render(
|
|
481
|
-
|
|
482
|
-
|
|
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(
|
|
485
|
-
|
|
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
|
-
...
|
|
844
|
+
...MATHML_TAGS
|
|
518
845
|
])];
|
|
519
|
-
return
|
|
520
|
-
ALLOWED_TAGS:
|
|
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(
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
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 (
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
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
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
return
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
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(
|
|
594
|
-
|
|
948
|
+
setOptions(options) {
|
|
949
|
+
if (options.components) this.options.components = {
|
|
595
950
|
...this.options.components,
|
|
596
|
-
...
|
|
597
|
-
}
|
|
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
|
-
...
|
|
600
|
-
}
|
|
956
|
+
...options.animationConfig
|
|
957
|
+
};
|
|
601
958
|
}
|
|
602
|
-
}
|
|
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:
|
|
968
|
+
config: { default: () => ({ gfm: true }) },
|
|
609
969
|
debug: {
|
|
610
970
|
type: Boolean,
|
|
611
|
-
default:
|
|
971
|
+
default: false
|
|
612
972
|
},
|
|
613
973
|
protectCustomTagNewlines: {
|
|
614
974
|
type: Boolean,
|
|
615
|
-
default:
|
|
975
|
+
default: true
|
|
616
976
|
},
|
|
617
977
|
escapeRawHtml: {
|
|
618
978
|
type: Boolean,
|
|
619
|
-
default:
|
|
979
|
+
default: false
|
|
620
980
|
},
|
|
621
981
|
className: {},
|
|
622
982
|
style: {},
|
|
623
983
|
openLinksInNewTab: {
|
|
624
984
|
type: Boolean,
|
|
625
|
-
default:
|
|
985
|
+
default: true
|
|
626
986
|
},
|
|
627
987
|
paragraphTag: { default: "p" }
|
|
628
988
|
},
|
|
629
|
-
setup(
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
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 () =>
|
|
1003
|
+
return () => h(resolvedTailComponent, { content });
|
|
637
1004
|
}
|
|
638
1005
|
});
|
|
639
1006
|
return {
|
|
640
|
-
...
|
|
641
|
-
"xmd-tail":
|
|
1007
|
+
...baseComponents,
|
|
1008
|
+
"xmd-tail": TailBridge
|
|
642
1009
|
};
|
|
643
|
-
})
|
|
1010
|
+
});
|
|
1011
|
+
const VNodeRenderer = defineComponent({
|
|
644
1012
|
name: "XmdVNodeRenderer",
|
|
645
1013
|
props: { node: {
|
|
646
1014
|
type: Object,
|
|
647
|
-
required:
|
|
1015
|
+
required: true
|
|
648
1016
|
} },
|
|
649
|
-
setup(
|
|
650
|
-
return () =>
|
|
1017
|
+
setup(props) {
|
|
1018
|
+
return () => props.node;
|
|
651
1019
|
}
|
|
652
|
-
})
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
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
|
-
|
|
673
|
-
openLinksInNewTab:
|
|
674
|
-
paragraphTag:
|
|
675
|
-
protectCustomTags:
|
|
676
|
-
escapeRawHtml:
|
|
677
|
-
})
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
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
|
|
698
|
-
|
|
699
|
-
function
|
|
700
|
-
return new
|
|
1089
|
+
function useParser(initialOptions) {
|
|
1090
|
+
const parser = shallowRef(null);
|
|
1091
|
+
function createParser(options) {
|
|
1092
|
+
return new Parser(options);
|
|
701
1093
|
}
|
|
702
|
-
function
|
|
703
|
-
|
|
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
|
|
706
|
-
|
|
1099
|
+
function resetParser(options) {
|
|
1100
|
+
parser.value = createParser(options);
|
|
707
1101
|
}
|
|
708
1102
|
return {
|
|
709
|
-
parser
|
|
710
|
-
parse
|
|
711
|
-
resetParser
|
|
1103
|
+
parser,
|
|
1104
|
+
parse,
|
|
1105
|
+
resetParser
|
|
712
1106
|
};
|
|
713
1107
|
}
|
|
714
1108
|
//#endregion
|
|
715
1109
|
//#region src/XMarkdown/composables/useRenderer.ts
|
|
716
|
-
function
|
|
717
|
-
|
|
718
|
-
function
|
|
719
|
-
return new
|
|
1110
|
+
function useRenderer(initialOptions) {
|
|
1111
|
+
const renderer = shallowRef(null);
|
|
1112
|
+
function createRenderer(options) {
|
|
1113
|
+
return new VueRenderer(options);
|
|
720
1114
|
}
|
|
721
|
-
function
|
|
722
|
-
|
|
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
|
|
725
|
-
|
|
1120
|
+
function resetRenderer(options) {
|
|
1121
|
+
renderer.value = createRenderer(options);
|
|
726
1122
|
}
|
|
727
1123
|
return {
|
|
728
|
-
renderer
|
|
729
|
-
render
|
|
730
|
-
resetRenderer
|
|
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
|
|
737
|
-
|
|
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 {
|
|
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 };
|