@antdv-next/x-markdown 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +15 -1
  3. package/dist/XMarkdown/components/AnimationText.js +5 -0
  4. package/dist/XMarkdown/components/AnimationText.vue_vue_type_script_setup_true_lang.js +42 -0
  5. package/dist/XMarkdown/components/DebugPanel.js +5 -0
  6. package/dist/XMarkdown/components/DebugPanel.vue_vue_type_script_setup_true_lang.js +128 -0
  7. package/dist/XMarkdown/components/TailIndicator.js +5 -0
  8. package/dist/XMarkdown/components/TailIndicator.vue_vue_type_script_setup_true_lang.js +14 -0
  9. package/dist/XMarkdown/components/index.js +4 -0
  10. package/dist/XMarkdown/composables/index.d.ts +4 -0
  11. package/dist/XMarkdown/composables/index.js +5 -0
  12. package/dist/XMarkdown/composables/useParser.js +24 -0
  13. package/dist/XMarkdown/composables/useRenderer.js +24 -0
  14. package/dist/XMarkdown/composables/useStreaming.js +215 -0
  15. package/dist/XMarkdown/composables/useTail.js +25 -0
  16. package/dist/XMarkdown/core/Parser.js +162 -0
  17. package/dist/XMarkdown/core/VueRenderer.js +223 -0
  18. package/dist/XMarkdown/core/detectUnclosedComponentTags.js +141 -0
  19. package/dist/XMarkdown/core/index.d.ts +3 -0
  20. package/dist/XMarkdown/core/index.js +4 -0
  21. package/dist/XMarkdown/index.d.ts +14 -0
  22. package/dist/XMarkdown/index.js +13 -0
  23. package/dist/XMarkdown/index.vue_vue_type_script_setup_true_lang.js +135 -0
  24. package/dist/XMarkdown/index2.js +5 -0
  25. package/dist/XMarkdown/interface.js +14 -0
  26. package/dist/XMarkdown/utils/tail.js +9 -0
  27. package/dist/env.d.js +0 -0
  28. package/dist/index.js +12 -1137
  29. package/package.json +9 -8
  30. package/{dist → themes}/index.css +0 -45
  31. /package/{dist/plugins → plugins}/Latex/index.d.ts +0 -0
  32. /package/{dist/plugins → plugins}/Latex/index.js +0 -0
  33. /package/{dist/themes → themes}/dark.css +0 -0
  34. /package/{dist/themes → themes}/light.css +0 -0
package/dist/index.js CHANGED
@@ -1,1138 +1,13 @@
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";
5
- //#region src/XMarkdown/components/DebugPanel.vue?vue&type=script&setup=true&lang.ts
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 = {
10
- class: "xmd-debug-chart",
11
- viewBox: "0 0 200 60"
12
- };
13
- var _hoisted_5 = ["d"];
14
- var maxSnapshots = 60;
15
- var DebugPanel_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
16
- __name: "DebugPanel",
17
- props: { className: {} },
18
- setup(__props) {
19
- const isDragging = ref(false);
20
- const position = ref({
21
- x: 20,
22
- y: 20
23
- });
24
- const dragOffset = ref({
25
- x: 0,
26
- y: 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;
48
- }
49
- snapshots.value.push({
50
- fps: fps.value,
51
- memory: memory.value,
52
- timestamp: Date.now()
53
- });
54
- if (snapshots.value.length > maxSnapshots) snapshots.value.shift();
55
- }
56
- animationFrameId = requestAnimationFrame(monitor);
57
- }
58
- animationFrameId = requestAnimationFrame(monitor);
59
- }
60
- function stopMonitoring() {
61
- if (animationFrameId !== null) {
62
- cancelAnimationFrame(animationFrameId);
63
- animationFrameId = null;
64
- }
65
- }
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
71
- };
72
- }
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
- };
79
- }
80
- function handleMouseUp() {
81
- isDragging.value = false;
82
- }
83
- function getFpsColor(fpsValue) {
84
- if (fpsValue >= 55) return "#52c41a";
85
- if (fpsValue >= 40) return "#faad14";
86
- return "#ff4d4f";
87
- }
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 ")}`;
96
- }
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({
146
- __name: "TailIndicator",
147
- props: { content: { default: "▋" } },
148
- setup(__props) {
149
- return (_ctx, _cache) => {
150
- return openBlock(), createElementBlock("span", _hoisted_1, toDisplayString(__props.content), 1);
151
- };
152
- }
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 = {
170
- image: [/^!\[[^\]\r\n]{0,1000}$/, /^!\[[^\r\n]{0,1000}\]\(*[^)\r\n]{0,1000}$/],
171
- link: [/^\[[^\]\r\n]{0,1000}$/, /^\[[^\r\n]{0,1000}\]\(*[^)\r\n]{0,1000}$/],
172
- html: [/^<\/$/, /^<\/?[a-zA-Z][a-zA-Z0-9-]{0,100}[^>\r\n]{0,1000}$/],
173
- commonEmphasis: [/^(\*{1,3}|_{1,3})(?!\s)(?!.*\1$)[^\r\n]{0,1000}$/],
174
- list: [/^[-+*]\s{0,3}$/, /^[-+*]\s{1,3}(\*{1,3}|_{1,3})(?!\s)(?!.*\1$)[^\r\n]{0,1000}$/],
175
- "inline-code": [/^`[^`\r\n]{0,300}$/]
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))
193
- },
194
- [StreamCacheTokenType.Image]: {
195
- tokenType: StreamCacheTokenType.Image,
196
- isStartOfToken: (markdown) => markdown.startsWith("!"),
197
- isStreamingValid: (markdown) => STREAM_INCOMPLETE_REGEX.image.some((re) => re.test(markdown))
198
- },
199
- [StreamCacheTokenType.Html]: {
200
- tokenType: StreamCacheTokenType.Html,
201
- isStartOfToken: (markdown) => markdown.startsWith("<"),
202
- isStreamingValid: (markdown) => STREAM_INCOMPLETE_REGEX.html.some((re) => re.test(markdown))
203
- },
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))
208
- },
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;
217
- }
218
- },
219
- [StreamCacheTokenType.Table]: {
220
- tokenType: StreamCacheTokenType.Table,
221
- isStartOfToken: (markdown) => markdown.startsWith("|"),
222
- isStreamingValid: isTableInComplete
223
- },
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;
236
- return;
237
- }
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;
244
- return;
245
- }
246
- commitCache(cache);
247
- }
248
- };
249
- var recognizeHandlers = Object.values(tokenRecognizerMap).filter((recognizer) => Boolean(recognizer));
250
- var getInitialCache = () => ({
251
- pending: "",
252
- token: StreamCacheTokenType.Text,
253
- processedLength: 0,
254
- completeMarkdown: ""
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;
280
- continue;
281
- }
282
- if (char === fenceChar && len >= fenceLen && /^\s*$/.test(after) && (isFinalChunk || i < lines.length - 1)) {
283
- inFenced = false;
284
- fenceChar = "";
285
- fenceLen = 0;
286
- }
287
- }
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];
300
- }
301
- return result;
302
- };
303
- var safeEncodeURIComponent = (str) => {
304
- try {
305
- return encodeURIComponent(str);
306
- } catch (error) {
307
- if (error instanceof URIError) return encodeURIComponent(sanitizeForURIComponent(str));
308
- return "";
309
- }
310
- };
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();
327
- return;
328
- }
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 || "");
336
- return;
337
- }
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);
343
- continue;
344
- }
345
- if (cache.token === StreamCacheTokenType.Text) for (const handler of recognizeHandlers) recognize(cache, handler.tokenType);
346
- else {
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);
350
- }
351
- if (cache.token === StreamCacheTokenType.Text) commitCache(cache);
352
- }
353
- const incompletePlaceholder = handleIncompleteMarkdown(cache, opts);
354
- processedContent.value = cache.completeMarkdown + (incompletePlaceholder || "");
355
- }
356
- function reset() {
357
- streamCache.value = getInitialCache();
358
- processedContent.value = "";
359
- }
360
- watch([content, () => streaming.value?.hasNextChunk], ([newContent, hasNextChunk]) => {
361
- const opts = streaming.value;
362
- if (!Boolean(hasNextChunk)) {
363
- processedContent.value = newContent;
364
- streamCache.value = {
365
- pending: "",
366
- token: StreamCacheTokenType.Text,
367
- processedLength: newContent.length,
368
- completeMarkdown: newContent
369
- };
370
- return;
371
- }
372
- processStreaming(newContent, opts);
373
- }, { immediate: true });
374
- return {
375
- processedContent,
376
- reset
377
- };
378
- }
379
- //#endregion
380
- //#region src/XMarkdown/composables/useTail.ts
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;
388
- });
389
- return {
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;
396
- }),
397
- showTail: computed(() => {
398
- return streaming.value?.hasNextChunk && tailContent.value !== null;
399
- })
400
- };
401
- }
402
- //#endregion
403
- //#region src/XMarkdown/core/Parser.ts
404
- var escapeReplacements = {
405
- "&": "&amp;",
406
- "<": "&lt;",
407
- ">": "&gt;",
408
- "\"": "&quot;",
409
- "'": "&#39;"
410
- };
411
- function escapeHtml(html) {
412
- if (/[&<>"']/.test(html)) return html.replace(/[&<>"']/g, (ch) => escapeReplacements[ch] || ch);
413
- return html;
414
- }
415
- var Parser = class Parser {
416
- static COMPLETE_FENCED_CODE = /^ {0,3}(`{3,}|~{3,})([\s\S]*?)\n {0,3}\1[ \n\t]*$/;
417
- options;
418
- markdownInstance;
419
- injectTail = false;
420
- codeBlockStates = [];
421
- codeBlockStateIndex = 0;
422
- constructor(options = {}) {
423
- this.options = {
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,
429
- config: {
430
- gfm: true,
431
- ...options.config
432
- },
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();
439
- }
440
- updateMarkedConfig(config) {
441
- this.options.config = {
442
- ...this.options.config,
443
- ...config
444
- };
445
- this.markdownInstance = new Marked(this.options.config);
446
- this.configureRenderers();
447
- }
448
- configureRenderers() {
449
- this.markdownInstance.use({ renderer: {
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>`;
464
- }
465
- } });
466
- }
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);
493
- }
494
- consumeCodeBlockState(lang) {
495
- const nextState = this.codeBlockStates[this.codeBlockStateIndex];
496
- this.codeBlockStateIndex += 1;
497
- return nextState ?? this.getCodeBlockState(lang);
498
- }
499
- getCodeBlockState(lang) {
500
- return this.options.codeBlockStatus[lang] ?? this.options.streamStatus;
501
- }
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);
529
- });
530
- }
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;
541
- continue;
542
- }
543
- if (node.nodeType !== Node.ELEMENT_NODE) continue;
544
- const nested = findLastMeaningfulNode(node);
545
- if (nested) return nested;
546
- return node;
547
- }
548
- return null;
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;
555
- }
556
- setOptions(options) {
557
- const { config, ...rest } = options;
558
- Object.assign(this.options, rest);
559
- if (config) this.updateMarkedConfig(config);
560
- }
561
- };
562
- //#endregion
563
- //#region src/XMarkdown/components/AnimationText.vue
564
- var AnimationText_default = /* @__PURE__ */ defineComponent({
565
- __name: "AnimationText",
566
- props: {
567
- text: {},
568
- fadeDuration: { default: 200 },
569
- easing: { default: "ease-in-out" }
570
- },
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;
580
- return;
581
- }
582
- const delta = nextText.slice(previousText.value.length);
583
- if (!delta) return;
584
- chunks.value = [...chunks.value, delta];
585
- previousText.value = nextText;
586
- }
587
- watch(() => props.text, updateChunks, { immediate: true });
588
- const animationStyle = computed(() => ({
589
- animation: `x-markdown-fade-in ${props.fadeDuration}ms ${props.easing} forwards`,
590
- color: "inherit"
591
- }));
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
- };
600
- }
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([
607
- "area",
608
- "base",
609
- "br",
610
- "col",
611
- "embed",
612
- "hr",
613
- "img",
614
- "input",
615
- "link",
616
- "meta",
617
- "param",
618
- "source",
619
- "track",
620
- "wbr"
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++;
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);
734
- }
735
- pos = openingTag.endPos;
736
- }
737
- for (const [tagName, pendingIndexes] of Object.entries(openTagIndexes)) pendingIndexes.forEach((instance) => {
738
- unclosedTags.add(getTagInstanceId(tagName, instance));
739
- });
740
- return unclosedTags;
741
- }
742
- //#endregion
743
- //#region src/XMarkdown/core/VueRenderer.ts
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 {
792
- options;
793
- constructor(options = {}) {
794
- this.options = {
795
- components: options.components ?? {},
796
- enableAnimation: options.enableAnimation ?? true,
797
- animationConfig: {
798
- fadeDuration: options.animationConfig?.fadeDuration ?? DEFAULT_ANIMATION_DURATION,
799
- easing: options.animationConfig?.easing ?? "ease-in-out"
800
- }
801
- };
802
- }
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);
810
- }
811
- sanitize(html) {
812
- const allowedTags = [...new Set([
813
- ...Object.keys(this.options.components),
814
- "p",
815
- "br",
816
- "span",
817
- "div",
818
- "a",
819
- "img",
820
- "ul",
821
- "ol",
822
- "li",
823
- "h1",
824
- "h2",
825
- "h3",
826
- "h4",
827
- "h5",
828
- "h6",
829
- "blockquote",
830
- "pre",
831
- "code",
832
- "em",
833
- "strong",
834
- "del",
835
- "ins",
836
- "table",
837
- "thead",
838
- "tbody",
839
- "tr",
840
- "th",
841
- "td",
842
- "hr",
843
- "xmd-tail",
844
- ...MATHML_TAGS
845
- ])];
846
- return DOMPurify.sanitize(html, {
847
- ALLOWED_TAGS: allowedTags,
848
- ALLOWED_ATTR: [
849
- "class",
850
- "style",
851
- "aria-hidden",
852
- "aria-label",
853
- "role",
854
- "xmlns",
855
- "encoding",
856
- "href",
857
- "src",
858
- "title",
859
- "alt",
860
- "target",
861
- "rel",
862
- "data-lang",
863
- "data-block",
864
- "data-state",
865
- "data-raw",
866
- "data-icon",
867
- "data-description",
868
- "icon",
869
- "description"
870
- ]
871
- });
872
- }
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);
892
- }
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 });
906
- }
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,
944
- fadeDuration: this.options.animationConfig.fadeDuration,
945
- easing: this.options.animationConfig.easing
946
- });
947
- }
948
- setOptions(options) {
949
- if (options.components) this.options.components = {
950
- ...this.options.components,
951
- ...options.components
952
- };
953
- if (options.enableAnimation !== void 0) this.options.enableAnimation = options.enableAnimation;
954
- if (options.animationConfig) this.options.animationConfig = {
955
- ...this.options.animationConfig,
956
- ...options.animationConfig
957
- };
958
- }
959
- };
960
- //#endregion
961
- //#region src/XMarkdown/index.vue
962
- var XMarkdown_default = /* @__PURE__ */ defineComponent({
963
- __name: "index",
964
- props: {
965
- content: { default: "" },
966
- components: { default: () => ({}) },
967
- streaming: { default: void 0 },
968
- config: { default: () => ({ gfm: true }) },
969
- debug: {
970
- type: Boolean,
971
- default: false
972
- },
973
- protectCustomTagNewlines: {
974
- type: Boolean,
975
- default: true
976
- },
977
- escapeRawHtml: {
978
- type: Boolean,
979
- default: false
980
- },
981
- className: {},
982
- style: {},
983
- openLinksInNewTab: {
984
- type: Boolean,
985
- default: true
986
- },
987
- paragraphTag: { default: "p" }
988
- },
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({
1001
- name: "XmdTailBridge",
1002
- setup() {
1003
- return () => h(resolvedTailComponent, { content });
1004
- }
1005
- });
1006
- return {
1007
- ...baseComponents,
1008
- "xmd-tail": TailBridge
1009
- };
1010
- });
1011
- const VNodeRenderer = defineComponent({
1012
- name: "XmdVNodeRenderer",
1013
- props: { node: {
1014
- type: Object,
1015
- required: true
1016
- } },
1017
- setup(props) {
1018
- return () => props.node;
1019
- }
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
1051
- ], () => {
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
- };
1085
- }
1086
- });
1087
- //#endregion
1088
- //#region src/XMarkdown/composables/useParser.ts
1089
- function useParser(initialOptions) {
1090
- const parser = shallowRef(null);
1091
- function createParser(options) {
1092
- return new Parser(options);
1093
- }
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);
1098
- }
1099
- function resetParser(options) {
1100
- parser.value = createParser(options);
1101
- }
1102
- return {
1103
- parser,
1104
- parse,
1105
- resetParser
1106
- };
1107
- }
1108
- //#endregion
1109
- //#region src/XMarkdown/composables/useRenderer.ts
1110
- function useRenderer(initialOptions) {
1111
- const renderer = shallowRef(null);
1112
- function createRenderer(options) {
1113
- return new VueRenderer(options);
1114
- }
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);
1119
- }
1120
- function resetRenderer(options) {
1121
- renderer.value = createRenderer(options);
1122
- }
1123
- return {
1124
- renderer,
1125
- render,
1126
- resetRenderer
1127
- };
1128
- }
1129
- //#endregion
1130
- //#region src/XMarkdown/utils/tail.ts
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;
1136
- }
1137
- //#endregion
1
+ import AnimationText_default from "./XMarkdown/components/AnimationText.js";
2
+ import DebugPanel_default from "./XMarkdown/components/DebugPanel.js";
3
+ import TailIndicator_default from "./XMarkdown/components/TailIndicator.js";
4
+ import { useStreaming } from "./XMarkdown/composables/useStreaming.js";
5
+ import { Parser } from "./XMarkdown/core/Parser.js";
6
+ import { useParser } from "./XMarkdown/composables/useParser.js";
7
+ import { detectUnclosedComponentTags } from "./XMarkdown/core/detectUnclosedComponentTags.js";
8
+ import { VueRenderer } from "./XMarkdown/core/VueRenderer.js";
9
+ import { useRenderer } from "./XMarkdown/composables/useRenderer.js";
10
+ import { useTail } from "./XMarkdown/composables/useTail.js";
11
+ import XMarkdown_default from "./XMarkdown/index2.js";
12
+ import { resolveTailContent } from "./XMarkdown/utils/tail.js";
1138
13
  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 };