stream-markdown-parser 0.0.7 → 0.0.8
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/index.d.ts +35 -35
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +783 -602
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -36,40 +36,41 @@ function applyContainers(md) {
|
|
|
36
36
|
} });
|
|
37
37
|
});
|
|
38
38
|
md.block.ruler.before("fence", "vmr_container_fallback", (state, startLine, endLine, silent) => {
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const
|
|
39
|
+
const s = state;
|
|
40
|
+
const startPos = s.bMarks[startLine] + s.tShift[startLine];
|
|
41
|
+
const lineMax = s.eMarks[startLine];
|
|
42
|
+
const markerMatch = s.src.slice(startPos, lineMax).match(/^:::\s*(\w+)/);
|
|
42
43
|
if (!markerMatch) return false;
|
|
43
44
|
if (silent) return true;
|
|
44
45
|
const name = markerMatch[1];
|
|
45
46
|
let nextLine = startLine + 1;
|
|
46
47
|
let found = false;
|
|
47
48
|
while (nextLine <= endLine) {
|
|
48
|
-
const sPos =
|
|
49
|
-
const ePos =
|
|
50
|
-
if (
|
|
49
|
+
const sPos = s.bMarks[nextLine] + s.tShift[nextLine];
|
|
50
|
+
const ePos = s.eMarks[nextLine];
|
|
51
|
+
if (s.src.slice(sPos, ePos).trim() === ":::") {
|
|
51
52
|
found = true;
|
|
52
53
|
break;
|
|
53
54
|
}
|
|
54
55
|
nextLine++;
|
|
55
56
|
}
|
|
56
57
|
if (!found) return false;
|
|
57
|
-
|
|
58
|
+
s.push("vmr_container_open", "div", 1).attrSet("class", `vmr-container vmr-container-${name}`);
|
|
58
59
|
const contentLines = [];
|
|
59
60
|
for (let i = startLine + 1; i < nextLine; i++) {
|
|
60
|
-
const sPos =
|
|
61
|
-
const ePos =
|
|
62
|
-
contentLines.push(
|
|
61
|
+
const sPos = s.bMarks[i] + s.tShift[i];
|
|
62
|
+
const ePos = s.eMarks[i];
|
|
63
|
+
contentLines.push(s.src.slice(sPos, ePos));
|
|
63
64
|
}
|
|
64
|
-
|
|
65
|
-
const inlineToken =
|
|
65
|
+
s.push("paragraph_open", "p", 1);
|
|
66
|
+
const inlineToken = s.push("inline", "", 0);
|
|
66
67
|
inlineToken.content = contentLines.join("\n");
|
|
67
68
|
inlineToken.map = [startLine + 1, nextLine];
|
|
68
69
|
inlineToken.children = [];
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
s.md.inline.parse(inlineToken.content, s.md, s.env, inlineToken.children);
|
|
71
|
+
s.push("paragraph_close", "p", -1);
|
|
72
|
+
s.push("vmr_container_close", "div", -1);
|
|
73
|
+
s.line = nextLine + 1;
|
|
73
74
|
return true;
|
|
74
75
|
});
|
|
75
76
|
}
|
|
@@ -278,7 +279,8 @@ function normalizeStandaloneBackslashT(s, opts) {
|
|
|
278
279
|
}
|
|
279
280
|
function applyMath(md, mathOpts) {
|
|
280
281
|
const mathInline = (state, silent) => {
|
|
281
|
-
|
|
282
|
+
const s = state;
|
|
283
|
+
if (/^\*[^*]+/.test(s.src)) return false;
|
|
282
284
|
const delimiters = [
|
|
283
285
|
["$$", "$$"],
|
|
284
286
|
["\\(", "\\)"],
|
|
@@ -287,28 +289,28 @@ function applyMath(md, mathOpts) {
|
|
|
287
289
|
let searchPos = 0;
|
|
288
290
|
let preMathPos = 0;
|
|
289
291
|
for (const [open, close] of delimiters) {
|
|
290
|
-
const src =
|
|
292
|
+
const src = s.src;
|
|
291
293
|
let foundAny = false;
|
|
292
294
|
const pushText = (text) => {
|
|
293
295
|
if (text === "undefined" || text == null) text = "";
|
|
294
296
|
if (text === "\\") {
|
|
295
|
-
|
|
296
|
-
searchPos =
|
|
297
|
+
s.pos = s.pos + text.length;
|
|
298
|
+
searchPos = s.pos;
|
|
297
299
|
return;
|
|
298
300
|
}
|
|
299
301
|
if (text === "\\)" || text === "\\(") {
|
|
300
|
-
const t$1 =
|
|
302
|
+
const t$1 = s.push("text_special", "", 0);
|
|
301
303
|
t$1.content = text === "\\)" ? ")" : "(";
|
|
302
304
|
t$1.markup = text;
|
|
303
|
-
|
|
304
|
-
searchPos =
|
|
305
|
+
s.pos = s.pos + text.length;
|
|
306
|
+
searchPos = s.pos;
|
|
305
307
|
return;
|
|
306
308
|
}
|
|
307
309
|
if (!text) return;
|
|
308
|
-
const t =
|
|
310
|
+
const t = s.push("text", "", 0);
|
|
309
311
|
t.content = text;
|
|
310
|
-
|
|
311
|
-
searchPos =
|
|
312
|
+
s.pos = s.pos + text.length;
|
|
313
|
+
searchPos = s.pos;
|
|
312
314
|
};
|
|
313
315
|
while (true) {
|
|
314
316
|
if (searchPos >= src.length) break;
|
|
@@ -326,28 +328,28 @@ function applyMath(md, mathOpts) {
|
|
|
326
328
|
searchPos = index + open.length;
|
|
327
329
|
foundAny = true;
|
|
328
330
|
if (!silent) {
|
|
329
|
-
|
|
331
|
+
s.pending = "";
|
|
330
332
|
const isStrongPrefix = countUnescapedStrong(preMathPos ? src.slice(preMathPos, searchPos) : src.slice(0, searchPos)) % 2 === 1;
|
|
331
333
|
if (preMathPos) pushText(src.slice(preMathPos, searchPos));
|
|
332
334
|
else pushText(src.slice(0, searchPos));
|
|
333
335
|
if (isStrongPrefix) {
|
|
334
|
-
const strongToken =
|
|
336
|
+
const strongToken = s.push("strong_open", "", 0);
|
|
335
337
|
strongToken.markup = src.slice(0, index + 2);
|
|
336
|
-
const token =
|
|
338
|
+
const token = s.push("math_inline", "math", 0);
|
|
337
339
|
token.content = normalizeStandaloneBackslashT(content$1, mathOpts);
|
|
338
340
|
token.markup = open === "$$" ? "$$" : open === "\\(" ? "\\(\\)" : open === "$" ? "$" : "()";
|
|
339
341
|
token.raw = `${open}${content$1}${close}`;
|
|
340
342
|
token.loading = true;
|
|
341
343
|
strongToken.content = content$1;
|
|
342
|
-
|
|
344
|
+
s.push("strong_close", "", 0);
|
|
343
345
|
} else {
|
|
344
|
-
const token =
|
|
346
|
+
const token = s.push("math_inline", "math", 0);
|
|
345
347
|
token.content = normalizeStandaloneBackslashT(content$1, mathOpts);
|
|
346
348
|
token.markup = open === "$$" ? "$$" : open === "\\(" ? "\\(\\)" : open === "$" ? "$" : "()";
|
|
347
349
|
token.raw = `${open}${content$1}${close}`;
|
|
348
350
|
token.loading = true;
|
|
349
351
|
}
|
|
350
|
-
|
|
352
|
+
s.pos = src.length;
|
|
351
353
|
}
|
|
352
354
|
searchPos = src.length;
|
|
353
355
|
preMathPos = searchPos;
|
|
@@ -357,8 +359,8 @@ function applyMath(md, mathOpts) {
|
|
|
357
359
|
const content = src.slice(index + open.length, endIdx);
|
|
358
360
|
if (!isMathLike(content)) {
|
|
359
361
|
searchPos = endIdx + close.length;
|
|
360
|
-
const text = src.slice(
|
|
361
|
-
if (!
|
|
362
|
+
const text = src.slice(s.pos, searchPos);
|
|
363
|
+
if (!s.pending) pushText(text);
|
|
362
364
|
continue;
|
|
363
365
|
}
|
|
364
366
|
foundAny = true;
|
|
@@ -366,42 +368,42 @@ function applyMath(md, mathOpts) {
|
|
|
366
368
|
const before = src.slice(0, index);
|
|
367
369
|
let toPushBefore = src.slice(0, searchPos) ? src.slice(preMathPos, index) : before;
|
|
368
370
|
const isStrongPrefix = countUnescapedStrong(toPushBefore) % 2 === 1;
|
|
369
|
-
if (index !==
|
|
370
|
-
if (
|
|
371
|
-
|
|
371
|
+
if (index !== s.pos && isStrongPrefix) toPushBefore = s.pending + src.slice(s.pos, index);
|
|
372
|
+
if (s.pending !== toPushBefore) {
|
|
373
|
+
s.pending = "";
|
|
372
374
|
if (isStrongPrefix) {
|
|
373
375
|
const _match = toPushBefore.match(/(\*+)/);
|
|
374
376
|
const after = toPushBefore.slice(_match.index + _match[0].length);
|
|
375
377
|
pushText(toPushBefore.slice(0, _match.index));
|
|
376
|
-
const strongToken =
|
|
378
|
+
const strongToken = s.push("strong_open", "", 0);
|
|
377
379
|
strongToken.markup = _match[0];
|
|
378
|
-
const textToken =
|
|
380
|
+
const textToken = s.push("text", "", 0);
|
|
379
381
|
textToken.content = after;
|
|
380
|
-
|
|
382
|
+
s.push("strong_close", "", 0);
|
|
381
383
|
} else pushText(toPushBefore);
|
|
382
384
|
}
|
|
383
385
|
if (isStrongPrefix) {
|
|
384
|
-
const strongToken =
|
|
386
|
+
const strongToken = s.push("strong_open", "", 0);
|
|
385
387
|
strongToken.markup = "**";
|
|
386
|
-
const token =
|
|
388
|
+
const token = s.push("math_inline", "math", 0);
|
|
387
389
|
token.content = normalizeStandaloneBackslashT(content, mathOpts);
|
|
388
390
|
token.markup = open === "$$" ? "$$" : open === "\\(" ? "\\(\\)" : open === "$" ? "$" : "()";
|
|
389
391
|
token.raw = `${open}${content}${close}`;
|
|
390
392
|
token.loading = false;
|
|
391
393
|
const raw = src.slice(endIdx + close.length);
|
|
392
394
|
const isBeforeClose = raw.startsWith("*");
|
|
393
|
-
if (isBeforeClose)
|
|
395
|
+
if (isBeforeClose) s.push("strong_close", "", 0);
|
|
394
396
|
if (raw) {
|
|
395
|
-
const textContentToken =
|
|
397
|
+
const textContentToken = s.push("text", "", 0);
|
|
396
398
|
textContentToken.content = (raw == null ? "" : String(raw)).replace(/^\*+/, "");
|
|
397
399
|
}
|
|
398
|
-
if (!isBeforeClose)
|
|
399
|
-
|
|
400
|
+
if (!isBeforeClose) s.push("strong_close", "", 0);
|
|
401
|
+
s.pos = src.length;
|
|
400
402
|
searchPos = src.length;
|
|
401
403
|
preMathPos = searchPos;
|
|
402
404
|
continue;
|
|
403
405
|
} else {
|
|
404
|
-
const token =
|
|
406
|
+
const token = s.push("math_inline", "math", 0);
|
|
405
407
|
token.content = normalizeStandaloneBackslashT(content, mathOpts);
|
|
406
408
|
token.markup = open === "$$" ? "$$" : open === "\\(" ? "\\(\\)" : open === "$" ? "$" : "()";
|
|
407
409
|
token.raw = `${open}${content}${close}`;
|
|
@@ -410,26 +412,27 @@ function applyMath(md, mathOpts) {
|
|
|
410
412
|
}
|
|
411
413
|
searchPos = endIdx + close.length;
|
|
412
414
|
preMathPos = searchPos;
|
|
413
|
-
|
|
415
|
+
s.pos = searchPos;
|
|
414
416
|
}
|
|
415
417
|
if (foundAny) {
|
|
416
418
|
if (!silent) {
|
|
417
419
|
if (searchPos < src.length) pushText(src.slice(searchPos));
|
|
418
|
-
|
|
419
|
-
} else
|
|
420
|
+
s.pos = src.length;
|
|
421
|
+
} else s.pos = searchPos;
|
|
420
422
|
return true;
|
|
421
423
|
}
|
|
422
424
|
}
|
|
423
425
|
return false;
|
|
424
426
|
};
|
|
425
427
|
const mathBlock = (state, startLine, endLine, silent) => {
|
|
428
|
+
const s = state;
|
|
426
429
|
const delimiters = [
|
|
427
430
|
["\\[", "\\]"],
|
|
428
431
|
["[", "]"],
|
|
429
432
|
["$$", "$$"]
|
|
430
433
|
];
|
|
431
|
-
const startPos =
|
|
432
|
-
const lineText =
|
|
434
|
+
const startPos = s.bMarks[startLine] + s.tShift[startLine];
|
|
435
|
+
const lineText = s.src.slice(startPos, s.eMarks[startLine]).trim();
|
|
433
436
|
let matched = false;
|
|
434
437
|
let openDelim = "";
|
|
435
438
|
let closeDelim = "";
|
|
@@ -455,14 +458,14 @@ function applyMath(md, mathOpts) {
|
|
|
455
458
|
const startDelimIndex = lineText.indexOf(openDelim);
|
|
456
459
|
const endDelimIndex = lineText.indexOf(closeDelim, startDelimIndex + openDelim.length);
|
|
457
460
|
const content$1 = lineText.slice(startDelimIndex + openDelim.length, endDelimIndex);
|
|
458
|
-
const token$1 =
|
|
461
|
+
const token$1 = s.push("math_block", "math", 0);
|
|
459
462
|
token$1.content = normalizeStandaloneBackslashT(content$1);
|
|
460
463
|
token$1.markup = openDelim === "$$" ? "$$" : openDelim === "[" ? "[]" : "\\[\\]";
|
|
461
464
|
token$1.map = [startLine, startLine + 1];
|
|
462
465
|
token$1.raw = `${openDelim}${content$1}${closeDelim}`;
|
|
463
466
|
token$1.block = true;
|
|
464
467
|
token$1.loading = false;
|
|
465
|
-
|
|
468
|
+
s.line = startLine + 1;
|
|
466
469
|
return true;
|
|
467
470
|
}
|
|
468
471
|
let nextLine = startLine;
|
|
@@ -477,9 +480,9 @@ function applyMath(md, mathOpts) {
|
|
|
477
480
|
} else {
|
|
478
481
|
if (firstLineContent) content = firstLineContent;
|
|
479
482
|
for (nextLine = startLine + 1; nextLine < endLine; nextLine++) {
|
|
480
|
-
const lineStart =
|
|
481
|
-
const lineEnd =
|
|
482
|
-
const currentLine =
|
|
483
|
+
const lineStart = s.bMarks[nextLine] + s.tShift[nextLine];
|
|
484
|
+
const lineEnd = s.eMarks[nextLine];
|
|
485
|
+
const currentLine = s.src.slice(lineStart - 1, lineEnd);
|
|
483
486
|
if (currentLine.trim() === closeDelim) {
|
|
484
487
|
found = true;
|
|
485
488
|
break;
|
|
@@ -492,14 +495,14 @@ function applyMath(md, mathOpts) {
|
|
|
492
495
|
content += (content ? "\n" : "") + currentLine;
|
|
493
496
|
}
|
|
494
497
|
}
|
|
495
|
-
const token =
|
|
498
|
+
const token = s.push("math_block", "math", 0);
|
|
496
499
|
token.content = normalizeStandaloneBackslashT(content);
|
|
497
500
|
token.markup = openDelim === "$$" ? "$$" : openDelim === "[" ? "[]" : "\\[\\]";
|
|
498
501
|
token.raw = `${openDelim}${content}${content.startsWith("\n") ? "\n" : ""}${closeDelim}`;
|
|
499
502
|
token.map = [startLine, nextLine + 1];
|
|
500
503
|
token.block = true;
|
|
501
504
|
token.loading = !found;
|
|
502
|
-
|
|
505
|
+
s.line = nextLine + 1;
|
|
503
506
|
return true;
|
|
504
507
|
};
|
|
505
508
|
md.inline.ruler.before("escape", "math", mathInline);
|
|
@@ -515,16 +518,19 @@ function applyMath(md, mathOpts) {
|
|
|
515
518
|
//#region src/renderers/index.ts
|
|
516
519
|
function applyRenderRules(md) {
|
|
517
520
|
const defaultImage = md.renderer.rules.image || function(tokens, idx, options, env, self) {
|
|
518
|
-
|
|
521
|
+
const tokensAny = tokens;
|
|
522
|
+
const selfShape = self;
|
|
523
|
+
return selfShape.renderToken ? selfShape.renderToken(tokensAny, idx, options) : "";
|
|
519
524
|
};
|
|
520
525
|
md.renderer.rules.image = (tokens, idx, options, env, self) => {
|
|
521
|
-
tokens
|
|
522
|
-
|
|
526
|
+
const tokensAny = tokens;
|
|
527
|
+
tokensAny[idx].attrSet?.("loading", "lazy");
|
|
528
|
+
return defaultImage(tokensAny, idx, options, env, self);
|
|
523
529
|
};
|
|
524
530
|
md.renderer.rules.fence = md.renderer.rules.fence || ((tokens, idx) => {
|
|
525
|
-
const
|
|
526
|
-
const info =
|
|
527
|
-
return `<pre class="${info ? `language-${md.utils.escapeHtml(info.split(/\s+/g)[0])}` : ""}"><code>${md.utils.escapeHtml(
|
|
531
|
+
const tokenShape = tokens[idx];
|
|
532
|
+
const info = String(tokenShape.info ?? "").trim();
|
|
533
|
+
return `<pre class="${info ? `language-${md.utils.escapeHtml(info.split(/\s+/g)[0])}` : ""}"><code>${md.utils.escapeHtml(String(tokenShape.content ?? ""))}</code></pre>`;
|
|
528
534
|
});
|
|
529
535
|
}
|
|
530
536
|
|
|
@@ -654,24 +660,26 @@ function fixTableTokens(tokens) {
|
|
|
654
660
|
const i = tokens.length - 2;
|
|
655
661
|
const token = tokens[i];
|
|
656
662
|
if (token.type === "inline") {
|
|
657
|
-
|
|
658
|
-
|
|
663
|
+
const tcontent = String(token.content ?? "");
|
|
664
|
+
const childContent = String(token.children?.[0]?.content ?? "");
|
|
665
|
+
if (/^\|(?:[^|\n]+\|?)+/.test(tcontent)) {
|
|
666
|
+
const body = childContent.slice(1).split("|").map((i$1) => i$1.trim()).filter(Boolean).flatMap((i$1) => createTh(i$1));
|
|
659
667
|
const insert = [
|
|
660
668
|
...createStart(),
|
|
661
669
|
...body,
|
|
662
670
|
...createEnd()
|
|
663
671
|
];
|
|
664
672
|
fixedTokens.splice(i - 1, 3, ...insert);
|
|
665
|
-
} else if (/^\|(?:[^|\n]+\|)+\n\|:?-/.test(
|
|
666
|
-
const body =
|
|
673
|
+
} else if (/^\|(?:[^|\n]+\|)+\n\|:?-/.test(tcontent)) {
|
|
674
|
+
const body = childContent.slice(1, -1).split("|").map((i$1) => i$1.trim()).flatMap((i$1) => createTh(i$1));
|
|
667
675
|
const insert = [
|
|
668
676
|
...createStart(),
|
|
669
677
|
...body,
|
|
670
678
|
...createEnd()
|
|
671
679
|
];
|
|
672
680
|
fixedTokens.splice(i - 1, 3, ...insert);
|
|
673
|
-
} else if (/^\|(?:[^|\n:]+\|)+\n\|:?$/.test(
|
|
674
|
-
token.content =
|
|
681
|
+
} else if (/^\|(?:[^|\n:]+\|)+\n\|:?$/.test(tcontent)) {
|
|
682
|
+
token.content = tcontent.slice(0, -2);
|
|
675
683
|
token.children.splice(2, 1);
|
|
676
684
|
}
|
|
677
685
|
}
|
|
@@ -681,28 +689,33 @@ function fixTableTokens(tokens) {
|
|
|
681
689
|
//#endregion
|
|
682
690
|
//#region src/parser/inline-parsers/checkbox-parser.ts
|
|
683
691
|
function parseCheckboxToken(token) {
|
|
692
|
+
const tokenMeta = token.meta ?? {};
|
|
684
693
|
return {
|
|
685
694
|
type: "checkbox",
|
|
686
|
-
checked:
|
|
687
|
-
raw:
|
|
695
|
+
checked: tokenMeta.checked === true,
|
|
696
|
+
raw: tokenMeta.checked ? "[x]" : "[ ]"
|
|
688
697
|
};
|
|
689
698
|
}
|
|
690
699
|
function parseCheckboxInputToken(token) {
|
|
700
|
+
const tokenAny = token;
|
|
701
|
+
const rawAttr = tokenAny.attrGet ? tokenAny.attrGet("checked") : void 0;
|
|
702
|
+
const checked = rawAttr === "" || rawAttr === "true";
|
|
691
703
|
return {
|
|
692
704
|
type: "checkbox_input",
|
|
693
|
-
checked
|
|
694
|
-
raw:
|
|
705
|
+
checked,
|
|
706
|
+
raw: checked ? "[x]" : "[ ]"
|
|
695
707
|
};
|
|
696
708
|
}
|
|
697
709
|
|
|
698
710
|
//#endregion
|
|
699
711
|
//#region src/parser/inline-parsers/emoji-parser.ts
|
|
700
712
|
function parseEmojiToken(token) {
|
|
713
|
+
const name = String(token.content ?? "");
|
|
701
714
|
return {
|
|
702
715
|
type: "emoji",
|
|
703
|
-
name
|
|
704
|
-
markup: token.markup
|
|
705
|
-
raw: `:${
|
|
716
|
+
name,
|
|
717
|
+
markup: String(token.markup ?? ""),
|
|
718
|
+
raw: `:${name}:`
|
|
706
719
|
};
|
|
707
720
|
}
|
|
708
721
|
|
|
@@ -714,7 +727,7 @@ function parseEmphasisToken(tokens, startIndex) {
|
|
|
714
727
|
let i = startIndex + 1;
|
|
715
728
|
const innerTokens = [];
|
|
716
729
|
while (i < tokens.length && tokens[i].type !== "em_close") {
|
|
717
|
-
emText += tokens[i].content
|
|
730
|
+
emText += String(tokens[i].content ?? "");
|
|
718
731
|
innerTokens.push(tokens[i]);
|
|
719
732
|
i++;
|
|
720
733
|
}
|
|
@@ -751,11 +764,12 @@ function splitUnifiedDiff(content) {
|
|
|
751
764
|
}
|
|
752
765
|
function parseFenceToken(token) {
|
|
753
766
|
const hasMap = Array.isArray(token.map) && token.map.length === 2;
|
|
754
|
-
const
|
|
755
|
-
const closed = typeof
|
|
756
|
-
const
|
|
757
|
-
const
|
|
758
|
-
|
|
767
|
+
const tokenMeta = token.meta ?? {};
|
|
768
|
+
const closed = typeof tokenMeta.closed === "boolean" ? tokenMeta.closed : void 0;
|
|
769
|
+
const info = String(token.info ?? "");
|
|
770
|
+
const diff = info.startsWith("diff");
|
|
771
|
+
const language = diff ? String(info.split(" ")[1] ?? "") : info;
|
|
772
|
+
let content = String(token.content ?? "");
|
|
759
773
|
const trailingFenceLine = /\r?\n[ \t]*`+\s*$/;
|
|
760
774
|
if (trailingFenceLine.test(content)) content = content.replace(trailingFenceLine, "");
|
|
761
775
|
if (diff) {
|
|
@@ -763,8 +777,8 @@ function parseFenceToken(token) {
|
|
|
763
777
|
return {
|
|
764
778
|
type: "code_block",
|
|
765
779
|
language,
|
|
766
|
-
code: updated
|
|
767
|
-
raw: content,
|
|
780
|
+
code: String(updated ?? ""),
|
|
781
|
+
raw: String(content ?? ""),
|
|
768
782
|
diff,
|
|
769
783
|
loading: closed === true ? false : closed === false ? true : !hasMap,
|
|
770
784
|
originalCode: original,
|
|
@@ -774,8 +788,8 @@ function parseFenceToken(token) {
|
|
|
774
788
|
return {
|
|
775
789
|
type: "code_block",
|
|
776
790
|
language,
|
|
777
|
-
code: content
|
|
778
|
-
raw: content
|
|
791
|
+
code: String(content ?? ""),
|
|
792
|
+
raw: String(content ?? ""),
|
|
779
793
|
diff,
|
|
780
794
|
loading: closed === true ? false : closed === false ? true : !hasMap
|
|
781
795
|
};
|
|
@@ -787,26 +801,31 @@ function isTextToken(t) {
|
|
|
787
801
|
return !!t && t.type === "text" && typeof t.content === "string";
|
|
788
802
|
}
|
|
789
803
|
function fixLinkToken(tokens) {
|
|
804
|
+
const tokensAny = tokens;
|
|
790
805
|
tokens = fixLinkToken4(fixLinkToken3(tokens));
|
|
791
806
|
if (tokens.length < 5) return tokens;
|
|
792
807
|
const first = tokens[tokens.length - 5];
|
|
793
|
-
|
|
808
|
+
const firstAny = first;
|
|
809
|
+
const firstContent = String(firstAny.content ?? "");
|
|
810
|
+
if (first.type !== "text" || !firstContent.endsWith("[")) return fixLinkTokens2(tokens);
|
|
794
811
|
if (tokens[tokens.length - 4].tag !== "em") return fixLinkTokens2(tokens);
|
|
795
812
|
const last = tokens[tokens.length - 1];
|
|
796
|
-
|
|
797
|
-
const
|
|
798
|
-
|
|
813
|
+
const lastAny = last;
|
|
814
|
+
const lastContent = String(lastAny.content ?? "");
|
|
815
|
+
if (last?.type === "text" && !lastContent.startsWith("]")) return fixLinkTokens2(tokens);
|
|
816
|
+
const thirdAny = tokens[tokens.length - 3];
|
|
817
|
+
const thirdContent = String(thirdAny.content ?? "");
|
|
799
818
|
const href = lastContent.replace(/^\]\(*/, "");
|
|
800
819
|
const loading = !lastContent.includes(")");
|
|
801
|
-
|
|
820
|
+
tokensAny[tokens.length - 5].content = firstContent.replace(/\[$/, "");
|
|
802
821
|
tokens.splice(tokens.length - 3, 1, {
|
|
803
822
|
type: "link",
|
|
804
823
|
href,
|
|
805
|
-
text:
|
|
824
|
+
text: thirdContent,
|
|
806
825
|
children: [{
|
|
807
826
|
type: "text",
|
|
808
|
-
content:
|
|
809
|
-
raw:
|
|
827
|
+
content: thirdContent,
|
|
828
|
+
raw: thirdContent
|
|
810
829
|
}],
|
|
811
830
|
loading
|
|
812
831
|
});
|
|
@@ -814,6 +833,7 @@ function fixLinkToken(tokens) {
|
|
|
814
833
|
return tokens;
|
|
815
834
|
}
|
|
816
835
|
function fixLinkTokens2(tokens) {
|
|
836
|
+
const tokensAny = tokens;
|
|
817
837
|
if (tokens.length < 8) return tokens;
|
|
818
838
|
let length = tokens.length;
|
|
819
839
|
let last = tokens[length - 1];
|
|
@@ -826,16 +846,18 @@ function fixLinkTokens2(tokens) {
|
|
|
826
846
|
const third = tokens[length - 6];
|
|
827
847
|
const first = tokens[length - 8];
|
|
828
848
|
if (first.type !== "text") return tokens;
|
|
829
|
-
let href =
|
|
849
|
+
let href = String(tokensAny[length - 2]?.content ?? "");
|
|
830
850
|
let count = 4;
|
|
831
851
|
if (length !== tokens.length) {
|
|
832
|
-
href += last.content
|
|
852
|
+
href += String(last.content ?? "");
|
|
833
853
|
count++;
|
|
834
854
|
}
|
|
835
855
|
tokens.splice(length - 4, count);
|
|
836
|
-
const
|
|
856
|
+
const thirdAny = third;
|
|
857
|
+
const content = String(thirdAny.content ?? "");
|
|
837
858
|
length -= 4;
|
|
838
|
-
|
|
859
|
+
const firstAny = first;
|
|
860
|
+
tokensAny[length - 8].content = String(firstAny.content ?? "").replace(/\[$/, "");
|
|
839
861
|
tokens.splice(length - 2, 1, {
|
|
840
862
|
type: "link",
|
|
841
863
|
href,
|
|
@@ -850,13 +872,16 @@ function fixLinkTokens2(tokens) {
|
|
|
850
872
|
return tokens;
|
|
851
873
|
}
|
|
852
874
|
function fixLinkToken3(tokens) {
|
|
875
|
+
const tokensAny = tokens;
|
|
853
876
|
const last = tokens[tokens.length - 1];
|
|
854
877
|
const preLast = tokens[tokens.length - 2];
|
|
855
878
|
const fixedTokens = [...tokens];
|
|
856
879
|
if (last.type !== "text" || !last.content?.startsWith(")")) return tokens;
|
|
857
880
|
if (preLast.type !== "link_close") return tokens;
|
|
858
|
-
if (isTextToken(tokens[tokens.length - 5]) && tokens[tokens.length - 5].content
|
|
859
|
-
const
|
|
881
|
+
if (isTextToken(tokens[tokens.length - 5]) && String(tokens[tokens.length - 5].content ?? "").endsWith("(")) {
|
|
882
|
+
const a = tokensAny[tokens.length - 5];
|
|
883
|
+
const b = tokensAny[tokens.length - 3];
|
|
884
|
+
const content = String(a.content ?? "") + String(b.content ?? "") + String(last.content ?? "");
|
|
860
885
|
fixedTokens.splice(tokens.length - 5, 5, {
|
|
861
886
|
type: "text",
|
|
862
887
|
content,
|
|
@@ -872,13 +897,17 @@ function fixLinkToken3(tokens) {
|
|
|
872
897
|
return fixedTokens;
|
|
873
898
|
}
|
|
874
899
|
function fixLinkToken4(tokens) {
|
|
900
|
+
const tokensAny = tokens;
|
|
875
901
|
const fixedTokens = [...tokens];
|
|
876
902
|
for (let i = tokens.length - 1; i >= 3; i--) if (tokens[i].type === "link_close") {
|
|
877
903
|
if (tokens[i - 3]?.content?.endsWith("(")) {
|
|
878
904
|
const nextToken = tokens[i + 1];
|
|
879
905
|
if (nextToken?.type === "text") {
|
|
880
906
|
if (tokens[i - 1].type === "text" && tokens[i - 3].type === "text") {
|
|
881
|
-
const
|
|
907
|
+
const nextTokenContent = String(nextToken.content ?? "");
|
|
908
|
+
const a = tokensAny[i - 3];
|
|
909
|
+
const b = tokensAny[i - 1];
|
|
910
|
+
const content = String(a.content ?? "") + String(b.content ?? "") + nextTokenContent;
|
|
882
911
|
fixedTokens.splice(i - 3, 5, {
|
|
883
912
|
type: "text",
|
|
884
913
|
content,
|
|
@@ -888,7 +917,9 @@ function fixLinkToken4(tokens) {
|
|
|
888
917
|
}
|
|
889
918
|
} else {
|
|
890
919
|
if (tokens[i - 1].type === "text" && tokens[i - 3].type === "text") {
|
|
891
|
-
const
|
|
920
|
+
const a = tokensAny[i - 3];
|
|
921
|
+
const b = tokensAny[i - 1];
|
|
922
|
+
const content = String(a.content ?? "") + String(b.content ?? "");
|
|
892
923
|
fixedTokens.splice(i - 3, 4, {
|
|
893
924
|
type: "text",
|
|
894
925
|
content,
|
|
@@ -906,7 +937,8 @@ function fixLinkToken4(tokens) {
|
|
|
906
937
|
//#region src/parser/inline-parsers/fixListItem.ts
|
|
907
938
|
function fixListItem(tokens) {
|
|
908
939
|
const last = tokens[tokens.length - 1];
|
|
909
|
-
|
|
940
|
+
const lastContent = String(last?.content ?? "");
|
|
941
|
+
if (last?.type === "text" && /^\s*\d+\.\s*$/.test(lastContent) && tokens[tokens.length - 2]?.tag === "br") tokens.splice(tokens.length - 1, 1);
|
|
910
942
|
return tokens;
|
|
911
943
|
}
|
|
912
944
|
|
|
@@ -918,7 +950,8 @@ function fixStrongTokens(tokens) {
|
|
|
918
950
|
const i = tokens.length - 4;
|
|
919
951
|
const token = tokens[i];
|
|
920
952
|
const nextToken = tokens[i + 1];
|
|
921
|
-
|
|
953
|
+
const tokenContent = String(token.content ?? "");
|
|
954
|
+
if (token.type === "text" && tokenContent.endsWith("*") && nextToken.type === "em_open") {
|
|
922
955
|
const _nextToken = tokens[i + 2];
|
|
923
956
|
const count = _nextToken?.type === "text" ? 4 : 3;
|
|
924
957
|
const insert = [
|
|
@@ -935,7 +968,7 @@ function fixStrongTokens(tokens) {
|
|
|
935
968
|
},
|
|
936
969
|
{
|
|
937
970
|
type: "text",
|
|
938
|
-
content: _nextToken?.type === "text" ? _nextToken.content : ""
|
|
971
|
+
content: _nextToken?.type === "text" ? String(_nextToken.content ?? "") : ""
|
|
939
972
|
},
|
|
940
973
|
{
|
|
941
974
|
type: "strong_close",
|
|
@@ -949,7 +982,7 @@ function fixStrongTokens(tokens) {
|
|
|
949
982
|
meta: null
|
|
950
983
|
}
|
|
951
984
|
];
|
|
952
|
-
const beforeText =
|
|
985
|
+
const beforeText = tokenContent.slice(0, -1);
|
|
953
986
|
if (beforeText) insert.unshift({
|
|
954
987
|
type: "text",
|
|
955
988
|
content: beforeText,
|
|
@@ -964,10 +997,11 @@ function fixStrongTokens(tokens) {
|
|
|
964
997
|
//#endregion
|
|
965
998
|
//#region src/parser/inline-parsers/footnote-ref-parser.ts
|
|
966
999
|
function parseFootnoteRefToken(token) {
|
|
1000
|
+
const tokenMeta = token.meta ?? {};
|
|
967
1001
|
return {
|
|
968
1002
|
type: "footnote_reference",
|
|
969
|
-
id:
|
|
970
|
-
raw: `[^${
|
|
1003
|
+
id: String(tokenMeta.label ?? ""),
|
|
1004
|
+
raw: `[^${String(tokenMeta.label ?? "")}]`
|
|
971
1005
|
};
|
|
972
1006
|
}
|
|
973
1007
|
|
|
@@ -988,7 +1022,7 @@ function parseHighlightToken(tokens, startIndex) {
|
|
|
988
1022
|
let i = startIndex + 1;
|
|
989
1023
|
const innerTokens = [];
|
|
990
1024
|
while (i < tokens.length && tokens[i].type !== "mark_close") {
|
|
991
|
-
markText += tokens[i].content
|
|
1025
|
+
markText += String(tokens[i].content ?? "");
|
|
992
1026
|
innerTokens.push(tokens[i]);
|
|
993
1027
|
i++;
|
|
994
1028
|
}
|
|
@@ -1006,12 +1040,33 @@ function parseHighlightToken(tokens, startIndex) {
|
|
|
1006
1040
|
//#endregion
|
|
1007
1041
|
//#region src/parser/inline-parsers/image-parser.ts
|
|
1008
1042
|
function parseImageToken(token, loading = false) {
|
|
1043
|
+
let attrs = token.attrs ?? [];
|
|
1044
|
+
let childWithAttrs = null;
|
|
1045
|
+
if ((!attrs || attrs.length === 0) && Array.isArray(token.children)) for (const child of token.children) {
|
|
1046
|
+
const childAttrs = child?.attrs;
|
|
1047
|
+
if (Array.isArray(childAttrs) && childAttrs.length > 0) {
|
|
1048
|
+
attrs = childAttrs;
|
|
1049
|
+
childWithAttrs = child;
|
|
1050
|
+
break;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
const src = String(attrs.find((attr) => attr[0] === "src")?.[1] ?? "");
|
|
1054
|
+
const altAttr = attrs.find((attr) => attr[0] === "alt")?.[1];
|
|
1055
|
+
let alt = "";
|
|
1056
|
+
if (altAttr != null && String(altAttr).length > 0) alt = String(altAttr);
|
|
1057
|
+
else if (childWithAttrs?.content != null && String(childWithAttrs.content).length > 0) alt = String(childWithAttrs.content);
|
|
1058
|
+
else if (Array.isArray(childWithAttrs?.children) && childWithAttrs.children[0]?.content) alt = String(childWithAttrs.children[0].content);
|
|
1059
|
+
else if (Array.isArray(token.children) && token.children[0]?.content) alt = String(token.children[0].content);
|
|
1060
|
+
else if (token.content != null && String(token.content).length > 0) alt = String(token.content);
|
|
1061
|
+
const _title = attrs.find((attr) => attr[0] === "title")?.[1] ?? null;
|
|
1062
|
+
const title = _title === null ? null : String(_title);
|
|
1063
|
+
const raw = String(token.content ?? "");
|
|
1009
1064
|
return {
|
|
1010
1065
|
type: "image",
|
|
1011
|
-
src
|
|
1012
|
-
alt
|
|
1013
|
-
title
|
|
1014
|
-
raw
|
|
1066
|
+
src,
|
|
1067
|
+
alt,
|
|
1068
|
+
title,
|
|
1069
|
+
raw,
|
|
1015
1070
|
loading
|
|
1016
1071
|
};
|
|
1017
1072
|
}
|
|
@@ -1019,10 +1074,11 @@ function parseImageToken(token, loading = false) {
|
|
|
1019
1074
|
//#endregion
|
|
1020
1075
|
//#region src/parser/inline-parsers/inline-code-parser.ts
|
|
1021
1076
|
function parseInlineCodeToken(token) {
|
|
1077
|
+
const code = String(token.content ?? "");
|
|
1022
1078
|
return {
|
|
1023
1079
|
type: "inline_code",
|
|
1024
|
-
code
|
|
1025
|
-
raw:
|
|
1080
|
+
code,
|
|
1081
|
+
raw: code
|
|
1026
1082
|
};
|
|
1027
1083
|
}
|
|
1028
1084
|
|
|
@@ -1034,7 +1090,7 @@ function parseInsertToken(tokens, startIndex) {
|
|
|
1034
1090
|
let i = startIndex + 1;
|
|
1035
1091
|
const innerTokens = [];
|
|
1036
1092
|
while (i < tokens.length && tokens[i].type !== "ins_close") {
|
|
1037
|
-
insText += tokens[i].content
|
|
1093
|
+
insText += String(tokens[i].content ?? "");
|
|
1038
1094
|
innerTokens.push(tokens[i]);
|
|
1039
1095
|
i++;
|
|
1040
1096
|
}
|
|
@@ -1043,7 +1099,7 @@ function parseInsertToken(tokens, startIndex) {
|
|
|
1043
1099
|
node: {
|
|
1044
1100
|
type: "insert",
|
|
1045
1101
|
children,
|
|
1046
|
-
raw: `++${insText}++`
|
|
1102
|
+
raw: `++${String(insText)}++`
|
|
1047
1103
|
},
|
|
1048
1104
|
nextIndex: i < tokens.length ? i + 1 : tokens.length
|
|
1049
1105
|
};
|
|
@@ -1052,9 +1108,10 @@ function parseInsertToken(tokens, startIndex) {
|
|
|
1052
1108
|
//#endregion
|
|
1053
1109
|
//#region src/parser/inline-parsers/link-parser.ts
|
|
1054
1110
|
function parseLinkToken(tokens, startIndex) {
|
|
1055
|
-
const
|
|
1056
|
-
const href =
|
|
1057
|
-
const
|
|
1111
|
+
const attrs = tokens[startIndex].attrs ?? [];
|
|
1112
|
+
const href = String(attrs.find((attr) => attr[0] === "href")?.[1] ?? "");
|
|
1113
|
+
const _title = attrs.find((attr) => attr[0] === "title")?.[1] ?? null;
|
|
1114
|
+
const title = _title === null ? null : String(_title);
|
|
1058
1115
|
let i = startIndex + 1;
|
|
1059
1116
|
const linkTokens = [];
|
|
1060
1117
|
const loading = true;
|
|
@@ -1064,8 +1121,9 @@ function parseLinkToken(tokens, startIndex) {
|
|
|
1064
1121
|
}
|
|
1065
1122
|
const children = parseInlineTokens(linkTokens);
|
|
1066
1123
|
const linkText = children.map((node) => {
|
|
1067
|
-
|
|
1068
|
-
return
|
|
1124
|
+
const nodeAny = node;
|
|
1125
|
+
if ("content" in node) return String(nodeAny.content ?? "");
|
|
1126
|
+
return String(nodeAny.raw ?? "");
|
|
1069
1127
|
}).join("");
|
|
1070
1128
|
return {
|
|
1071
1129
|
node: {
|
|
@@ -1074,7 +1132,7 @@ function parseLinkToken(tokens, startIndex) {
|
|
|
1074
1132
|
title,
|
|
1075
1133
|
text: linkText,
|
|
1076
1134
|
children,
|
|
1077
|
-
raw: `[${linkText}](${href}${title ? ` "${title}"` : ""})
|
|
1135
|
+
raw: String(`[${linkText}](${href}${title ? ` "${title}"` : ""})`),
|
|
1078
1136
|
loading
|
|
1079
1137
|
},
|
|
1080
1138
|
nextIndex: i < tokens.length ? i + 1 : tokens.length
|
|
@@ -1086,7 +1144,7 @@ function parseLinkToken(tokens, startIndex) {
|
|
|
1086
1144
|
function parseMathInlineToken(token) {
|
|
1087
1145
|
return {
|
|
1088
1146
|
type: "math_inline",
|
|
1089
|
-
content: token.content
|
|
1147
|
+
content: String(token.content ?? ""),
|
|
1090
1148
|
loading: !!token.loading,
|
|
1091
1149
|
raw: token.raw
|
|
1092
1150
|
};
|
|
@@ -1097,8 +1155,8 @@ function parseMathInlineToken(token) {
|
|
|
1097
1155
|
function parseReferenceToken(token) {
|
|
1098
1156
|
return {
|
|
1099
1157
|
type: "reference",
|
|
1100
|
-
id: token.content
|
|
1101
|
-
raw: token.markup
|
|
1158
|
+
id: String(token.content ?? ""),
|
|
1159
|
+
raw: String(token.markup ?? `[${token.content ?? ""}]`)
|
|
1102
1160
|
};
|
|
1103
1161
|
}
|
|
1104
1162
|
|
|
@@ -1110,7 +1168,7 @@ function parseStrikethroughToken(tokens, startIndex) {
|
|
|
1110
1168
|
let i = startIndex + 1;
|
|
1111
1169
|
const innerTokens = [];
|
|
1112
1170
|
while (i < tokens.length && tokens[i].type !== "s_close") {
|
|
1113
|
-
sText += tokens[i].content
|
|
1171
|
+
sText += String(tokens[i].content ?? "");
|
|
1114
1172
|
innerTokens.push(tokens[i]);
|
|
1115
1173
|
i++;
|
|
1116
1174
|
}
|
|
@@ -1133,7 +1191,7 @@ function parseStrongToken(tokens, startIndex, raw) {
|
|
|
1133
1191
|
let i = startIndex + 1;
|
|
1134
1192
|
const innerTokens = [];
|
|
1135
1193
|
while (i < tokens.length && tokens[i].type !== "strong_close") {
|
|
1136
|
-
strongText += tokens[i].content
|
|
1194
|
+
strongText += String(tokens[i].content ?? "");
|
|
1137
1195
|
innerTokens.push(tokens[i]);
|
|
1138
1196
|
i++;
|
|
1139
1197
|
}
|
|
@@ -1142,7 +1200,7 @@ function parseStrongToken(tokens, startIndex, raw) {
|
|
|
1142
1200
|
node: {
|
|
1143
1201
|
type: "strong",
|
|
1144
1202
|
children,
|
|
1145
|
-
raw: `**${strongText}**`
|
|
1203
|
+
raw: `**${String(strongText)}**`
|
|
1146
1204
|
},
|
|
1147
1205
|
nextIndex: i < tokens.length ? i + 1 : tokens.length
|
|
1148
1206
|
};
|
|
@@ -1156,20 +1214,22 @@ function parseSubscriptToken(tokens, startIndex) {
|
|
|
1156
1214
|
let i = startIndex + 1;
|
|
1157
1215
|
const innerTokens = [];
|
|
1158
1216
|
while (i < tokens.length && tokens[i].type !== "sub_close") {
|
|
1159
|
-
subText += tokens[i].content
|
|
1217
|
+
subText += String(tokens[i].content ?? "");
|
|
1160
1218
|
innerTokens.push(tokens[i]);
|
|
1161
1219
|
i++;
|
|
1162
1220
|
}
|
|
1163
1221
|
children.push(...parseInlineTokens(innerTokens));
|
|
1222
|
+
const startContent = String(tokens[startIndex].content ?? "");
|
|
1223
|
+
const display = subText || startContent;
|
|
1164
1224
|
return {
|
|
1165
1225
|
node: {
|
|
1166
1226
|
type: "subscript",
|
|
1167
1227
|
children: children.length > 0 ? children : [{
|
|
1168
1228
|
type: "text",
|
|
1169
|
-
content:
|
|
1170
|
-
raw:
|
|
1229
|
+
content: display,
|
|
1230
|
+
raw: display
|
|
1171
1231
|
}],
|
|
1172
|
-
raw: `~${
|
|
1232
|
+
raw: `~${display}~`
|
|
1173
1233
|
},
|
|
1174
1234
|
nextIndex: i < tokens.length ? i + 1 : tokens.length
|
|
1175
1235
|
};
|
|
@@ -1183,7 +1243,7 @@ function parseSuperscriptToken(tokens, startIndex) {
|
|
|
1183
1243
|
let i = startIndex + 1;
|
|
1184
1244
|
const innerTokens = [];
|
|
1185
1245
|
while (i < tokens.length && tokens[i].type !== "sup_close") {
|
|
1186
|
-
supText += tokens[i].content
|
|
1246
|
+
supText += String(tokens[i].content ?? "");
|
|
1187
1247
|
innerTokens.push(tokens[i]);
|
|
1188
1248
|
i++;
|
|
1189
1249
|
}
|
|
@@ -1193,10 +1253,10 @@ function parseSuperscriptToken(tokens, startIndex) {
|
|
|
1193
1253
|
type: "superscript",
|
|
1194
1254
|
children: children.length > 0 ? children : [{
|
|
1195
1255
|
type: "text",
|
|
1196
|
-
content: supText || tokens[startIndex].content
|
|
1197
|
-
raw: supText || tokens[startIndex].content
|
|
1256
|
+
content: supText || String(tokens[startIndex].content ?? ""),
|
|
1257
|
+
raw: supText || String(tokens[startIndex].content ?? "")
|
|
1198
1258
|
}],
|
|
1199
|
-
raw: `^${supText || tokens[startIndex].content
|
|
1259
|
+
raw: `^${supText || String(tokens[startIndex].content ?? "")}^`
|
|
1200
1260
|
},
|
|
1201
1261
|
nextIndex: i < tokens.length ? i + 1 : tokens.length
|
|
1202
1262
|
};
|
|
@@ -1205,10 +1265,11 @@ function parseSuperscriptToken(tokens, startIndex) {
|
|
|
1205
1265
|
//#endregion
|
|
1206
1266
|
//#region src/parser/inline-parsers/text-parser.ts
|
|
1207
1267
|
function parseTextToken(token) {
|
|
1268
|
+
const content = String(token.content ?? "");
|
|
1208
1269
|
return {
|
|
1209
1270
|
type: "text",
|
|
1210
|
-
content
|
|
1211
|
-
raw:
|
|
1271
|
+
content,
|
|
1272
|
+
raw: content
|
|
1212
1273
|
};
|
|
1213
1274
|
}
|
|
1214
1275
|
|
|
@@ -1222,314 +1283,232 @@ function parseInlineTokens(tokens, raw, pPreToken) {
|
|
|
1222
1283
|
tokens = fixStrongTokens(tokens);
|
|
1223
1284
|
tokens = fixListItem(tokens);
|
|
1224
1285
|
tokens = fixLinkToken(tokens);
|
|
1286
|
+
function resetCurrentTextNode() {
|
|
1287
|
+
currentTextNode = null;
|
|
1288
|
+
}
|
|
1289
|
+
function handleEmphasisAndStrikethrough(content, token) {
|
|
1290
|
+
if (/[^~]*~{2,}[^~]+/.test(content)) {
|
|
1291
|
+
let idx = content.indexOf("~~");
|
|
1292
|
+
if (idx === -1) idx = 0;
|
|
1293
|
+
const _text = content.slice(0, idx);
|
|
1294
|
+
if (_text) if (currentTextNode) {
|
|
1295
|
+
currentTextNode.content += _text;
|
|
1296
|
+
currentTextNode.raw += _text;
|
|
1297
|
+
} else {
|
|
1298
|
+
currentTextNode = {
|
|
1299
|
+
type: "text",
|
|
1300
|
+
content: String(_text ?? ""),
|
|
1301
|
+
raw: String(token.content ?? "")
|
|
1302
|
+
};
|
|
1303
|
+
result.push(currentTextNode);
|
|
1304
|
+
}
|
|
1305
|
+
const { node } = parseStrikethroughToken([
|
|
1306
|
+
{
|
|
1307
|
+
type: "s_open",
|
|
1308
|
+
tag: "s",
|
|
1309
|
+
content: "",
|
|
1310
|
+
markup: "*",
|
|
1311
|
+
info: "",
|
|
1312
|
+
meta: null
|
|
1313
|
+
},
|
|
1314
|
+
{
|
|
1315
|
+
type: "text",
|
|
1316
|
+
tag: "",
|
|
1317
|
+
content: content.slice(idx).replace(/~/g, ""),
|
|
1318
|
+
markup: "",
|
|
1319
|
+
info: "",
|
|
1320
|
+
meta: null
|
|
1321
|
+
},
|
|
1322
|
+
{
|
|
1323
|
+
type: "s_close",
|
|
1324
|
+
tag: "s",
|
|
1325
|
+
content: "",
|
|
1326
|
+
markup: "*",
|
|
1327
|
+
info: "",
|
|
1328
|
+
meta: null
|
|
1329
|
+
}
|
|
1330
|
+
], 0);
|
|
1331
|
+
resetCurrentTextNode();
|
|
1332
|
+
pushNode(node);
|
|
1333
|
+
i++;
|
|
1334
|
+
return true;
|
|
1335
|
+
}
|
|
1336
|
+
if (/\*\*/.test(content)) {
|
|
1337
|
+
const openIdx = content.indexOf("**");
|
|
1338
|
+
const beforeText = openIdx > -1 ? content.slice(0, openIdx) : "";
|
|
1339
|
+
if (beforeText) pushText(beforeText, beforeText);
|
|
1340
|
+
if (openIdx === -1) {
|
|
1341
|
+
i++;
|
|
1342
|
+
return true;
|
|
1343
|
+
}
|
|
1344
|
+
const exec = /\*\*([\s\S]*?)\*\*/.exec(content);
|
|
1345
|
+
let inner = "";
|
|
1346
|
+
let after = "";
|
|
1347
|
+
if (exec && typeof exec.index === "number") {
|
|
1348
|
+
inner = exec[1];
|
|
1349
|
+
after = content.slice(exec.index + exec[0].length);
|
|
1350
|
+
} else {
|
|
1351
|
+
inner = content.slice(openIdx + 2);
|
|
1352
|
+
after = "";
|
|
1353
|
+
}
|
|
1354
|
+
const { node } = parseStrongToken([
|
|
1355
|
+
{
|
|
1356
|
+
type: "strong_open",
|
|
1357
|
+
tag: "strong",
|
|
1358
|
+
content: "",
|
|
1359
|
+
markup: "*",
|
|
1360
|
+
info: "",
|
|
1361
|
+
meta: null
|
|
1362
|
+
},
|
|
1363
|
+
{
|
|
1364
|
+
type: "text",
|
|
1365
|
+
tag: "",
|
|
1366
|
+
content: inner,
|
|
1367
|
+
markup: "",
|
|
1368
|
+
info: "",
|
|
1369
|
+
meta: null
|
|
1370
|
+
},
|
|
1371
|
+
{
|
|
1372
|
+
type: "strong_close",
|
|
1373
|
+
tag: "strong",
|
|
1374
|
+
content: "",
|
|
1375
|
+
markup: "*",
|
|
1376
|
+
info: "",
|
|
1377
|
+
meta: null
|
|
1378
|
+
}
|
|
1379
|
+
], 0, raw);
|
|
1380
|
+
resetCurrentTextNode();
|
|
1381
|
+
pushNode(node);
|
|
1382
|
+
if (after) {
|
|
1383
|
+
handleToken({
|
|
1384
|
+
type: "text",
|
|
1385
|
+
content: after,
|
|
1386
|
+
raw: after
|
|
1387
|
+
});
|
|
1388
|
+
i--;
|
|
1389
|
+
}
|
|
1390
|
+
i++;
|
|
1391
|
+
return true;
|
|
1392
|
+
}
|
|
1393
|
+
if (/[^*]*\*[^*]+/.test(content)) {
|
|
1394
|
+
let idx = content.indexOf("*");
|
|
1395
|
+
if (idx === -1) idx = 0;
|
|
1396
|
+
const _text = content.slice(0, idx);
|
|
1397
|
+
if (_text) if (currentTextNode) {
|
|
1398
|
+
currentTextNode.content += _text;
|
|
1399
|
+
currentTextNode.raw += _text;
|
|
1400
|
+
} else {
|
|
1401
|
+
currentTextNode = {
|
|
1402
|
+
type: "text",
|
|
1403
|
+
content: String(_text ?? ""),
|
|
1404
|
+
raw: String(token.content ?? "")
|
|
1405
|
+
};
|
|
1406
|
+
result.push(currentTextNode);
|
|
1407
|
+
}
|
|
1408
|
+
const { node } = parseEmphasisToken([
|
|
1409
|
+
{
|
|
1410
|
+
type: "em_open",
|
|
1411
|
+
tag: "em",
|
|
1412
|
+
content: "",
|
|
1413
|
+
markup: "*",
|
|
1414
|
+
info: "",
|
|
1415
|
+
meta: null
|
|
1416
|
+
},
|
|
1417
|
+
{
|
|
1418
|
+
type: "text",
|
|
1419
|
+
tag: "",
|
|
1420
|
+
content: content.slice(idx).replace(/\*/g, ""),
|
|
1421
|
+
markup: "",
|
|
1422
|
+
info: "",
|
|
1423
|
+
meta: null
|
|
1424
|
+
},
|
|
1425
|
+
{
|
|
1426
|
+
type: "em_close",
|
|
1427
|
+
tag: "em",
|
|
1428
|
+
content: "",
|
|
1429
|
+
markup: "*",
|
|
1430
|
+
info: "",
|
|
1431
|
+
meta: null
|
|
1432
|
+
}
|
|
1433
|
+
], 0);
|
|
1434
|
+
resetCurrentTextNode();
|
|
1435
|
+
pushNode(node);
|
|
1436
|
+
i++;
|
|
1437
|
+
return true;
|
|
1438
|
+
}
|
|
1439
|
+
return false;
|
|
1440
|
+
}
|
|
1441
|
+
function handleInlineCodeContent(content, _token) {
|
|
1442
|
+
if (!/`[^`]*/.test(content)) return false;
|
|
1443
|
+
resetCurrentTextNode();
|
|
1444
|
+
const code_start = content.indexOf("`");
|
|
1445
|
+
const code_end = content.indexOf("`", code_start + 1);
|
|
1446
|
+
const _text = content.slice(0, code_start);
|
|
1447
|
+
const codeContent = code_end === -1 ? content.slice(code_start) : content.slice(code_start, code_end);
|
|
1448
|
+
const after = code_end === -1 ? "" : content.slice(code_end + 1);
|
|
1449
|
+
if (_text) if (!handleEmphasisAndStrikethrough(_text, _token)) pushText(_text, _text);
|
|
1450
|
+
else i--;
|
|
1451
|
+
const code = codeContent.replace(/`/g, "");
|
|
1452
|
+
pushParsed({
|
|
1453
|
+
type: "inline_code",
|
|
1454
|
+
code,
|
|
1455
|
+
raw: String(code ?? "")
|
|
1456
|
+
});
|
|
1457
|
+
if (after) {
|
|
1458
|
+
handleToken({
|
|
1459
|
+
type: "text",
|
|
1460
|
+
content: after,
|
|
1461
|
+
raw: String(after ?? "")
|
|
1462
|
+
});
|
|
1463
|
+
i--;
|
|
1464
|
+
} else if (code_end === -1) {
|
|
1465
|
+
if (tokens[i + 1]) {
|
|
1466
|
+
let fixedAfter = after;
|
|
1467
|
+
for (let j = i + 1; j < tokens.length; j++) fixedAfter += String((tokens[j].content ?? "") + (tokens[j].markup ?? ""));
|
|
1468
|
+
i = tokens.length - 1;
|
|
1469
|
+
handleToken({
|
|
1470
|
+
type: "text",
|
|
1471
|
+
content: fixedAfter,
|
|
1472
|
+
raw: String(fixedAfter ?? "")
|
|
1473
|
+
});
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
i++;
|
|
1477
|
+
return true;
|
|
1478
|
+
}
|
|
1479
|
+
function pushParsed(node) {
|
|
1480
|
+
resetCurrentTextNode();
|
|
1481
|
+
result.push(node);
|
|
1482
|
+
}
|
|
1483
|
+
function pushToken(token) {
|
|
1484
|
+
resetCurrentTextNode();
|
|
1485
|
+
result.push(token);
|
|
1486
|
+
}
|
|
1487
|
+
function pushNode(node) {
|
|
1488
|
+
pushParsed(node);
|
|
1489
|
+
}
|
|
1490
|
+
function pushText(content, raw$1) {
|
|
1491
|
+
if (currentTextNode) {
|
|
1492
|
+
currentTextNode.content += content;
|
|
1493
|
+
currentTextNode.raw += raw$1 ?? content;
|
|
1494
|
+
} else {
|
|
1495
|
+
currentTextNode = {
|
|
1496
|
+
type: "text",
|
|
1497
|
+
content: String(content ?? ""),
|
|
1498
|
+
raw: String(raw$1 ?? content ?? "")
|
|
1499
|
+
};
|
|
1500
|
+
result.push(currentTextNode);
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1225
1503
|
while (i < tokens.length) {
|
|
1226
1504
|
const token = tokens[i];
|
|
1227
1505
|
handleToken(token);
|
|
1228
1506
|
}
|
|
1229
1507
|
function handleToken(token) {
|
|
1230
1508
|
switch (token.type) {
|
|
1231
|
-
case "text":
|
|
1232
|
-
|
|
1233
|
-
let content = token.content.replace(/\\/g, "") || "";
|
|
1234
|
-
if (content.startsWith(")") && result[result.length - 1]?.type === "link") content = content.slice(1);
|
|
1235
|
-
for (; index >= 0; index--) {
|
|
1236
|
-
const item = result[index];
|
|
1237
|
-
if (item.type === "text") {
|
|
1238
|
-
currentTextNode = null;
|
|
1239
|
-
content = item.content + content;
|
|
1240
|
-
continue;
|
|
1241
|
-
}
|
|
1242
|
-
break;
|
|
1243
|
-
}
|
|
1244
|
-
if (index < result.length - 1) result.splice(index + 1);
|
|
1245
|
-
const nextToken = tokens[i + 1];
|
|
1246
|
-
if (content === "`" || content === "|" || content === "$" || content === "1" || /^\*+$/.test(content) || /^\d$/.test(content)) {
|
|
1247
|
-
i++;
|
|
1248
|
-
break;
|
|
1249
|
-
}
|
|
1250
|
-
if (!nextToken && /[^\]]\s*\(\s*$/.test(content)) content = content.replace(/\(\s*$/, "");
|
|
1251
|
-
if (raw?.startsWith("[") && pPreToken?.type === "list_item_open") {
|
|
1252
|
-
const w = content.slice(1).match(/[^\s\]]/);
|
|
1253
|
-
if (w === null) {
|
|
1254
|
-
i++;
|
|
1255
|
-
break;
|
|
1256
|
-
}
|
|
1257
|
-
if (w && /x/i.test(w[0]) || !w) {
|
|
1258
|
-
const checked = w ? w[0] === "x" || w[0] === "X" : false;
|
|
1259
|
-
result.push({
|
|
1260
|
-
type: "checkbox_input",
|
|
1261
|
-
checked,
|
|
1262
|
-
raw: checked ? "[x]" : "[ ]"
|
|
1263
|
-
});
|
|
1264
|
-
i++;
|
|
1265
|
-
break;
|
|
1266
|
-
}
|
|
1267
|
-
}
|
|
1268
|
-
if (/`[^`]*/.test(content)) {
|
|
1269
|
-
currentTextNode = null;
|
|
1270
|
-
const index$1 = content.indexOf("`");
|
|
1271
|
-
const _text = content.slice(0, index$1);
|
|
1272
|
-
const codeContent = content.slice(index$1);
|
|
1273
|
-
if (_text) result.push({
|
|
1274
|
-
type: "text",
|
|
1275
|
-
content: _text || "",
|
|
1276
|
-
raw: _text || ""
|
|
1277
|
-
});
|
|
1278
|
-
result.push({
|
|
1279
|
-
type: "inline_code",
|
|
1280
|
-
code: codeContent.replace(/`/g, ""),
|
|
1281
|
-
raw: codeContent || ""
|
|
1282
|
-
});
|
|
1283
|
-
i++;
|
|
1284
|
-
break;
|
|
1285
|
-
}
|
|
1286
|
-
if (content === "[") {
|
|
1287
|
-
i++;
|
|
1288
|
-
break;
|
|
1289
|
-
}
|
|
1290
|
-
if (/[^~]*~{2,}[^~]+/.test(content)) {
|
|
1291
|
-
const index$1 = content.indexOf("~~") || 0;
|
|
1292
|
-
const _text = content.slice(0, index$1);
|
|
1293
|
-
if (_text) if (currentTextNode) {
|
|
1294
|
-
currentTextNode.content += _text;
|
|
1295
|
-
currentTextNode.raw += _text;
|
|
1296
|
-
} else {
|
|
1297
|
-
currentTextNode = {
|
|
1298
|
-
type: "text",
|
|
1299
|
-
content: _text || "",
|
|
1300
|
-
raw: token.content || ""
|
|
1301
|
-
};
|
|
1302
|
-
result.push(currentTextNode);
|
|
1303
|
-
}
|
|
1304
|
-
const strikethroughContent = content.slice(index$1);
|
|
1305
|
-
currentTextNode = null;
|
|
1306
|
-
const { node } = parseStrikethroughToken([
|
|
1307
|
-
{
|
|
1308
|
-
type: "s_open",
|
|
1309
|
-
tag: "s",
|
|
1310
|
-
content: "",
|
|
1311
|
-
markup: "*",
|
|
1312
|
-
info: "",
|
|
1313
|
-
meta: null
|
|
1314
|
-
},
|
|
1315
|
-
{
|
|
1316
|
-
type: "text",
|
|
1317
|
-
tag: "",
|
|
1318
|
-
content: strikethroughContent.replace(/~/g, ""),
|
|
1319
|
-
markup: "",
|
|
1320
|
-
info: "",
|
|
1321
|
-
meta: null
|
|
1322
|
-
},
|
|
1323
|
-
{
|
|
1324
|
-
type: "s_close",
|
|
1325
|
-
tag: "s",
|
|
1326
|
-
content: "",
|
|
1327
|
-
markup: "*",
|
|
1328
|
-
info: "",
|
|
1329
|
-
meta: null
|
|
1330
|
-
}
|
|
1331
|
-
], 0);
|
|
1332
|
-
result.push(node);
|
|
1333
|
-
i++;
|
|
1334
|
-
break;
|
|
1335
|
-
}
|
|
1336
|
-
if (/[^*]*\*\*[^*]+/.test(content)) {
|
|
1337
|
-
const index$1 = content.indexOf("*") || 0;
|
|
1338
|
-
const _text = content.slice(0, index$1);
|
|
1339
|
-
if (_text) if (currentTextNode) {
|
|
1340
|
-
currentTextNode.content += _text;
|
|
1341
|
-
currentTextNode.raw += _text;
|
|
1342
|
-
} else {
|
|
1343
|
-
currentTextNode = {
|
|
1344
|
-
type: "text",
|
|
1345
|
-
content: _text || "",
|
|
1346
|
-
raw: token.content || ""
|
|
1347
|
-
};
|
|
1348
|
-
result.push(currentTextNode);
|
|
1349
|
-
}
|
|
1350
|
-
const strongContent = content.slice(index$1);
|
|
1351
|
-
currentTextNode = null;
|
|
1352
|
-
const { node } = parseStrongToken([
|
|
1353
|
-
{
|
|
1354
|
-
type: "strong_open",
|
|
1355
|
-
tag: "strong",
|
|
1356
|
-
content: "",
|
|
1357
|
-
markup: "*",
|
|
1358
|
-
info: "",
|
|
1359
|
-
meta: null
|
|
1360
|
-
},
|
|
1361
|
-
{
|
|
1362
|
-
type: "text",
|
|
1363
|
-
tag: "",
|
|
1364
|
-
content: strongContent.replace(/\*/g, ""),
|
|
1365
|
-
markup: "",
|
|
1366
|
-
info: "",
|
|
1367
|
-
meta: null
|
|
1368
|
-
},
|
|
1369
|
-
{
|
|
1370
|
-
type: "strong_close",
|
|
1371
|
-
tag: "strong",
|
|
1372
|
-
content: "",
|
|
1373
|
-
markup: "*",
|
|
1374
|
-
info: "",
|
|
1375
|
-
meta: null
|
|
1376
|
-
}
|
|
1377
|
-
], 0, raw);
|
|
1378
|
-
result.push(node);
|
|
1379
|
-
i++;
|
|
1380
|
-
break;
|
|
1381
|
-
} else if (/[^*]*\*[^*]+/.test(content)) {
|
|
1382
|
-
const index$1 = content.indexOf("*") || 0;
|
|
1383
|
-
const _text = content.slice(0, index$1);
|
|
1384
|
-
if (_text) if (currentTextNode) {
|
|
1385
|
-
currentTextNode.content += _text;
|
|
1386
|
-
currentTextNode.raw += _text;
|
|
1387
|
-
} else {
|
|
1388
|
-
currentTextNode = {
|
|
1389
|
-
type: "text",
|
|
1390
|
-
content: _text || "",
|
|
1391
|
-
raw: token.content || ""
|
|
1392
|
-
};
|
|
1393
|
-
result.push(currentTextNode);
|
|
1394
|
-
}
|
|
1395
|
-
const emphasisContent = content.slice(index$1);
|
|
1396
|
-
currentTextNode = null;
|
|
1397
|
-
const { node } = parseEmphasisToken([
|
|
1398
|
-
{
|
|
1399
|
-
type: "em_open",
|
|
1400
|
-
tag: "em",
|
|
1401
|
-
content: "",
|
|
1402
|
-
markup: "*",
|
|
1403
|
-
info: "",
|
|
1404
|
-
meta: null
|
|
1405
|
-
},
|
|
1406
|
-
{
|
|
1407
|
-
type: "text",
|
|
1408
|
-
tag: "",
|
|
1409
|
-
content: emphasisContent.replace(/\*/g, ""),
|
|
1410
|
-
markup: "",
|
|
1411
|
-
info: "",
|
|
1412
|
-
meta: null
|
|
1413
|
-
},
|
|
1414
|
-
{
|
|
1415
|
-
type: "em_close",
|
|
1416
|
-
tag: "em",
|
|
1417
|
-
content: "",
|
|
1418
|
-
markup: "*",
|
|
1419
|
-
info: "",
|
|
1420
|
-
meta: null
|
|
1421
|
-
}
|
|
1422
|
-
], 0);
|
|
1423
|
-
result.push(node);
|
|
1424
|
-
i++;
|
|
1425
|
-
break;
|
|
1426
|
-
}
|
|
1427
|
-
const imageStart = content.indexOf(";
|
|
1451
|
-
if (linkEnd !== -1) {
|
|
1452
|
-
const textToken = tokens[i + 2];
|
|
1453
|
-
let text = content.slice(linkStart + 1, linkEnd);
|
|
1454
|
-
if (text.includes("[")) {
|
|
1455
|
-
const secondLinkStart = text.indexOf("[");
|
|
1456
|
-
linkStart = linkStart + secondLinkStart + 1;
|
|
1457
|
-
textNodeContent += content.slice(0, linkStart);
|
|
1458
|
-
text = content.slice(linkStart + 1, linkEnd);
|
|
1459
|
-
}
|
|
1460
|
-
if (content.endsWith("](") && nextToken?.type === "link_open" && textToken) {
|
|
1461
|
-
const last = tokens[i + 4];
|
|
1462
|
-
let index$1 = 4;
|
|
1463
|
-
let loading$1 = true;
|
|
1464
|
-
if (last?.type === "text" && last.content === ")") {
|
|
1465
|
-
index$1++;
|
|
1466
|
-
loading$1 = false;
|
|
1467
|
-
} else if (last?.type === "text" && last.content === ".") i++;
|
|
1468
|
-
if (textNodeContent) result.push({
|
|
1469
|
-
type: "text",
|
|
1470
|
-
content: textNodeContent,
|
|
1471
|
-
raw: textNodeContent
|
|
1472
|
-
});
|
|
1473
|
-
result.push({
|
|
1474
|
-
type: "link",
|
|
1475
|
-
href: textToken.content || "",
|
|
1476
|
-
text,
|
|
1477
|
-
children: [{
|
|
1478
|
-
type: "text",
|
|
1479
|
-
content: text,
|
|
1480
|
-
raw: text
|
|
1481
|
-
}],
|
|
1482
|
-
loading: loading$1
|
|
1483
|
-
});
|
|
1484
|
-
i += index$1;
|
|
1485
|
-
break;
|
|
1486
|
-
}
|
|
1487
|
-
const linkContentEnd = content.indexOf(")", linkEnd);
|
|
1488
|
-
const href = linkContentEnd !== -1 ? content.slice(linkEnd + 2, linkContentEnd) : "";
|
|
1489
|
-
const loading = linkContentEnd === -1;
|
|
1490
|
-
if (textNodeContent) result.push({
|
|
1491
|
-
type: "text",
|
|
1492
|
-
content: textNodeContent,
|
|
1493
|
-
raw: textNodeContent
|
|
1494
|
-
});
|
|
1495
|
-
result.push({
|
|
1496
|
-
type: "link",
|
|
1497
|
-
href,
|
|
1498
|
-
text,
|
|
1499
|
-
children: [{
|
|
1500
|
-
type: "text",
|
|
1501
|
-
content: text,
|
|
1502
|
-
raw: text
|
|
1503
|
-
}],
|
|
1504
|
-
loading
|
|
1505
|
-
});
|
|
1506
|
-
const afterText = linkContentEnd !== -1 ? content.slice(linkContentEnd + 1) : "";
|
|
1507
|
-
if (afterText) {
|
|
1508
|
-
handleToken({
|
|
1509
|
-
type: "text",
|
|
1510
|
-
content: afterText,
|
|
1511
|
-
raw: afterText
|
|
1512
|
-
});
|
|
1513
|
-
i--;
|
|
1514
|
-
}
|
|
1515
|
-
i++;
|
|
1516
|
-
break;
|
|
1517
|
-
}
|
|
1518
|
-
}
|
|
1519
|
-
const preToken = tokens[i - 1];
|
|
1520
|
-
if (currentTextNode) {
|
|
1521
|
-
currentTextNode.content += textNode.content.replace(/(\*+|\(|\\)$/, "");
|
|
1522
|
-
currentTextNode.raw += textNode.raw;
|
|
1523
|
-
} else {
|
|
1524
|
-
const maybeMath = preToken?.tag === "br" && tokens[i - 2]?.content === "[";
|
|
1525
|
-
if (!tokens[i + 1]) textNode.content = textNode.content.replace(/(\*+|\(|\\)$/, "");
|
|
1526
|
-
currentTextNode = textNode;
|
|
1527
|
-
currentTextNode.center = maybeMath;
|
|
1528
|
-
result.push(currentTextNode);
|
|
1529
|
-
}
|
|
1530
|
-
i++;
|
|
1509
|
+
case "text":
|
|
1510
|
+
handleTextToken(token);
|
|
1531
1511
|
break;
|
|
1532
|
-
}
|
|
1533
1512
|
case "softbreak":
|
|
1534
1513
|
if (currentTextNode) {
|
|
1535
1514
|
currentTextNode.content += "\n";
|
|
@@ -1538,193 +1517,358 @@ function parseInlineTokens(tokens, raw, pPreToken) {
|
|
|
1538
1517
|
i++;
|
|
1539
1518
|
break;
|
|
1540
1519
|
case "code_inline":
|
|
1541
|
-
|
|
1542
|
-
result.push(parseInlineCodeToken(token));
|
|
1520
|
+
pushNode(parseInlineCodeToken(token));
|
|
1543
1521
|
i++;
|
|
1544
1522
|
break;
|
|
1545
|
-
case "link_open":
|
|
1546
|
-
|
|
1547
|
-
const href = token.attrs?.find((attr) => attr[0] === "href")?.[1];
|
|
1548
|
-
if (raw && tokens[i + 1].type === "text") {
|
|
1549
|
-
const text = tokens[i + 1]?.content || "";
|
|
1550
|
-
if (!(/* @__PURE__ */ new RegExp(`\\[${text}\\s*\\]`)).test(raw)) {
|
|
1551
|
-
result.push({
|
|
1552
|
-
type: "text",
|
|
1553
|
-
content: text,
|
|
1554
|
-
raw: text
|
|
1555
|
-
});
|
|
1556
|
-
i += 3;
|
|
1557
|
-
break;
|
|
1558
|
-
}
|
|
1559
|
-
}
|
|
1560
|
-
if (raw && href) {
|
|
1561
|
-
const loadingMath = /* @__PURE__ */ new RegExp(`\\(\\s*${href}\\s*\\)`);
|
|
1562
|
-
const pre = result.length > 0 ? result[result.length - 1] : null;
|
|
1563
|
-
const loading = !loadingMath.test(raw);
|
|
1564
|
-
if (loading && pre) {
|
|
1565
|
-
if ((/* @__PURE__ */ new RegExp(`\\[${pre.text}\\s*\\]\\(`)).test(raw)) {
|
|
1566
|
-
const text = pre?.text || pre?.content?.slice(1, -1) || "";
|
|
1567
|
-
result.splice(result.length - 1, 1, {
|
|
1568
|
-
type: "link",
|
|
1569
|
-
href: "",
|
|
1570
|
-
text,
|
|
1571
|
-
loading
|
|
1572
|
-
});
|
|
1573
|
-
i += 3;
|
|
1574
|
-
if (tokens[i]?.content === ".") i++;
|
|
1575
|
-
break;
|
|
1576
|
-
}
|
|
1577
|
-
}
|
|
1578
|
-
}
|
|
1579
|
-
const { node, nextIndex } = parseLinkToken(tokens, i);
|
|
1580
|
-
i = nextIndex;
|
|
1581
|
-
node.loading = false;
|
|
1582
|
-
result.push(node);
|
|
1523
|
+
case "link_open":
|
|
1524
|
+
handleLinkOpen(token);
|
|
1583
1525
|
break;
|
|
1584
|
-
}
|
|
1585
1526
|
case "image":
|
|
1586
|
-
|
|
1587
|
-
|
|
1527
|
+
resetCurrentTextNode();
|
|
1528
|
+
pushNode(parseImageToken(token));
|
|
1588
1529
|
i++;
|
|
1589
1530
|
break;
|
|
1590
1531
|
case "strong_open": {
|
|
1591
|
-
|
|
1532
|
+
resetCurrentTextNode();
|
|
1592
1533
|
const { node, nextIndex } = parseStrongToken(tokens, i, token.content);
|
|
1593
|
-
|
|
1534
|
+
pushNode(node);
|
|
1594
1535
|
i = nextIndex;
|
|
1595
1536
|
break;
|
|
1596
1537
|
}
|
|
1597
1538
|
case "em_open": {
|
|
1598
|
-
|
|
1539
|
+
resetCurrentTextNode();
|
|
1599
1540
|
const { node, nextIndex } = parseEmphasisToken(tokens, i);
|
|
1600
|
-
|
|
1541
|
+
pushNode(node);
|
|
1601
1542
|
i = nextIndex;
|
|
1602
1543
|
break;
|
|
1603
1544
|
}
|
|
1604
1545
|
case "s_open": {
|
|
1605
|
-
|
|
1546
|
+
resetCurrentTextNode();
|
|
1606
1547
|
const { node, nextIndex } = parseStrikethroughToken(tokens, i);
|
|
1607
|
-
|
|
1548
|
+
pushNode(node);
|
|
1608
1549
|
i = nextIndex;
|
|
1609
1550
|
break;
|
|
1610
1551
|
}
|
|
1611
1552
|
case "mark_open": {
|
|
1612
|
-
|
|
1553
|
+
resetCurrentTextNode();
|
|
1613
1554
|
const { node, nextIndex } = parseHighlightToken(tokens, i);
|
|
1614
|
-
|
|
1555
|
+
pushNode(node);
|
|
1615
1556
|
i = nextIndex;
|
|
1616
1557
|
break;
|
|
1617
1558
|
}
|
|
1618
1559
|
case "ins_open": {
|
|
1619
|
-
|
|
1560
|
+
resetCurrentTextNode();
|
|
1620
1561
|
const { node, nextIndex } = parseInsertToken(tokens, i);
|
|
1621
|
-
|
|
1562
|
+
pushNode(node);
|
|
1622
1563
|
i = nextIndex;
|
|
1623
1564
|
break;
|
|
1624
1565
|
}
|
|
1625
1566
|
case "sub_open": {
|
|
1626
|
-
|
|
1567
|
+
resetCurrentTextNode();
|
|
1627
1568
|
const { node, nextIndex } = parseSubscriptToken(tokens, i);
|
|
1628
|
-
|
|
1569
|
+
pushNode(node);
|
|
1629
1570
|
i = nextIndex;
|
|
1630
1571
|
break;
|
|
1631
1572
|
}
|
|
1632
1573
|
case "sup_open": {
|
|
1633
|
-
|
|
1574
|
+
resetCurrentTextNode();
|
|
1634
1575
|
const { node, nextIndex } = parseSuperscriptToken(tokens, i);
|
|
1635
|
-
|
|
1576
|
+
pushNode(node);
|
|
1636
1577
|
i = nextIndex;
|
|
1637
1578
|
break;
|
|
1638
1579
|
}
|
|
1639
1580
|
case "sub":
|
|
1640
|
-
|
|
1641
|
-
|
|
1581
|
+
resetCurrentTextNode();
|
|
1582
|
+
pushNode({
|
|
1642
1583
|
type: "subscript",
|
|
1643
1584
|
children: [{
|
|
1644
1585
|
type: "text",
|
|
1645
|
-
content: token.content
|
|
1646
|
-
raw: token.content
|
|
1586
|
+
content: String(token.content ?? ""),
|
|
1587
|
+
raw: String(token.content ?? "")
|
|
1647
1588
|
}],
|
|
1648
|
-
raw: `~${token.content
|
|
1589
|
+
raw: `~${String(token.content ?? "")}~`
|
|
1649
1590
|
});
|
|
1650
1591
|
i++;
|
|
1651
1592
|
break;
|
|
1652
1593
|
case "sup":
|
|
1653
|
-
|
|
1654
|
-
|
|
1594
|
+
resetCurrentTextNode();
|
|
1595
|
+
pushNode({
|
|
1655
1596
|
type: "superscript",
|
|
1656
1597
|
children: [{
|
|
1657
1598
|
type: "text",
|
|
1658
|
-
content: token.content
|
|
1659
|
-
raw: token.content
|
|
1599
|
+
content: String(token.content ?? ""),
|
|
1600
|
+
raw: String(token.content ?? "")
|
|
1660
1601
|
}],
|
|
1661
|
-
raw: `^${token.content
|
|
1602
|
+
raw: `^${String(token.content ?? "")}^`
|
|
1662
1603
|
});
|
|
1663
1604
|
i++;
|
|
1664
1605
|
break;
|
|
1665
1606
|
case "emoji": {
|
|
1666
|
-
|
|
1607
|
+
resetCurrentTextNode();
|
|
1667
1608
|
const preToken = tokens[i - 1];
|
|
1668
|
-
if (preToken?.type === "text" && /\|:-+/.test(preToken.content
|
|
1669
|
-
|
|
1670
|
-
content: "",
|
|
1671
|
-
raw: ""
|
|
1672
|
-
});
|
|
1673
|
-
else result.push(parseEmojiToken(token));
|
|
1609
|
+
if (preToken?.type === "text" && /\|:-+/.test(String(preToken.content ?? ""))) pushText("", "");
|
|
1610
|
+
else pushNode(parseEmojiToken(token));
|
|
1674
1611
|
i++;
|
|
1675
1612
|
break;
|
|
1676
1613
|
}
|
|
1677
1614
|
case "checkbox":
|
|
1678
|
-
|
|
1679
|
-
|
|
1615
|
+
resetCurrentTextNode();
|
|
1616
|
+
pushNode(parseCheckboxToken(token));
|
|
1680
1617
|
i++;
|
|
1681
1618
|
break;
|
|
1682
1619
|
case "checkbox_input":
|
|
1683
|
-
|
|
1684
|
-
|
|
1620
|
+
resetCurrentTextNode();
|
|
1621
|
+
pushNode(parseCheckboxInputToken(token));
|
|
1685
1622
|
i++;
|
|
1686
1623
|
break;
|
|
1687
1624
|
case "footnote_ref":
|
|
1688
|
-
|
|
1689
|
-
|
|
1625
|
+
resetCurrentTextNode();
|
|
1626
|
+
pushNode(parseFootnoteRefToken(token));
|
|
1690
1627
|
i++;
|
|
1691
1628
|
break;
|
|
1692
1629
|
case "hardbreak":
|
|
1693
|
-
|
|
1694
|
-
|
|
1630
|
+
resetCurrentTextNode();
|
|
1631
|
+
pushNode(parseHardbreakToken());
|
|
1695
1632
|
i++;
|
|
1696
1633
|
break;
|
|
1697
1634
|
case "fence":
|
|
1698
|
-
|
|
1699
|
-
|
|
1635
|
+
resetCurrentTextNode();
|
|
1636
|
+
pushNode(parseFenceToken(tokens[i]));
|
|
1700
1637
|
i++;
|
|
1701
1638
|
break;
|
|
1702
1639
|
case "math_inline":
|
|
1703
|
-
|
|
1704
|
-
|
|
1640
|
+
resetCurrentTextNode();
|
|
1641
|
+
pushNode(parseMathInlineToken(token));
|
|
1705
1642
|
i++;
|
|
1706
1643
|
break;
|
|
1707
|
-
case "reference":
|
|
1708
|
-
|
|
1709
|
-
const nextToken = tokens[i + 1];
|
|
1710
|
-
const preToken = tokens[i - 1];
|
|
1711
|
-
const preResult = result[result.length - 1];
|
|
1712
|
-
if (nextToken?.type === "text" && !nextToken.content?.startsWith("(") || preToken.type === "text" && /\]$|^\s*$/.test(preToken.content || "")) result.push(parseReferenceToken(token));
|
|
1713
|
-
else if (nextToken && nextToken.type === "text") nextToken.content = token.markup + nextToken.content;
|
|
1714
|
-
else if (preResult.type === "text") {
|
|
1715
|
-
preResult.content = preResult.content + token.markup;
|
|
1716
|
-
preResult.raw = preResult.raw + token.markup;
|
|
1717
|
-
}
|
|
1718
|
-
i++;
|
|
1644
|
+
case "reference":
|
|
1645
|
+
handleReference(token);
|
|
1719
1646
|
break;
|
|
1720
|
-
}
|
|
1721
1647
|
default:
|
|
1722
|
-
|
|
1723
|
-
currentTextNode = null;
|
|
1648
|
+
pushToken(token);
|
|
1724
1649
|
i++;
|
|
1725
1650
|
break;
|
|
1726
1651
|
}
|
|
1727
1652
|
}
|
|
1653
|
+
function handleTextToken(token) {
|
|
1654
|
+
let index = result.length - 1;
|
|
1655
|
+
let content = String(token.content ?? "").replace(/\\/g, "");
|
|
1656
|
+
if (content.startsWith(")") && result[result.length - 1]?.type === "link") content = content.slice(1);
|
|
1657
|
+
if (content.endsWith("undefined") && !raw?.endsWith("undefined")) content = content.slice(0, -9);
|
|
1658
|
+
for (; index >= 0; index--) {
|
|
1659
|
+
const item = result[index];
|
|
1660
|
+
if (item.type === "text") {
|
|
1661
|
+
currentTextNode = null;
|
|
1662
|
+
content = item.content + content;
|
|
1663
|
+
continue;
|
|
1664
|
+
}
|
|
1665
|
+
break;
|
|
1666
|
+
}
|
|
1667
|
+
if (index < result.length - 1) result.splice(index + 1);
|
|
1668
|
+
const nextToken = tokens[i + 1];
|
|
1669
|
+
if (content === "`" || content === "|" || content === "$" || content === "1" || /^\*+$/.test(content) || /^\d$/.test(content)) {
|
|
1670
|
+
i++;
|
|
1671
|
+
return;
|
|
1672
|
+
}
|
|
1673
|
+
if (!nextToken && /[^\]]\s*\(\s*$/.test(content)) content = content.replace(/\(\s*$/, "");
|
|
1674
|
+
if (handleCheckboxLike(content)) return;
|
|
1675
|
+
if (content === "[") {
|
|
1676
|
+
i++;
|
|
1677
|
+
return;
|
|
1678
|
+
}
|
|
1679
|
+
if (handleInlineCodeContent(content, token)) return;
|
|
1680
|
+
if (handleEmphasisAndStrikethrough(content, token)) return;
|
|
1681
|
+
if (handleInlineImageContent(content, token)) return;
|
|
1682
|
+
const textNode = parseTextToken({
|
|
1683
|
+
...token,
|
|
1684
|
+
content
|
|
1685
|
+
});
|
|
1686
|
+
if (handleInlineLinkContent(content, token)) return;
|
|
1687
|
+
const preToken = tokens[i - 1];
|
|
1688
|
+
if (currentTextNode) {
|
|
1689
|
+
currentTextNode.content += textNode.content.replace(/(\*+|\(|\\)$/, "");
|
|
1690
|
+
currentTextNode.raw += textNode.raw;
|
|
1691
|
+
} else {
|
|
1692
|
+
const maybeMath = preToken?.tag === "br" && tokens[i - 2]?.content === "[";
|
|
1693
|
+
if (!tokens[i + 1]) textNode.content = textNode.content.replace(/(\*+|\(|\\)$/, "");
|
|
1694
|
+
currentTextNode = textNode;
|
|
1695
|
+
currentTextNode.center = maybeMath;
|
|
1696
|
+
result.push(currentTextNode);
|
|
1697
|
+
}
|
|
1698
|
+
i++;
|
|
1699
|
+
}
|
|
1700
|
+
function handleLinkOpen(token) {
|
|
1701
|
+
resetCurrentTextNode();
|
|
1702
|
+
const href = token.attrs?.find(([name]) => name === "href")?.[1];
|
|
1703
|
+
function escapeRegExp(str) {
|
|
1704
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1705
|
+
}
|
|
1706
|
+
if (raw && tokens[i + 1].type === "text") {
|
|
1707
|
+
const text = String(tokens[i + 1]?.content ?? "");
|
|
1708
|
+
const escText = escapeRegExp(text);
|
|
1709
|
+
if (!(/* @__PURE__ */ new RegExp(`\\[${escText}\\s*\\]`)).test(raw)) {
|
|
1710
|
+
pushText(text, text);
|
|
1711
|
+
i += 3;
|
|
1712
|
+
return;
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
if (raw && href) {
|
|
1716
|
+
const loadingMath = /* @__PURE__ */ new RegExp(`\\(\\s*${escapeRegExp(href)}\\s*\\)`);
|
|
1717
|
+
const pre = result.length > 0 ? result[result.length - 1] : void 0;
|
|
1718
|
+
const loading = !loadingMath.test(raw);
|
|
1719
|
+
if (loading && pre) {
|
|
1720
|
+
let preText = "";
|
|
1721
|
+
if (pre) {
|
|
1722
|
+
if (pre.type === "link") preText = String(pre.text ?? "");
|
|
1723
|
+
else if (pre.type === "text") preText = String(pre.content ?? "");
|
|
1724
|
+
else if (pre.content && typeof pre.content === "string") preText = String(pre.content ?? "").slice(1, -1);
|
|
1725
|
+
}
|
|
1726
|
+
if ((/* @__PURE__ */ new RegExp(`\\[${escapeRegExp(preText)}\\s*\\]\\(`)).test(raw)) {
|
|
1727
|
+
const text = String(preText ?? "");
|
|
1728
|
+
resetCurrentTextNode();
|
|
1729
|
+
const node$1 = {
|
|
1730
|
+
type: "link",
|
|
1731
|
+
href: "",
|
|
1732
|
+
title: null,
|
|
1733
|
+
text,
|
|
1734
|
+
children: [{
|
|
1735
|
+
type: "text",
|
|
1736
|
+
content: text,
|
|
1737
|
+
raw: text
|
|
1738
|
+
}],
|
|
1739
|
+
loading
|
|
1740
|
+
};
|
|
1741
|
+
result.splice(result.length - 1, 1, node$1);
|
|
1742
|
+
i += 3;
|
|
1743
|
+
if (String(tokens[i]?.content ?? "") === ".") i++;
|
|
1744
|
+
return;
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
const { node, nextIndex } = parseLinkToken(tokens, i);
|
|
1749
|
+
i = nextIndex;
|
|
1750
|
+
node.loading = false;
|
|
1751
|
+
pushParsed(node);
|
|
1752
|
+
}
|
|
1753
|
+
function handleReference(token) {
|
|
1754
|
+
resetCurrentTextNode();
|
|
1755
|
+
const nextToken = tokens[i + 1];
|
|
1756
|
+
const preToken = tokens[i - 1];
|
|
1757
|
+
const preResult = result[result.length - 1];
|
|
1758
|
+
const nextIsTextNotStartingParens = nextToken?.type === "text" && !String(nextToken.content ?? "").startsWith("(");
|
|
1759
|
+
const preIsTextEndingBracketOrOnlySpace = preToken?.type === "text" && /\]$|^\s*$/.test(String(preToken.content ?? ""));
|
|
1760
|
+
if (nextIsTextNotStartingParens || preIsTextEndingBracketOrOnlySpace) pushNode(parseReferenceToken(token));
|
|
1761
|
+
else if (nextToken && nextToken.type === "text") nextToken.content = String(token.markup ?? "") + String(nextToken.content ?? "");
|
|
1762
|
+
else if (preResult && preResult.type === "text") {
|
|
1763
|
+
preResult.content = String(preResult.content ?? "") + String(token.markup ?? "");
|
|
1764
|
+
preResult.raw = String(preResult.raw ?? "") + String(token.markup ?? "");
|
|
1765
|
+
}
|
|
1766
|
+
i++;
|
|
1767
|
+
}
|
|
1768
|
+
function handleInlineLinkContent(content, _token) {
|
|
1769
|
+
const linkStart = content.indexOf("[");
|
|
1770
|
+
if (linkStart === -1) return false;
|
|
1771
|
+
let textNodeContent = content.slice(0, linkStart);
|
|
1772
|
+
const linkEnd = content.indexOf("](", linkStart);
|
|
1773
|
+
if (linkEnd !== -1) {
|
|
1774
|
+
const textToken = tokens[i + 2];
|
|
1775
|
+
let text = content.slice(linkStart + 1, linkEnd);
|
|
1776
|
+
if (text.includes("[")) {
|
|
1777
|
+
const secondLinkStart = text.indexOf("[");
|
|
1778
|
+
textNodeContent += content.slice(0, linkStart + secondLinkStart + 1);
|
|
1779
|
+
const newLinkStart = linkStart + secondLinkStart + 1;
|
|
1780
|
+
text = content.slice(newLinkStart + 1, linkEnd);
|
|
1781
|
+
}
|
|
1782
|
+
const nextToken = tokens[i + 1];
|
|
1783
|
+
if (content.endsWith("](") && nextToken?.type === "link_open" && textToken) {
|
|
1784
|
+
const last = tokens[i + 4];
|
|
1785
|
+
let index = 4;
|
|
1786
|
+
let loading$1 = true;
|
|
1787
|
+
if (last?.type === "text" && last.content === ")") {
|
|
1788
|
+
index++;
|
|
1789
|
+
loading$1 = false;
|
|
1790
|
+
} else if (last?.type === "text" && last.content === ".") i++;
|
|
1791
|
+
if (textNodeContent) pushText(textNodeContent, textNodeContent);
|
|
1792
|
+
pushParsed({
|
|
1793
|
+
type: "link",
|
|
1794
|
+
href: String(textToken.content ?? ""),
|
|
1795
|
+
title: null,
|
|
1796
|
+
text,
|
|
1797
|
+
children: [{
|
|
1798
|
+
type: "text",
|
|
1799
|
+
content: text,
|
|
1800
|
+
raw: text
|
|
1801
|
+
}],
|
|
1802
|
+
loading: loading$1
|
|
1803
|
+
});
|
|
1804
|
+
i += index;
|
|
1805
|
+
return true;
|
|
1806
|
+
}
|
|
1807
|
+
const linkContentEnd = content.indexOf(")", linkEnd);
|
|
1808
|
+
const href = linkContentEnd !== -1 ? content.slice(linkEnd + 2, linkContentEnd) : "";
|
|
1809
|
+
const loading = linkContentEnd === -1;
|
|
1810
|
+
if (textNodeContent) pushText(textNodeContent, textNodeContent);
|
|
1811
|
+
pushParsed({
|
|
1812
|
+
type: "link",
|
|
1813
|
+
href,
|
|
1814
|
+
title: null,
|
|
1815
|
+
text,
|
|
1816
|
+
children: [{
|
|
1817
|
+
type: "text",
|
|
1818
|
+
content: text,
|
|
1819
|
+
raw: text
|
|
1820
|
+
}],
|
|
1821
|
+
loading
|
|
1822
|
+
});
|
|
1823
|
+
const afterText = linkContentEnd !== -1 ? content.slice(linkContentEnd + 1) : "";
|
|
1824
|
+
if (afterText) {
|
|
1825
|
+
handleToken({
|
|
1826
|
+
type: "text",
|
|
1827
|
+
content: afterText,
|
|
1828
|
+
raw: afterText
|
|
1829
|
+
});
|
|
1830
|
+
i--;
|
|
1831
|
+
}
|
|
1832
|
+
i++;
|
|
1833
|
+
return true;
|
|
1834
|
+
}
|
|
1835
|
+
return false;
|
|
1836
|
+
}
|
|
1837
|
+
function handleInlineImageContent(content, token) {
|
|
1838
|
+
const imageStart = content.indexOf("![");
|
|
1839
|
+
if (imageStart === -1) return false;
|
|
1840
|
+
const textNodeContent = content.slice(0, imageStart);
|
|
1841
|
+
if (!currentTextNode) currentTextNode = {
|
|
1842
|
+
type: "text",
|
|
1843
|
+
content: textNodeContent,
|
|
1844
|
+
raw: textNodeContent
|
|
1845
|
+
};
|
|
1846
|
+
else currentTextNode.content += textNodeContent;
|
|
1847
|
+
result.push(currentTextNode);
|
|
1848
|
+
currentTextNode = null;
|
|
1849
|
+
pushParsed(parseImageToken(token, true));
|
|
1850
|
+
i++;
|
|
1851
|
+
return true;
|
|
1852
|
+
}
|
|
1853
|
+
function handleCheckboxLike(content) {
|
|
1854
|
+
if (!(content?.startsWith("[") && pPreToken?.type === "list_item_open")) return false;
|
|
1855
|
+
const w = content.slice(1).match(/[^\s\]]/);
|
|
1856
|
+
if (w === null) {
|
|
1857
|
+
i++;
|
|
1858
|
+
return true;
|
|
1859
|
+
}
|
|
1860
|
+
if (w && /x/i.test(w[0])) {
|
|
1861
|
+
const checked = w[0] === "x" || w[0] === "X";
|
|
1862
|
+
pushParsed({
|
|
1863
|
+
type: "checkbox_input",
|
|
1864
|
+
checked,
|
|
1865
|
+
raw: checked ? "[x]" : "[ ]"
|
|
1866
|
+
});
|
|
1867
|
+
i++;
|
|
1868
|
+
return true;
|
|
1869
|
+
}
|
|
1870
|
+
return false;
|
|
1871
|
+
}
|
|
1728
1872
|
return result;
|
|
1729
1873
|
}
|
|
1730
1874
|
|
|
@@ -1738,7 +1882,7 @@ function parseBlockquote(tokens, index) {
|
|
|
1738
1882
|
blockquoteChildren.push({
|
|
1739
1883
|
type: "paragraph",
|
|
1740
1884
|
children: parseInlineTokens(contentToken.children || []),
|
|
1741
|
-
raw: contentToken.content
|
|
1885
|
+
raw: String(contentToken.content ?? "")
|
|
1742
1886
|
});
|
|
1743
1887
|
j += 3;
|
|
1744
1888
|
} else if (tokens[j].type === "bullet_list_open" || tokens[j].type === "ordered_list_open") {
|
|
@@ -1757,14 +1901,15 @@ function parseBlockquote(tokens, index) {
|
|
|
1757
1901
|
//#region src/parser/node-parsers/code-block-parser.ts
|
|
1758
1902
|
function parseCodeBlock(token) {
|
|
1759
1903
|
if (token.info?.startsWith("diff")) return parseFenceToken(token);
|
|
1760
|
-
const
|
|
1761
|
-
|
|
1904
|
+
const contentStr = String(token.content ?? "");
|
|
1905
|
+
const match = contentStr.match(/ type="application\/vnd\.ant\.([^"]+)"/);
|
|
1906
|
+
if (match?.[1]) token.content = contentStr.replace(/<antArtifact[^>]*>/g, "").replace(/<\/antArtifact>/g, "");
|
|
1762
1907
|
const hasMap = Array.isArray(token.map) && token.map.length === 2;
|
|
1763
1908
|
return {
|
|
1764
1909
|
type: "code_block",
|
|
1765
|
-
language: match ? match[1] : token.info
|
|
1766
|
-
code: token.content
|
|
1767
|
-
raw: token.content
|
|
1910
|
+
language: match ? match[1] : String(token.info ?? ""),
|
|
1911
|
+
code: String(token.content ?? ""),
|
|
1912
|
+
raw: String(token.content ?? ""),
|
|
1768
1913
|
loading: !hasMap
|
|
1769
1914
|
};
|
|
1770
1915
|
}
|
|
@@ -1787,8 +1932,8 @@ function parseDefinitionList(tokens, index) {
|
|
|
1787
1932
|
const contentToken = tokens[k + 1];
|
|
1788
1933
|
definitionNodes.push({
|
|
1789
1934
|
type: "paragraph",
|
|
1790
|
-
children: parseInlineTokens(contentToken.children || [], contentToken.content
|
|
1791
|
-
raw: contentToken.content
|
|
1935
|
+
children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? "")),
|
|
1936
|
+
raw: String(contentToken.content ?? "")
|
|
1792
1937
|
});
|
|
1793
1938
|
k += 3;
|
|
1794
1939
|
} else k++;
|
|
@@ -1813,7 +1958,8 @@ function parseDefinitionList(tokens, index) {
|
|
|
1813
1958
|
//#endregion
|
|
1814
1959
|
//#region src/parser/node-parsers/footnote-parser.ts
|
|
1815
1960
|
function parseFootnote(tokens, index) {
|
|
1816
|
-
const
|
|
1961
|
+
const meta = tokens[index].meta ?? {};
|
|
1962
|
+
const id = String(meta?.label ?? "0");
|
|
1817
1963
|
const footnoteChildren = [];
|
|
1818
1964
|
let j = index + 1;
|
|
1819
1965
|
while (j < tokens.length && tokens[j].type !== "footnote_close") if (tokens[j].type === "paragraph_open") {
|
|
@@ -1821,7 +1967,7 @@ function parseFootnote(tokens, index) {
|
|
|
1821
1967
|
footnoteChildren.push({
|
|
1822
1968
|
type: "paragraph",
|
|
1823
1969
|
children: parseInlineTokens(contentToken.children || []),
|
|
1824
|
-
raw: contentToken.content
|
|
1970
|
+
raw: String(contentToken.content ?? "")
|
|
1825
1971
|
});
|
|
1826
1972
|
j += 3;
|
|
1827
1973
|
} else j++;
|
|
@@ -1837,9 +1983,10 @@ function parseFootnote(tokens, index) {
|
|
|
1837
1983
|
//#region src/parser/node-parsers/heading-parser.ts
|
|
1838
1984
|
function parseHeading(tokens, index) {
|
|
1839
1985
|
const token = tokens[index];
|
|
1840
|
-
const
|
|
1986
|
+
const levelStr = String(token.tag?.substring(1) ?? "1");
|
|
1987
|
+
const headingLevel = Number.parseInt(levelStr, 10);
|
|
1841
1988
|
const headingContentToken = tokens[index + 1];
|
|
1842
|
-
const headingContent = headingContentToken.content
|
|
1989
|
+
const headingContent = String(headingContentToken.content ?? "");
|
|
1843
1990
|
return {
|
|
1844
1991
|
type: "heading",
|
|
1845
1992
|
level: headingLevel,
|
|
@@ -1854,9 +2001,9 @@ function parseHeading(tokens, index) {
|
|
|
1854
2001
|
function parseMathBlock(token) {
|
|
1855
2002
|
return {
|
|
1856
2003
|
type: "math_block",
|
|
1857
|
-
content: token.content
|
|
2004
|
+
content: String(token.content ?? ""),
|
|
1858
2005
|
loading: !!token.loading,
|
|
1859
|
-
raw: token.raw
|
|
2006
|
+
raw: String(token.raw ?? "")
|
|
1860
2007
|
};
|
|
1861
2008
|
}
|
|
1862
2009
|
|
|
@@ -1880,7 +2027,7 @@ function parseTable(tokens, index) {
|
|
|
1880
2027
|
while (k < tokens.length && tokens[k].type !== "tr_close") if (tokens[k].type === "th_open" || tokens[k].type === "td_open") {
|
|
1881
2028
|
const isHeaderCell = tokens[k].type === "th_open";
|
|
1882
2029
|
const contentToken = tokens[k + 1];
|
|
1883
|
-
const content = contentToken.content
|
|
2030
|
+
const content = String(contentToken.content ?? "");
|
|
1884
2031
|
cells.push({
|
|
1885
2032
|
type: "table_cell",
|
|
1886
2033
|
header: isHeaderCell || isHeader,
|
|
@@ -1907,7 +2054,7 @@ function parseTable(tokens, index) {
|
|
|
1907
2054
|
type: "table",
|
|
1908
2055
|
header: headerRow,
|
|
1909
2056
|
rows,
|
|
1910
|
-
loading: tokens[index].loading
|
|
2057
|
+
loading: tokens[index].loading ?? false,
|
|
1911
2058
|
raw: [headerRow, ...rows].map((row) => row.raw).join("\n")
|
|
1912
2059
|
}, j + 1];
|
|
1913
2060
|
}
|
|
@@ -1933,14 +2080,15 @@ function parseList(tokens, index) {
|
|
|
1933
2080
|
while (k < tokens.length && tokens[k].type !== "list_item_close") if (tokens[k].type === "paragraph_open") {
|
|
1934
2081
|
const contentToken = tokens[k + 1];
|
|
1935
2082
|
const preToken = tokens[k - 1];
|
|
1936
|
-
|
|
1937
|
-
|
|
2083
|
+
const contentStr = String(contentToken.content ?? "");
|
|
2084
|
+
if (/\n\d+$/.test(contentStr)) {
|
|
2085
|
+
contentToken.content = contentStr.replace(/\n\d+$/, "");
|
|
1938
2086
|
contentToken.children?.splice(-1, 1);
|
|
1939
2087
|
}
|
|
1940
2088
|
itemChildren.push({
|
|
1941
2089
|
type: "paragraph",
|
|
1942
|
-
children: parseInlineTokens(contentToken.children || [], contentToken.content
|
|
1943
|
-
raw: contentToken.content
|
|
2090
|
+
children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? ""), preToken),
|
|
2091
|
+
raw: String(contentToken.content ?? "")
|
|
1944
2092
|
});
|
|
1945
2093
|
k += 3;
|
|
1946
2094
|
} else if (tokens[k].type === "blockquote_open") {
|
|
@@ -1984,7 +2132,7 @@ function parseList(tokens, index) {
|
|
|
1984
2132
|
itemChildren.push(parseThematicBreak());
|
|
1985
2133
|
k += 1;
|
|
1986
2134
|
} else if (tokens[k].type === "container_open") {
|
|
1987
|
-
const match = /^::: ?(warning|info|note|tip|danger|caution) ?(.*)$/.exec(tokens[k].info
|
|
2135
|
+
const match = /^::: ?(warning|info|note|tip|danger|caution) ?(.*)$/.exec(String(tokens[k].info ?? ""));
|
|
1988
2136
|
if (match) {
|
|
1989
2137
|
const [admonitionNode, newIndex] = parseAdmonition(tokens, k, match);
|
|
1990
2138
|
itemChildren.push(admonitionNode);
|
|
@@ -2004,7 +2152,10 @@ function parseList(tokens, index) {
|
|
|
2004
2152
|
start: (() => {
|
|
2005
2153
|
if (token.attrs && token.attrs.length) {
|
|
2006
2154
|
const found = token.attrs.find((a) => a[0] === "start");
|
|
2007
|
-
if (found)
|
|
2155
|
+
if (found) {
|
|
2156
|
+
const parsed = Number(found[1]);
|
|
2157
|
+
return Number.isFinite(parsed) && parsed !== 0 ? parsed : 1;
|
|
2158
|
+
}
|
|
2008
2159
|
}
|
|
2009
2160
|
})(),
|
|
2010
2161
|
items: listItems,
|
|
@@ -2023,8 +2174,8 @@ function parseNestedList(tokens, index) {
|
|
|
2023
2174
|
const preToken = tokens[k - 1];
|
|
2024
2175
|
itemChildren.push({
|
|
2025
2176
|
type: "paragraph",
|
|
2026
|
-
children: parseInlineTokens(contentToken.children || [], contentToken.content
|
|
2027
|
-
raw: contentToken.content
|
|
2177
|
+
children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? ""), preToken),
|
|
2178
|
+
raw: String(contentToken.content ?? "")
|
|
2028
2179
|
});
|
|
2029
2180
|
k += 3;
|
|
2030
2181
|
} else if (tokens[k].type === "bullet_list_open" || tokens[k].type === "ordered_list_open") {
|
|
@@ -2058,7 +2209,10 @@ function parseNestedList(tokens, index) {
|
|
|
2058
2209
|
start: (() => {
|
|
2059
2210
|
if (nestedToken.attrs && nestedToken.attrs.length) {
|
|
2060
2211
|
const found = nestedToken.attrs.find((a) => a[0] === "start");
|
|
2061
|
-
if (found)
|
|
2212
|
+
if (found) {
|
|
2213
|
+
const parsed = Number(found[1]);
|
|
2214
|
+
return Number.isFinite(parsed) && parsed !== 0 ? parsed : 1;
|
|
2215
|
+
}
|
|
2062
2216
|
}
|
|
2063
2217
|
})(),
|
|
2064
2218
|
items: nestedItems,
|
|
@@ -2069,8 +2223,8 @@ function parseNestedList(tokens, index) {
|
|
|
2069
2223
|
//#endregion
|
|
2070
2224
|
//#region src/parser/node-parsers/admonition-parser.ts
|
|
2071
2225
|
function parseAdmonition(tokens, index, match) {
|
|
2072
|
-
const kind = match[1]
|
|
2073
|
-
const title = match[2]
|
|
2226
|
+
const kind = String(match[1] ?? "note");
|
|
2227
|
+
const title = String(match[2] ?? kind.charAt(0).toUpperCase() + kind.slice(1));
|
|
2074
2228
|
const admonitionChildren = [];
|
|
2075
2229
|
let j = index + 1;
|
|
2076
2230
|
while (j < tokens.length && tokens[j].type !== "container_close") if (tokens[j].type === "paragraph_open") {
|
|
@@ -2078,7 +2232,7 @@ function parseAdmonition(tokens, index, match) {
|
|
|
2078
2232
|
if (contentToken) admonitionChildren.push({
|
|
2079
2233
|
type: "paragraph",
|
|
2080
2234
|
children: parseInlineTokens(contentToken.children || []),
|
|
2081
|
-
raw: contentToken.content
|
|
2235
|
+
raw: String(contentToken.content ?? "")
|
|
2082
2236
|
});
|
|
2083
2237
|
j += 3;
|
|
2084
2238
|
} else if (tokens[j].type === "bullet_list_open" || tokens[j].type === "ordered_list_open") {
|
|
@@ -2104,17 +2258,17 @@ function parseContainer(tokens, index) {
|
|
|
2104
2258
|
const typeMatch = openToken.type.match(/^container_(\w+)_open$/);
|
|
2105
2259
|
if (typeMatch) {
|
|
2106
2260
|
kind = typeMatch[1];
|
|
2107
|
-
const info = (openToken.info
|
|
2261
|
+
const info = String(openToken.info ?? "").trim();
|
|
2108
2262
|
if (info && !info.startsWith(":::")) {
|
|
2109
2263
|
const maybe = info.replace(/* @__PURE__ */ new RegExp(`^${kind}`), "").trim();
|
|
2110
2264
|
if (maybe) title = maybe;
|
|
2111
2265
|
}
|
|
2112
2266
|
} else {
|
|
2113
|
-
const info = (openToken.info
|
|
2267
|
+
const info = String(openToken.info ?? "").trim();
|
|
2114
2268
|
const match = /^:{1,3}\s*(warning|info|note|tip|danger|caution)\s*(.*)$/i.exec(info);
|
|
2115
2269
|
if (match) {
|
|
2116
2270
|
kind = match[1];
|
|
2117
|
-
title = match[2]
|
|
2271
|
+
title = String(match[2] ?? "");
|
|
2118
2272
|
}
|
|
2119
2273
|
}
|
|
2120
2274
|
if (!title) title = kind.charAt(0).toUpperCase() + kind.slice(1);
|
|
@@ -2124,12 +2278,20 @@ function parseContainer(tokens, index) {
|
|
|
2124
2278
|
while (j < tokens.length && tokens[j].type !== "container_close" && !closeType.test(tokens[j].type)) if (tokens[j].type === "paragraph_open") {
|
|
2125
2279
|
const contentToken = tokens[j + 1];
|
|
2126
2280
|
if (contentToken) {
|
|
2127
|
-
const
|
|
2128
|
-
|
|
2281
|
+
const childrenArr = contentToken.children || [];
|
|
2282
|
+
let i = -1;
|
|
2283
|
+
for (let k = childrenArr.length - 1; k >= 0; k--) {
|
|
2284
|
+
const t = childrenArr[k];
|
|
2285
|
+
if (t.type === "text" && /:+/.test(t.content)) {
|
|
2286
|
+
i = k;
|
|
2287
|
+
break;
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
const _children = i !== -1 ? childrenArr.slice(0, i) : childrenArr;
|
|
2129
2291
|
children.push({
|
|
2130
2292
|
type: "paragraph",
|
|
2131
2293
|
children: parseInlineTokens(_children || []),
|
|
2132
|
-
raw: contentToken.content
|
|
2294
|
+
raw: String(contentToken.content ?? "").replace(/\n:+$/, "").replace(/\n\s*:::\s*$/, "")
|
|
2133
2295
|
});
|
|
2134
2296
|
}
|
|
2135
2297
|
j += 3;
|
|
@@ -2160,7 +2322,7 @@ function parseHardBreak() {
|
|
|
2160
2322
|
//#region src/parser/node-parsers/paragraph-parser.ts
|
|
2161
2323
|
function parseParagraph(tokens, index) {
|
|
2162
2324
|
const paragraphContentToken = tokens[index + 1];
|
|
2163
|
-
const paragraphContent = paragraphContentToken.content
|
|
2325
|
+
const paragraphContent = String(paragraphContentToken.content ?? "");
|
|
2164
2326
|
return {
|
|
2165
2327
|
type: "paragraph",
|
|
2166
2328
|
children: parseInlineTokens(paragraphContentToken.children || [], paragraphContent),
|
|
@@ -2182,7 +2344,15 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
|
|
|
2182
2344
|
let transformedTokens = tokens;
|
|
2183
2345
|
if (pre && typeof pre === "function") transformedTokens = pre(tokens) || tokens;
|
|
2184
2346
|
let result = processTokens(transformedTokens);
|
|
2185
|
-
if (post && typeof post === "function")
|
|
2347
|
+
if (post && typeof post === "function") {
|
|
2348
|
+
const postResult = post(transformedTokens);
|
|
2349
|
+
if (Array.isArray(postResult)) {
|
|
2350
|
+
const first = postResult[0];
|
|
2351
|
+
const firstType = first?.type;
|
|
2352
|
+
if (first && typeof firstType === "string") result = processTokens(postResult);
|
|
2353
|
+
else result = postResult;
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2186
2356
|
return result;
|
|
2187
2357
|
}
|
|
2188
2358
|
function processTokens(tokens) {
|
|
@@ -2258,7 +2428,7 @@ function processTokens(tokens) {
|
|
|
2258
2428
|
break;
|
|
2259
2429
|
}
|
|
2260
2430
|
case "container_open": {
|
|
2261
|
-
const match = /^::: ?(warning|info|note|tip|danger|caution|error) ?(.*)$/.exec(token.info
|
|
2431
|
+
const match = /^::: ?(warning|info|note|tip|danger|caution|error) ?(.*)$/.exec(String(token.info ?? ""));
|
|
2262
2432
|
if (match) {
|
|
2263
2433
|
const [admonitionNode, newIndex] = parseAdmonition(tokens, i, match);
|
|
2264
2434
|
result.push(admonitionNode);
|
|
@@ -2293,8 +2463,14 @@ function getMarkdown(msgId = `editor-${Date.now()}`, options = {}) {
|
|
|
2293
2463
|
const i18nMap = options.i18n;
|
|
2294
2464
|
t = (key) => i18nMap[key] ?? defaultTranslations[key] ?? key;
|
|
2295
2465
|
} else t = (key) => defaultTranslations[key] ?? key;
|
|
2296
|
-
if (Array.isArray(options.plugin)) for (const p of options.plugin)
|
|
2297
|
-
|
|
2466
|
+
if (Array.isArray(options.plugin)) for (const p of options.plugin) {
|
|
2467
|
+
const pluginItem = p;
|
|
2468
|
+
if (Array.isArray(pluginItem)) {
|
|
2469
|
+
const fn = pluginItem[0];
|
|
2470
|
+
const opts = pluginItem[1];
|
|
2471
|
+
if (typeof fn === "function") md.use(fn, opts);
|
|
2472
|
+
} else if (typeof pluginItem === "function") md.use(pluginItem);
|
|
2473
|
+
}
|
|
2298
2474
|
if (Array.isArray(options.apply)) for (const fn of options.apply) try {
|
|
2299
2475
|
fn(md);
|
|
2300
2476
|
} catch (e) {
|
|
@@ -2309,8 +2485,9 @@ function getMarkdown(msgId = `editor-${Date.now()}`, options = {}) {
|
|
|
2309
2485
|
md.use(markdownItIns);
|
|
2310
2486
|
md.use(markdownItFootnote);
|
|
2311
2487
|
md.core.ruler.after("block", "mark_fence_closed", (state) => {
|
|
2312
|
-
const
|
|
2313
|
-
|
|
2488
|
+
const s = state;
|
|
2489
|
+
const lines = s.src.split(/\r?\n/);
|
|
2490
|
+
for (const token of s.tokens) {
|
|
2314
2491
|
if (token.type !== "fence" || !token.map || !token.markup) continue;
|
|
2315
2492
|
const openLine = token.map[0];
|
|
2316
2493
|
const endLine = token.map[1];
|
|
@@ -2325,33 +2502,35 @@ function getMarkdown(msgId = `editor-${Date.now()}`, options = {}) {
|
|
|
2325
2502
|
let j = i + count;
|
|
2326
2503
|
while (j < line.length && (line[j] === " " || line[j] === " ")) j++;
|
|
2327
2504
|
const closed = endLine > openLine + 1 && count >= minLen && j === line.length;
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2505
|
+
const tokenShape = token;
|
|
2506
|
+
tokenShape.meta = tokenShape.meta ?? {};
|
|
2507
|
+
tokenShape.meta.unclosed = !closed;
|
|
2508
|
+
tokenShape.meta.closed = !!closed;
|
|
2331
2509
|
}
|
|
2332
2510
|
});
|
|
2333
2511
|
const waveRule = (state, silent) => {
|
|
2334
|
-
const
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
const
|
|
2512
|
+
const s = state;
|
|
2513
|
+
const start = s.pos;
|
|
2514
|
+
if (s.src[start] !== "~") return false;
|
|
2515
|
+
const prevChar = s.src[start - 1];
|
|
2516
|
+
const nextChar = s.src[start + 1];
|
|
2338
2517
|
if (/\d/.test(prevChar) && /\d/.test(nextChar)) {
|
|
2339
2518
|
if (!silent) {
|
|
2340
|
-
const token =
|
|
2519
|
+
const token = s.push("text", "", 0);
|
|
2341
2520
|
token.content = "~";
|
|
2342
2521
|
}
|
|
2343
|
-
|
|
2522
|
+
s.pos += 1;
|
|
2344
2523
|
return true;
|
|
2345
2524
|
}
|
|
2346
2525
|
return false;
|
|
2347
2526
|
};
|
|
2348
2527
|
md.inline.ruler.before("sub", "wave", waveRule);
|
|
2349
2528
|
md.renderer.rules.fence = (tokens, idx) => {
|
|
2350
|
-
const
|
|
2351
|
-
const info =
|
|
2352
|
-
const str =
|
|
2529
|
+
const tokenShape = tokens[idx];
|
|
2530
|
+
const info = String(tokenShape.info ?? "").trim();
|
|
2531
|
+
const str = String(tokenShape.content ?? "");
|
|
2353
2532
|
const encodedCode = btoa(unescape(encodeURIComponent(str)));
|
|
2354
|
-
const language = info
|
|
2533
|
+
const language = String(info ?? "text");
|
|
2355
2534
|
return `<div class="code-block" data-code="${encodedCode}" data-lang="${language}" id="${`editor-${msgId}-${idx}-${language}`}">
|
|
2356
2535
|
<div class="code-header">
|
|
2357
2536
|
<span class="code-lang">${language.toUpperCase()}</span>
|
|
@@ -2361,21 +2540,23 @@ function getMarkdown(msgId = `editor-${Date.now()}`, options = {}) {
|
|
|
2361
2540
|
</div>`;
|
|
2362
2541
|
};
|
|
2363
2542
|
const referenceInline = (state, silent) => {
|
|
2364
|
-
|
|
2365
|
-
|
|
2543
|
+
const s = state;
|
|
2544
|
+
if (s.src[s.pos] !== "[") return false;
|
|
2545
|
+
const match = /^\[(\d+)\]/.exec(s.src.slice(s.pos));
|
|
2366
2546
|
if (!match) return false;
|
|
2367
2547
|
if (!silent) {
|
|
2368
2548
|
const id = match[1];
|
|
2369
|
-
const token =
|
|
2549
|
+
const token = s.push("reference", "span", 0);
|
|
2370
2550
|
token.content = id;
|
|
2371
2551
|
token.markup = match[0];
|
|
2372
2552
|
}
|
|
2373
|
-
|
|
2553
|
+
s.pos += match[0].length;
|
|
2374
2554
|
return true;
|
|
2375
2555
|
};
|
|
2376
2556
|
md.inline.ruler.before("escape", "reference", referenceInline);
|
|
2377
2557
|
md.renderer.rules.reference = (tokens, idx) => {
|
|
2378
|
-
const
|
|
2558
|
+
const tokensAny = tokens;
|
|
2559
|
+
const id = String(tokensAny[idx].content ?? "");
|
|
2379
2560
|
return `<span class="reference-link" data-reference-id="${id}" role="button" tabindex="0" title="Click to view reference">${id}</span>`;
|
|
2380
2561
|
};
|
|
2381
2562
|
return md;
|