@antdv-next/x-markdown 0.1.4 → 0.3.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.
- package/dist/XMarkdown/components/AnimationText.vue.d.ts +6 -0
- package/dist/XMarkdown/components/AnimationText.vue_vue_type_script_setup_true_lang.js +58 -2
- package/dist/XMarkdown/components/Section.js +5 -0
- package/dist/XMarkdown/components/Section.vue.d.ts +76 -0
- package/dist/XMarkdown/components/Section.vue_vue_type_script_lang.js +54 -0
- package/dist/XMarkdown/composables/index.d.ts +2 -1
- package/dist/XMarkdown/composables/index.js +3 -2
- package/dist/XMarkdown/composables/useStreaming.d.ts +37 -1
- package/dist/XMarkdown/composables/useStreaming.js +449 -34
- package/dist/XMarkdown/composables/useTypewriter.d.ts +11 -0
- package/dist/XMarkdown/composables/useTypewriter.js +378 -0
- package/dist/XMarkdown/core/Parser.d.ts +15 -0
- package/dist/XMarkdown/core/Parser.js +42 -14
- package/dist/XMarkdown/core/VueRenderer.js +16 -9
- package/dist/XMarkdown/core/detectUnclosedComponentTags.d.ts +12 -0
- package/dist/XMarkdown/core/detectUnclosedComponentTags.js +240 -6
- package/dist/XMarkdown/core/index.js +1 -1
- package/dist/XMarkdown/index.d.ts +6 -2
- package/dist/XMarkdown/index.js +5 -3
- package/dist/XMarkdown/index.vue.d.ts +1 -1
- package/dist/XMarkdown/index.vue_vue_type_script_setup_true_lang.js +64 -30
- package/dist/XMarkdown/interface.d.ts +241 -14
- package/dist/XMarkdown/utils/streaming.d.ts +6 -0
- package/dist/XMarkdown/utils/streaming.js +32 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.js +5 -3
- package/package.json +2 -2
- package/plugins/Latex/index.js +8 -2
|
@@ -36,7 +36,6 @@ var parseClosingTag = (html, pos) => {
|
|
|
36
36
|
if (html[pos + 1] !== "/") return null;
|
|
37
37
|
let scanPos = pos + 2;
|
|
38
38
|
let tagName = "";
|
|
39
|
-
while (scanPos < html.length && WHITESPACE_REGEX.test(html[scanPos])) scanPos++;
|
|
40
39
|
while (scanPos < html.length && TAG_NAME_CHAR_REGEX.test(html[scanPos])) {
|
|
41
40
|
tagName += html[scanPos];
|
|
42
41
|
scanPos++;
|
|
@@ -56,6 +55,7 @@ var parseOpeningTag = (html, pos) => {
|
|
|
56
55
|
scanPos++;
|
|
57
56
|
}
|
|
58
57
|
if (!tagName) return null;
|
|
58
|
+
if (scanPos < html.length && html[scanPos] !== ">" && html[scanPos] !== "/" && !WHITESPACE_REGEX.test(html[scanPos])) return null;
|
|
59
59
|
let foundEnd = false;
|
|
60
60
|
let isSelfClosing = false;
|
|
61
61
|
while (scanPos < html.length) {
|
|
@@ -68,10 +68,6 @@ var parseOpeningTag = (html, pos) => {
|
|
|
68
68
|
const quoteChar = html[scanPos];
|
|
69
69
|
scanPos++;
|
|
70
70
|
while (scanPos < html.length) {
|
|
71
|
-
if (html[scanPos] === "\\" && scanPos + 1 < html.length) {
|
|
72
|
-
scanPos += 2;
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
71
|
if (html[scanPos] === quoteChar) {
|
|
76
72
|
scanPos++;
|
|
77
73
|
break;
|
|
@@ -137,5 +133,243 @@ function detectUnclosedComponentTags(html, componentNames) {
|
|
|
137
133
|
});
|
|
138
134
|
return unclosedTags;
|
|
139
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Line-level fenced-code tracking with the same rules as feedFenceState in
|
|
138
|
+
* useStreaming: a fence is a run of >= 3 backticks or tildes indented by up
|
|
139
|
+
* to three spaces, and a closing run needs the same character, at least the
|
|
140
|
+
* opening run's length and a whitespace-only tail. Tags inside fenced code
|
|
141
|
+
* are code, not HTML — without this, a JSX snippet or `#include <vector>`
|
|
142
|
+
* would look like an open container and veto every later split.
|
|
143
|
+
*/
|
|
144
|
+
var classifyRawScanLine = (line, fence) => {
|
|
145
|
+
let pos = 0;
|
|
146
|
+
let indent = 0;
|
|
147
|
+
while (indent < 3 && line[pos] === " ") {
|
|
148
|
+
indent += 1;
|
|
149
|
+
pos += 1;
|
|
150
|
+
}
|
|
151
|
+
const marker = line[pos];
|
|
152
|
+
let runLen = 0;
|
|
153
|
+
if (marker === "`" || marker === "~") while (line[pos + runLen] === marker) runLen += 1;
|
|
154
|
+
if (runLen < 3) return;
|
|
155
|
+
if (!fence.inFence) {
|
|
156
|
+
if (marker === "`" && line.slice(pos + runLen).includes("`")) return;
|
|
157
|
+
fence.inFence = true;
|
|
158
|
+
fence.fenceChar = marker;
|
|
159
|
+
fence.fenceLen = runLen;
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (marker === fence.fenceChar && runLen >= fence.fenceLen && line.slice(pos + runLen).trim() === "") {
|
|
163
|
+
fence.inFence = false;
|
|
164
|
+
fence.fenceChar = "";
|
|
165
|
+
fence.fenceLen = 0;
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
/**
|
|
169
|
+
* Tag names whose line-leading `<name` (or, for the type-6 names, `</name`)
|
|
170
|
+
* starts an HTML block that *interrupts a paragraph*: CommonMark's type-6 list.
|
|
171
|
+
* Derived by asking marked rather than from memory — `span`, `em`, `a`, `svg`,
|
|
172
|
+
* `math` and the other inline names are deliberately absent, because a line
|
|
173
|
+
* starting with one of those is paragraph text that a code span may cross.
|
|
174
|
+
*/
|
|
175
|
+
var PARAGRAPH_INTERRUPTING_TAGS = new Set("address article aside base basefont blockquote body caption center col colgroup dd details dialog dir div dl dt fieldset figcaption figure footer form frame frameset h1 h2 h3 h4 h5 h6 head header hr html iframe legend li link main menu menuitem nav noframes ol optgroup option p param search section summary table tbody td tfoot th thead title tr track ul".split(" "));
|
|
176
|
+
/** Type-1 tags interrupt as openers only; their closing tags start nothing. */
|
|
177
|
+
var BLOCK_OPENER_TAGS = /* @__PURE__ */ new Set([
|
|
178
|
+
"pre",
|
|
179
|
+
"script",
|
|
180
|
+
"style",
|
|
181
|
+
"textarea"
|
|
182
|
+
]);
|
|
183
|
+
/**
|
|
184
|
+
* Whether a `<` at `pos` begins an HTML block that interrupts the paragraph a
|
|
185
|
+
* code span lives in — in which case the span cannot cross it and the tag must
|
|
186
|
+
* be left visible to the tag scan.
|
|
187
|
+
*/
|
|
188
|
+
var startsParagraphInterruptingBlock = (text, pos) => {
|
|
189
|
+
let cursor = pos + 1;
|
|
190
|
+
const closing = text[cursor] === "/";
|
|
191
|
+
if (closing) cursor += 1;
|
|
192
|
+
let tagName = "";
|
|
193
|
+
while (cursor < text.length && TAG_NAME_CHAR_REGEX.test(text[cursor])) {
|
|
194
|
+
tagName += text[cursor];
|
|
195
|
+
cursor += 1;
|
|
196
|
+
}
|
|
197
|
+
tagName = tagName.toLowerCase();
|
|
198
|
+
if (BLOCK_OPENER_TAGS.has(tagName)) return !closing;
|
|
199
|
+
return PARAGRAPH_INTERRUPTING_TAGS.has(tagName);
|
|
200
|
+
};
|
|
201
|
+
/**
|
|
202
|
+
* Index of the next run of exactly `len` backticks before the paragraph ends,
|
|
203
|
+
* or -1 when there is none. CommonMark: a code span ends at the next run of
|
|
204
|
+
* the *same* length, may contain line endings, and does not cross a blank
|
|
205
|
+
* line; a run with no such closer is literal text, not a span.
|
|
206
|
+
*
|
|
207
|
+
* The lookahead also stops where the paragraph does: a blank line, or a line
|
|
208
|
+
* that starts an HTML block (`<div>`, `</pre>`, …) — the paragraph cannot
|
|
209
|
+
* continue past either, so a tag on that line is real HTML and must not be
|
|
210
|
+
* swallowed by a pairing.
|
|
211
|
+
*/
|
|
212
|
+
var findClosingBacktickRun = (text, from, len) => {
|
|
213
|
+
let pos = from;
|
|
214
|
+
while (pos < text.length) {
|
|
215
|
+
const char = text[pos];
|
|
216
|
+
if (char === "\n") {
|
|
217
|
+
let ahead = pos + 1;
|
|
218
|
+
while (text[ahead] === " " || text[ahead] === " ") ahead += 1;
|
|
219
|
+
if (text[ahead] === "\n" || ahead >= text.length) return -1;
|
|
220
|
+
if (text[ahead] === "<" && startsParagraphInterruptingBlock(text, ahead)) return -1;
|
|
221
|
+
pos += 1;
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
if (char !== "`") {
|
|
225
|
+
pos += 1;
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
let run = 1;
|
|
229
|
+
while (text[pos + run] === "`") run += 1;
|
|
230
|
+
if (run === len) return pos;
|
|
231
|
+
pos += run;
|
|
232
|
+
}
|
|
233
|
+
return -1;
|
|
234
|
+
};
|
|
235
|
+
/**
|
|
236
|
+
* Columns of whitespace between the start of `pos`'s line and `pos`, or -1 when
|
|
237
|
+
* a non-whitespace character precedes it on the line. A tab advances to the
|
|
238
|
+
* next multiple of four, the way CommonMark counts indentation.
|
|
239
|
+
*/
|
|
240
|
+
var lineIndentColumns = (text, pos) => {
|
|
241
|
+
let lineStart = pos;
|
|
242
|
+
while (lineStart > 0 && text[lineStart - 1] !== "\n") lineStart -= 1;
|
|
243
|
+
let columns = 0;
|
|
244
|
+
for (let i = lineStart; i < pos; i++) if (text[i] === " ") columns += 1;
|
|
245
|
+
else if (text[i] === " ") columns += 4 - columns % 4;
|
|
246
|
+
else return -1;
|
|
247
|
+
return columns;
|
|
248
|
+
};
|
|
249
|
+
/**
|
|
250
|
+
* End offset of the indented code block whose first line starts at `pos` (a
|
|
251
|
+
* line indented four columns): the start of the first following line that is
|
|
252
|
+
* neither blank nor indented four columns, or the end of the text. Blank lines
|
|
253
|
+
* do not end the block.
|
|
254
|
+
*/
|
|
255
|
+
var skipIndentedCodeBlock = (text, pos) => {
|
|
256
|
+
let cursor = pos;
|
|
257
|
+
for (;;) {
|
|
258
|
+
const newline = text.indexOf("\n", cursor);
|
|
259
|
+
cursor = newline === -1 ? text.length : newline + 1;
|
|
260
|
+
if (cursor >= text.length) return cursor;
|
|
261
|
+
let probe = cursor;
|
|
262
|
+
let columns = 0;
|
|
263
|
+
while (probe < text.length && (text[probe] === " " || text[probe] === " ")) {
|
|
264
|
+
columns += text[probe] === " " ? 4 - columns % 4 : 1;
|
|
265
|
+
probe += 1;
|
|
266
|
+
}
|
|
267
|
+
if (probe < text.length && text[probe] !== "\n" && columns < 4) return cursor;
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
/**
|
|
271
|
+
* Scan one run of non-fence lines for raw HTML tags, maintaining the stack of
|
|
272
|
+
* open containers across runs. Returns true when the range ends inside an
|
|
273
|
+
* unterminated tag or comment (the browser would swallow whatever follows,
|
|
274
|
+
* so a split there is never safe).
|
|
275
|
+
*/
|
|
276
|
+
var scanRawTagRange = (text, openStack) => {
|
|
277
|
+
let pos = 0;
|
|
278
|
+
while (pos < text.length) {
|
|
279
|
+
const char = text[pos];
|
|
280
|
+
if (char === "`" || char === "~") {
|
|
281
|
+
let runLen = 1;
|
|
282
|
+
while (text[pos + runLen] === char) runLen += 1;
|
|
283
|
+
if ((runLen >= 3 ? lineIndentColumns(text, pos) : -1) >= 4) {
|
|
284
|
+
pos = skipIndentedCodeBlock(text, pos);
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
if (char === "~") {
|
|
288
|
+
pos += runLen;
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
const close = findClosingBacktickRun(text, pos + runLen, runLen);
|
|
292
|
+
pos = close === -1 ? pos + runLen : close + runLen;
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
if (char !== "<") {
|
|
296
|
+
pos += 1;
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
if (text.startsWith(COMMENT_START, pos)) {
|
|
300
|
+
const end = text.indexOf(COMMENT_END, pos + 4);
|
|
301
|
+
if (end === -1) return true;
|
|
302
|
+
pos = end + 3;
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
if (text.startsWith(CDATA_START, pos)) {
|
|
306
|
+
const end = text.indexOf(CDATA_END, pos + 9);
|
|
307
|
+
if (end === -1) return true;
|
|
308
|
+
pos = end + 3;
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
const closingTag = parseClosingTag(text, pos);
|
|
312
|
+
if (closingTag) {
|
|
313
|
+
for (let i = openStack.length - 1; i >= 0; i--) if (openStack[i] === closingTag.tagName) {
|
|
314
|
+
openStack.length = i;
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
pos = closingTag.endPos;
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
const openingTag = parseOpeningTag(text, pos);
|
|
321
|
+
if (openingTag) {
|
|
322
|
+
if (!openingTag.foundEnd) return true;
|
|
323
|
+
if (/[A-Z]/.test(text[pos + 1] ?? "") || !VOID_ELEMENTS.has(openingTag.tagName)) openStack.push(openingTag.tagName);
|
|
324
|
+
pos = openingTag.endPos;
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
pos += 1;
|
|
328
|
+
}
|
|
329
|
+
return false;
|
|
330
|
+
};
|
|
331
|
+
/**
|
|
332
|
+
* Whether `text` (a section's worth of Markdown source) leaves a raw HTML
|
|
333
|
+
* container open. CommonMark ends an HTML block at a blank line, but the
|
|
334
|
+
* browser keeps nesting into an unclosed `<div>`/`<details>`/`<table>`/…
|
|
335
|
+
* until its closing tag — so a section split placed before the next heading
|
|
336
|
+
* would auto-close the container at the section end and produce a different
|
|
337
|
+
* DOM from the whole-document render. An open `<p>` is the one exception:
|
|
338
|
+
* the HTML parser closes it when a heading starts, so both parses nest the
|
|
339
|
+
* heading identically. (Downstream-only guard; upstream ant-design/x#2061
|
|
340
|
+
* only checks registered custom component tags here.)
|
|
341
|
+
*/
|
|
342
|
+
function hasUnclosedRawTags(text) {
|
|
343
|
+
const openStack = [];
|
|
344
|
+
const fence = {
|
|
345
|
+
inFence: false,
|
|
346
|
+
fenceChar: "",
|
|
347
|
+
fenceLen: 0
|
|
348
|
+
};
|
|
349
|
+
let rangeStart = 0;
|
|
350
|
+
let rangeOpen = false;
|
|
351
|
+
const flushRange = (end) => {
|
|
352
|
+
if (!rangeOpen) return false;
|
|
353
|
+
rangeOpen = false;
|
|
354
|
+
return end > rangeStart ? scanRawTagRange(text.slice(rangeStart, end), openStack) : false;
|
|
355
|
+
};
|
|
356
|
+
let lineStart = 0;
|
|
357
|
+
while (lineStart < text.length) {
|
|
358
|
+
const newline = text.indexOf("\n", lineStart);
|
|
359
|
+
const lineEnd = newline === -1 ? text.length : newline;
|
|
360
|
+
const wasInFence = fence.inFence;
|
|
361
|
+
classifyRawScanLine(text.slice(lineStart, lineEnd), fence);
|
|
362
|
+
if (fence.inFence || wasInFence) {
|
|
363
|
+
if (flushRange(lineStart)) return true;
|
|
364
|
+
} else if (!rangeOpen) {
|
|
365
|
+
rangeStart = lineStart;
|
|
366
|
+
rangeOpen = true;
|
|
367
|
+
}
|
|
368
|
+
if (newline === -1) break;
|
|
369
|
+
lineStart = newline + 1;
|
|
370
|
+
}
|
|
371
|
+
if (flushRange(text.length)) return true;
|
|
372
|
+
return openStack.some((tagName) => tagName !== "p");
|
|
373
|
+
}
|
|
140
374
|
//#endregion
|
|
141
|
-
export { detectUnclosedComponentTags, getTagInstanceId };
|
|
375
|
+
export { detectUnclosedComponentTags, getTagInstanceId, hasUnclosedRawTags };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Parser } from "./Parser.js";
|
|
2
1
|
import { detectUnclosedComponentTags } from "./detectUnclosedComponentTags.js";
|
|
2
|
+
import { Parser } from "./Parser.js";
|
|
3
3
|
import { VueRenderer } from "./VueRenderer.js";
|
|
4
4
|
export { Parser, VueRenderer, detectUnclosedComponentTags };
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
export { default as XMarkdown } from './index.vue';
|
|
2
2
|
export type { XMarkdownProps } from './interface';
|
|
3
|
-
export type { StreamingOption } from './interface';
|
|
3
|
+
export type { StreamingOption, TypewriterOption } from './interface';
|
|
4
|
+
export type { AnimationConfig, TypewriterConfig } from './interface';
|
|
5
|
+
export type { StreamCacheTokenType } from './interface';
|
|
4
6
|
export type { MarkedConfig } from './interface';
|
|
5
7
|
export type { ComponentProps } from './interface';
|
|
6
8
|
export { Parser } from './core/Parser';
|
|
7
9
|
export { VueRenderer } from './core/VueRenderer';
|
|
8
10
|
export { detectUnclosedComponentTags } from './core/detectUnclosedComponentTags';
|
|
9
|
-
export { useStreaming } from './composables/useStreaming';
|
|
11
|
+
export { useStreaming, useStreamingCore } from './composables/useStreaming';
|
|
12
|
+
export { useTypewriter } from './composables/useTypewriter';
|
|
10
13
|
export { useParser } from './composables/useParser';
|
|
11
14
|
export { useRenderer } from './composables/useRenderer';
|
|
12
15
|
export { useTail } from './composables/useTail';
|
|
13
16
|
export { AnimationText, DebugPanel, TailIndicator } from './components';
|
|
17
|
+
export { resolveStreaming } from './utils/streaming';
|
|
14
18
|
export { resolveTailContent } from './utils/tail';
|
package/dist/XMarkdown/index.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import AnimationText_default from "./components/AnimationText.js";
|
|
2
2
|
import DebugPanel_default from "./components/DebugPanel2.js";
|
|
3
3
|
import TailIndicator_default from "./components/TailIndicator.js";
|
|
4
|
-
import {
|
|
4
|
+
import { detectUnclosedComponentTags } from "./core/detectUnclosedComponentTags.js";
|
|
5
|
+
import { resolveStreaming } from "./utils/streaming.js";
|
|
6
|
+
import { useStreaming, useStreamingCore } from "./composables/useStreaming.js";
|
|
7
|
+
import useTypewriter from "./composables/useTypewriter.js";
|
|
5
8
|
import { Parser } from "./core/Parser.js";
|
|
6
9
|
import { useParser } from "./composables/useParser.js";
|
|
7
|
-
import { detectUnclosedComponentTags } from "./core/detectUnclosedComponentTags.js";
|
|
8
10
|
import { VueRenderer } from "./core/VueRenderer.js";
|
|
9
11
|
import { useRenderer } from "./composables/useRenderer.js";
|
|
10
12
|
import { useTail } from "./composables/useTail.js";
|
|
11
13
|
import XMarkdown_default from "./index2.js";
|
|
12
14
|
import { resolveTailContent } from "./utils/tail.js";
|
|
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 };
|
|
15
|
+
export { AnimationText_default as AnimationText, DebugPanel_default as DebugPanel, Parser, TailIndicator_default as TailIndicator, VueRenderer, XMarkdown_default as XMarkdown, detectUnclosedComponentTags, resolveStreaming, resolveTailContent, useParser, useRenderer, useStreaming, useStreamingCore, useTail, useTypewriter };
|
|
@@ -2,12 +2,12 @@ import { Component } from 'vue';
|
|
|
2
2
|
import { XMarkdownProps } from './interface';
|
|
3
3
|
declare const __VLS_export: import('vue').DefineComponent<XMarkdownProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<XMarkdownProps> & Readonly<{}>, {
|
|
4
4
|
content: string;
|
|
5
|
+
streaming: boolean | import('./interface').StreamingOption;
|
|
5
6
|
openLinksInNewTab: boolean;
|
|
6
7
|
paragraphTag: string;
|
|
7
8
|
escapeRawHtml: boolean;
|
|
8
9
|
config: import('./interface').MarkedConfig;
|
|
9
10
|
components: Record<string, Component>;
|
|
10
|
-
streaming: import('./interface').StreamingOption;
|
|
11
11
|
debug: boolean;
|
|
12
12
|
protectCustomTagNewlines: boolean;
|
|
13
13
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import DebugPanel_default from "./components/DebugPanel2.js";
|
|
2
2
|
import TailIndicator_default from "./components/TailIndicator.js";
|
|
3
|
-
import {
|
|
3
|
+
import { resolveStreaming } from "./utils/streaming.js";
|
|
4
|
+
import { useStreamingCore } from "./composables/useStreaming.js";
|
|
5
|
+
import useTypewriter from "./composables/useTypewriter.js";
|
|
4
6
|
import { Parser } from "./core/Parser.js";
|
|
5
7
|
import { VueRenderer } from "./core/VueRenderer.js";
|
|
6
8
|
import { useTail } from "./composables/useTail.js";
|
|
7
|
-
import
|
|
9
|
+
import Section_default from "./components/Section.js";
|
|
10
|
+
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, defineComponent, h, normalizeClass, normalizeStyle, openBlock, ref, renderList, shallowRef, unref, watch } from "vue";
|
|
8
11
|
//#region src/XMarkdown/index.vue?vue&type=script&setup=true&lang.ts
|
|
9
12
|
var index_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
|
|
10
13
|
__name: "index",
|
|
@@ -12,7 +15,10 @@ var index_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComp
|
|
|
12
15
|
content: { default: "" },
|
|
13
16
|
components: { default: () => ({}) },
|
|
14
17
|
componentsProps: {},
|
|
15
|
-
streaming: {
|
|
18
|
+
streaming: {
|
|
19
|
+
type: [Boolean, Object],
|
|
20
|
+
default: void 0
|
|
21
|
+
},
|
|
16
22
|
config: { default: () => ({ gfm: true }) },
|
|
17
23
|
debug: {
|
|
18
24
|
type: Boolean,
|
|
@@ -36,21 +42,29 @@ var index_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComp
|
|
|
36
42
|
},
|
|
37
43
|
setup(__props) {
|
|
38
44
|
const props = __props;
|
|
45
|
+
const streamingResolved = computed(() => resolveStreaming(props.streaming));
|
|
39
46
|
const contentRef = computed(() => props.content || "");
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
const
|
|
47
|
+
const componentsRef = computed(() => props.components);
|
|
48
|
+
const pacedContent = useTypewriter(contentRef, computed(() => streamingResolved.value?.typewriter), computed(() => !!streamingResolved.value?.hasNextChunk));
|
|
49
|
+
const parser = shallowRef(new Parser({
|
|
50
|
+
openLinksInNewTab: props.openLinksInNewTab,
|
|
51
|
+
paragraphTag: props.paragraphTag,
|
|
52
|
+
protectCustomTags: props.protectCustomTagNewlines,
|
|
53
|
+
escapeRawHtml: props.escapeRawHtml,
|
|
54
|
+
config: props.config,
|
|
55
|
+
components: props.components
|
|
56
|
+
}));
|
|
57
|
+
const { output: processedContent, sections } = useStreamingCore(pacedContent, streamingResolved, componentsRef, (markdown) => parser.value.lex(markdown));
|
|
58
|
+
const { tailContent, tailComponent, showTail } = useTail(streamingResolved);
|
|
59
|
+
const TailBridge = defineComponent({
|
|
60
|
+
name: "XmdTailBridge",
|
|
61
|
+
setup() {
|
|
62
|
+
return () => h(tailComponent.value || TailIndicator_default, { content: tailContent.value });
|
|
63
|
+
}
|
|
64
|
+
});
|
|
43
65
|
const mergedComponents = computed(() => {
|
|
44
66
|
const baseComponents = { ...props.components };
|
|
45
67
|
if (!showTail.value || !tailContent.value) return baseComponents;
|
|
46
|
-
const resolvedTailComponent = tailComponent.value || TailIndicator_default;
|
|
47
|
-
const content = tailContent.value;
|
|
48
|
-
const TailBridge = defineComponent({
|
|
49
|
-
name: "XmdTailBridge",
|
|
50
|
-
setup() {
|
|
51
|
-
return () => h(resolvedTailComponent, { content });
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
68
|
return {
|
|
55
69
|
...baseComponents,
|
|
56
70
|
"xmd-tail": TailBridge
|
|
@@ -66,19 +80,11 @@ var index_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComp
|
|
|
66
80
|
return () => props.node;
|
|
67
81
|
}
|
|
68
82
|
});
|
|
69
|
-
const parser = shallowRef(new Parser({
|
|
70
|
-
openLinksInNewTab: props.openLinksInNewTab,
|
|
71
|
-
paragraphTag: props.paragraphTag,
|
|
72
|
-
protectCustomTags: props.protectCustomTagNewlines,
|
|
73
|
-
escapeRawHtml: props.escapeRawHtml,
|
|
74
|
-
config: props.config,
|
|
75
|
-
components: props.components
|
|
76
|
-
}));
|
|
77
83
|
const renderer = shallowRef(new VueRenderer({
|
|
78
84
|
components: mergedComponents.value,
|
|
79
85
|
componentsProps: props.componentsProps,
|
|
80
|
-
enableAnimation:
|
|
81
|
-
animationConfig:
|
|
86
|
+
enableAnimation: streamingResolved.value?.enableAnimation ?? true,
|
|
87
|
+
animationConfig: streamingResolved.value?.animationConfig
|
|
82
88
|
}));
|
|
83
89
|
const optionsVersion = ref(0);
|
|
84
90
|
const bumpOptionsVersion = () => {
|
|
@@ -86,6 +92,7 @@ var index_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComp
|
|
|
86
92
|
};
|
|
87
93
|
const htmlOutput = computed(() => {
|
|
88
94
|
optionsVersion.value;
|
|
95
|
+
if (sections.value) return "";
|
|
89
96
|
return parser.value.parse(processedContent.value, { injectTail: showTail.value });
|
|
90
97
|
});
|
|
91
98
|
const vNode = computed(() => {
|
|
@@ -122,18 +129,45 @@ var index_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComp
|
|
|
122
129
|
renderer.value.setOptions({ componentsProps: newComponentsProps });
|
|
123
130
|
bumpOptionsVersion();
|
|
124
131
|
}, { deep: true });
|
|
125
|
-
watch(
|
|
132
|
+
watch([
|
|
133
|
+
() => streamingResolved.value?.enableAnimation,
|
|
134
|
+
() => streamingResolved.value?.animationConfig?.fadeDuration,
|
|
135
|
+
() => streamingResolved.value?.animationConfig?.easing,
|
|
136
|
+
() => streamingResolved.value?.animationConfig?.splitBy,
|
|
137
|
+
() => streamingResolved.value?.animationConfig?.delimiters?.join("\0"),
|
|
138
|
+
() => streamingResolved.value?.animationConfig?.maxSentenceChars
|
|
139
|
+
], () => {
|
|
140
|
+
const animationConfig = streamingResolved.value?.animationConfig;
|
|
126
141
|
renderer.value.setOptions({
|
|
127
|
-
enableAnimation:
|
|
128
|
-
animationConfig:
|
|
142
|
+
enableAnimation: streamingResolved.value?.enableAnimation ?? true,
|
|
143
|
+
animationConfig: animationConfig ? { ...animationConfig } : void 0
|
|
129
144
|
});
|
|
130
145
|
bumpOptionsVersion();
|
|
131
|
-
}
|
|
146
|
+
});
|
|
132
147
|
return (_ctx, _cache) => {
|
|
133
|
-
return openBlock(), createElementBlock("div", {
|
|
148
|
+
return unref(processedContent) ? (openBlock(), createElementBlock("div", {
|
|
149
|
+
key: 0,
|
|
134
150
|
class: normalizeClass(["x-markdown", __props.className]),
|
|
135
151
|
style: normalizeStyle(__props.style)
|
|
136
|
-
}, [
|
|
152
|
+
}, [unref(sections) ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(unref(sections), (section, index) => {
|
|
153
|
+
return openBlock(), createBlock(Section_default, {
|
|
154
|
+
key: index,
|
|
155
|
+
content: section,
|
|
156
|
+
parser: parser.value,
|
|
157
|
+
renderer: renderer.value,
|
|
158
|
+
"inject-tail": !!unref(showTail) && index === unref(sections).length - 1,
|
|
159
|
+
"options-version": optionsVersion.value
|
|
160
|
+
}, null, 8, [
|
|
161
|
+
"content",
|
|
162
|
+
"parser",
|
|
163
|
+
"renderer",
|
|
164
|
+
"inject-tail",
|
|
165
|
+
"options-version"
|
|
166
|
+
]);
|
|
167
|
+
}), 128)) : (openBlock(), createBlock(unref(VNodeRenderer), {
|
|
168
|
+
key: 1,
|
|
169
|
+
node: vNode.value
|
|
170
|
+
}, null, 8, ["node"])), __props.debug ? (openBlock(), createBlock(DebugPanel_default, { key: 2 })) : createCommentVNode("", true)], 6)) : createCommentVNode("", true);
|
|
137
171
|
};
|
|
138
172
|
}
|
|
139
173
|
});
|