stream-markdown-parser 0.0.6 → 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.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 startPos = state.bMarks[startLine] + state.tShift[startLine];
40
- const lineMax = state.eMarks[startLine];
41
- const markerMatch = state.src.slice(startPos, lineMax).match(/^:::\s*(\w+)/);
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 = state.bMarks[nextLine] + state.tShift[nextLine];
49
- const ePos = state.eMarks[nextLine];
50
- if (state.src.slice(sPos, ePos).trim() === ":::") {
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
- state.push("vmr_container_open", "div", 1).attrSet("class", `vmr-container vmr-container-${name}`);
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 = state.bMarks[i] + state.tShift[i];
61
- const ePos = state.eMarks[i];
62
- contentLines.push(state.src.slice(sPos, ePos));
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
- state.push("paragraph_open", "p", 1);
65
- const inlineToken = state.push("inline", "", 0);
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
- state.md.inline.parse(inlineToken.content, state.md, state.env, inlineToken.children);
70
- state.push("paragraph_close", "p", -1);
71
- state.push("vmr_container_close", "div", -1);
72
- state.line = nextLine + 1;
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
- if (/^\*[^*]+/.test(state.src)) return false;
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 = state.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
- state.pos = state.pos + text.length;
296
- searchPos = state.pos;
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 = state.push("text_special", "", 0);
302
+ const t$1 = s.push("text_special", "", 0);
301
303
  t$1.content = text === "\\)" ? ")" : "(";
302
304
  t$1.markup = text;
303
- state.pos = state.pos + text.length;
304
- searchPos = state.pos;
305
+ s.pos = s.pos + text.length;
306
+ searchPos = s.pos;
305
307
  return;
306
308
  }
307
309
  if (!text) return;
308
- const t = state.push("text", "", 0);
310
+ const t = s.push("text", "", 0);
309
311
  t.content = text;
310
- state.pos = state.pos + text.length;
311
- searchPos = state.pos;
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
- state.pending = "";
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 = state.push("strong_open", "", 0);
336
+ const strongToken = s.push("strong_open", "", 0);
335
337
  strongToken.markup = src.slice(0, index + 2);
336
- const token = state.push("math_inline", "math", 0);
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
- state.push("strong_close", "", 0);
344
+ s.push("strong_close", "", 0);
343
345
  } else {
344
- const token = state.push("math_inline", "math", 0);
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
- state.pos = src.length;
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(state.pos, searchPos);
361
- if (!state.pending) pushText(text);
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 !== state.pos && isStrongPrefix) toPushBefore = state.pending + src.slice(state.pos, index);
370
- if (state.pending !== toPushBefore) {
371
- state.pending = "";
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 = state.push("strong_open", "", 0);
378
+ const strongToken = s.push("strong_open", "", 0);
377
379
  strongToken.markup = _match[0];
378
- const textToken = state.push("text", "", 0);
380
+ const textToken = s.push("text", "", 0);
379
381
  textToken.content = after;
380
- state.push("strong_close", "", 0);
382
+ s.push("strong_close", "", 0);
381
383
  } else pushText(toPushBefore);
382
384
  }
383
385
  if (isStrongPrefix) {
384
- const strongToken = state.push("strong_open", "", 0);
386
+ const strongToken = s.push("strong_open", "", 0);
385
387
  strongToken.markup = "**";
386
- const token = state.push("math_inline", "math", 0);
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) state.push("strong_close", "", 0);
395
+ if (isBeforeClose) s.push("strong_close", "", 0);
394
396
  if (raw) {
395
- const textContentToken = state.push("text", "", 0);
397
+ const textContentToken = s.push("text", "", 0);
396
398
  textContentToken.content = (raw == null ? "" : String(raw)).replace(/^\*+/, "");
397
399
  }
398
- if (!isBeforeClose) state.push("strong_close", "", 0);
399
- state.pos = src.length;
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 = state.push("math_inline", "math", 0);
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
- state.pos = searchPos;
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
- state.pos = src.length;
419
- } else state.pos = searchPos;
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 = state.bMarks[startLine] + state.tShift[startLine];
432
- const lineText = state.src.slice(startPos, state.eMarks[startLine]).trim();
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 = state.push("math_block", "math", 0);
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
- state.line = startLine + 1;
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 = state.bMarks[nextLine] + state.tShift[nextLine];
481
- const lineEnd = state.eMarks[nextLine];
482
- const currentLine = state.src.slice(lineStart - 1, lineEnd);
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 = state.push("math_block", "math", 0);
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
- state.line = nextLine + 1;
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
- return self.renderToken(tokens, idx, options);
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[idx].attrSet?.("loading", "lazy");
522
- return defaultImage(tokens, idx, options, env, self);
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 token = tokens[idx];
526
- const info = token.info ? token.info.trim() : "";
527
- return `<pre class="${info ? `language-${md.utils.escapeHtml(info.split(/\s+/g)[0])}` : ""}"><code>${md.utils.escapeHtml(token.content)}</code></pre>`;
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
- if (/^\|(?:[^|\n]+\|?)+/.test(token.content)) {
658
- const body = token.children[0].content.slice(1).split("|").map((i$1) => i$1.trim()).filter(Boolean).flatMap((i$1) => createTh(i$1));
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(token.content)) {
666
- const body = token.children[0].content.slice(1, -1).split("|").map((i$1) => i$1.trim()).flatMap((i$1) => createTh(i$1));
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(token.content)) {
674
- token.content = token.content.slice(0, -2);
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: token.meta?.checked === true,
687
- raw: token.meta?.checked ? "[x]" : "[ ]"
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: token.attrGet("checked") === "" || token.attrGet("checked") === "true",
694
- raw: token.attrGet("checked") === "" || token.attrGet("checked") === "true" ? "[x]" : "[ ]"
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: token.content || "",
704
- markup: token.markup || "",
705
- raw: `:${token.content || ""}:`
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 meta = token.meta;
755
- const closed = typeof meta?.closed === "boolean" ? meta.closed : void 0;
756
- const diff = token.info?.startsWith("diff") || false;
757
- const language = diff ? token.info?.split(" ")[1] || "" : token.info || "";
758
- let content = token.content || "";
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
  };
@@ -783,26 +797,35 @@ function parseFenceToken(token) {
783
797
 
784
798
  //#endregion
785
799
  //#region src/parser/inline-parsers/fixLinkToken.ts
800
+ function isTextToken(t) {
801
+ return !!t && t.type === "text" && typeof t.content === "string";
802
+ }
786
803
  function fixLinkToken(tokens) {
804
+ const tokensAny = tokens;
787
805
  tokens = fixLinkToken4(fixLinkToken3(tokens));
788
806
  if (tokens.length < 5) return tokens;
789
807
  const first = tokens[tokens.length - 5];
790
- if (first.type !== "text" && !first.content.endsWith("[")) return fixLinkTokens2(tokens);
808
+ const firstAny = first;
809
+ const firstContent = String(firstAny.content ?? "");
810
+ if (first.type !== "text" || !firstContent.endsWith("[")) return fixLinkTokens2(tokens);
791
811
  if (tokens[tokens.length - 4].tag !== "em") return fixLinkTokens2(tokens);
792
812
  const last = tokens[tokens.length - 1];
793
- if (last.type === "text" && !last.content.startsWith("]")) return fixLinkTokens2(tokens);
794
- const third = tokens[tokens.length - 3];
795
- const href = last.content.replace(/^\]\(*/, "");
796
- const loading = !last.content.includes(")");
797
- first.content = first.content.replace(/\[$/, "");
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 ?? "");
818
+ const href = lastContent.replace(/^\]\(*/, "");
819
+ const loading = !lastContent.includes(")");
820
+ tokensAny[tokens.length - 5].content = firstContent.replace(/\[$/, "");
798
821
  tokens.splice(tokens.length - 3, 1, {
799
822
  type: "link",
800
823
  href,
801
- text: third.content,
824
+ text: thirdContent,
802
825
  children: [{
803
826
  type: "text",
804
- content: third.content,
805
- raw: third.content
827
+ content: thirdContent,
828
+ raw: thirdContent
806
829
  }],
807
830
  loading
808
831
  });
@@ -810,6 +833,7 @@ function fixLinkToken(tokens) {
810
833
  return tokens;
811
834
  }
812
835
  function fixLinkTokens2(tokens) {
836
+ const tokensAny = tokens;
813
837
  if (tokens.length < 8) return tokens;
814
838
  let length = tokens.length;
815
839
  let last = tokens[length - 1];
@@ -822,16 +846,18 @@ function fixLinkTokens2(tokens) {
822
846
  const third = tokens[length - 6];
823
847
  const first = tokens[length - 8];
824
848
  if (first.type !== "text") return tokens;
825
- let href = tokens[length - 2].content;
849
+ let href = String(tokensAny[length - 2]?.content ?? "");
826
850
  let count = 4;
827
851
  if (length !== tokens.length) {
828
- href += last.content || "";
852
+ href += String(last.content ?? "");
829
853
  count++;
830
854
  }
831
855
  tokens.splice(length - 4, count);
832
- const content = third.content;
856
+ const thirdAny = third;
857
+ const content = String(thirdAny.content ?? "");
833
858
  length -= 4;
834
- first.content = first.content.replace(/\[$/, "");
859
+ const firstAny = first;
860
+ tokensAny[length - 8].content = String(firstAny.content ?? "").replace(/\[$/, "");
835
861
  tokens.splice(length - 2, 1, {
836
862
  type: "link",
837
863
  href,
@@ -846,38 +872,54 @@ function fixLinkTokens2(tokens) {
846
872
  return tokens;
847
873
  }
848
874
  function fixLinkToken3(tokens) {
875
+ const tokensAny = tokens;
849
876
  const last = tokens[tokens.length - 1];
850
877
  const preLast = tokens[tokens.length - 2];
851
878
  const fixedTokens = [...tokens];
852
879
  if (last.type !== "text" || !last.content?.startsWith(")")) return tokens;
853
880
  if (preLast.type !== "link_close") return tokens;
854
- if (tokens[tokens.length - 5].type === "text" && tokens[tokens.length - 5].content?.endsWith("(")) {
855
- const content = tokens[tokens.length - 5].content + tokens[tokens.length - 3].content + last.content;
856
- fixedTokens.splice(tokens.length - 5, tokens.length - 1, {
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 ?? "");
885
+ fixedTokens.splice(tokens.length - 5, 5, {
857
886
  type: "text",
858
887
  content,
859
888
  raw: content
860
889
  });
861
- } else last.content = last.content.slice(1);
890
+ } else {
891
+ const lc = (last.content ?? "").slice(1);
892
+ fixedTokens[fixedTokens.length - 1] = {
893
+ ...last,
894
+ content: lc
895
+ };
896
+ }
862
897
  return fixedTokens;
863
898
  }
864
899
  function fixLinkToken4(tokens) {
900
+ const tokensAny = tokens;
865
901
  const fixedTokens = [...tokens];
866
- for (let i = tokens.length - 1; i >= 0; i--) if (tokens[i].type === "link_close") {
902
+ for (let i = tokens.length - 1; i >= 3; i--) if (tokens[i].type === "link_close") {
867
903
  if (tokens[i - 3]?.content?.endsWith("(")) {
868
904
  const nextToken = tokens[i + 1];
869
905
  if (nextToken?.type === "text") {
870
906
  if (tokens[i - 1].type === "text" && tokens[i - 3].type === "text") {
871
- const content = tokens[i - 3].content + tokens[i - 1].content + nextToken.content;
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;
872
911
  fixedTokens.splice(i - 3, 5, {
873
912
  type: "text",
874
913
  content,
875
914
  raw: content
876
915
  });
916
+ i -= 3;
877
917
  }
878
918
  } else {
879
919
  if (tokens[i - 1].type === "text" && tokens[i - 3].type === "text") {
880
- const content = tokens[i - 3].content + tokens[i - 1].content;
920
+ const a = tokensAny[i - 3];
921
+ const b = tokensAny[i - 1];
922
+ const content = String(a.content ?? "") + String(b.content ?? "");
881
923
  fixedTokens.splice(i - 3, 4, {
882
924
  type: "text",
883
925
  content,
@@ -895,7 +937,8 @@ function fixLinkToken4(tokens) {
895
937
  //#region src/parser/inline-parsers/fixListItem.ts
896
938
  function fixListItem(tokens) {
897
939
  const last = tokens[tokens.length - 1];
898
- if (last?.type === "text" && /^\s*\d+\.\s*$/.test(last.content || "") && tokens[tokens.length - 2]?.tag === "br") tokens.splice(tokens.length - 1, 1);
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);
899
942
  return tokens;
900
943
  }
901
944
 
@@ -907,7 +950,8 @@ function fixStrongTokens(tokens) {
907
950
  const i = tokens.length - 4;
908
951
  const token = tokens[i];
909
952
  const nextToken = tokens[i + 1];
910
- if (token.type === "text" && token.content?.endsWith("*") && nextToken.type === "em_open") {
953
+ const tokenContent = String(token.content ?? "");
954
+ if (token.type === "text" && tokenContent.endsWith("*") && nextToken.type === "em_open") {
911
955
  const _nextToken = tokens[i + 2];
912
956
  const count = _nextToken?.type === "text" ? 4 : 3;
913
957
  const insert = [
@@ -924,7 +968,7 @@ function fixStrongTokens(tokens) {
924
968
  },
925
969
  {
926
970
  type: "text",
927
- content: _nextToken?.type === "text" ? _nextToken.content : ""
971
+ content: _nextToken?.type === "text" ? String(_nextToken.content ?? "") : ""
928
972
  },
929
973
  {
930
974
  type: "strong_close",
@@ -938,7 +982,7 @@ function fixStrongTokens(tokens) {
938
982
  meta: null
939
983
  }
940
984
  ];
941
- const beforeText = token.content?.slice(0, -1);
985
+ const beforeText = tokenContent.slice(0, -1);
942
986
  if (beforeText) insert.unshift({
943
987
  type: "text",
944
988
  content: beforeText,
@@ -953,10 +997,11 @@ function fixStrongTokens(tokens) {
953
997
  //#endregion
954
998
  //#region src/parser/inline-parsers/footnote-ref-parser.ts
955
999
  function parseFootnoteRefToken(token) {
1000
+ const tokenMeta = token.meta ?? {};
956
1001
  return {
957
1002
  type: "footnote_reference",
958
- id: token.meta?.label || "",
959
- raw: `[^${token.meta?.label || ""}]`
1003
+ id: String(tokenMeta.label ?? ""),
1004
+ raw: `[^${String(tokenMeta.label ?? "")}]`
960
1005
  };
961
1006
  }
962
1007
 
@@ -977,7 +1022,7 @@ function parseHighlightToken(tokens, startIndex) {
977
1022
  let i = startIndex + 1;
978
1023
  const innerTokens = [];
979
1024
  while (i < tokens.length && tokens[i].type !== "mark_close") {
980
- markText += tokens[i].content || "";
1025
+ markText += String(tokens[i].content ?? "");
981
1026
  innerTokens.push(tokens[i]);
982
1027
  i++;
983
1028
  }
@@ -995,12 +1040,33 @@ function parseHighlightToken(tokens, startIndex) {
995
1040
  //#endregion
996
1041
  //#region src/parser/inline-parsers/image-parser.ts
997
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 ?? "");
998
1064
  return {
999
1065
  type: "image",
1000
- src: token.attrs?.find((attr) => attr[0] === "src")?.[1] || "",
1001
- alt: token.attrs?.find((attr) => attr[0] === "alt")?.[1] || "",
1002
- title: token.attrs?.find((attr) => attr[0] === "title")?.[1] || null,
1003
- raw: token.content || "",
1066
+ src,
1067
+ alt,
1068
+ title,
1069
+ raw,
1004
1070
  loading
1005
1071
  };
1006
1072
  }
@@ -1008,10 +1074,11 @@ function parseImageToken(token, loading = false) {
1008
1074
  //#endregion
1009
1075
  //#region src/parser/inline-parsers/inline-code-parser.ts
1010
1076
  function parseInlineCodeToken(token) {
1077
+ const code = String(token.content ?? "");
1011
1078
  return {
1012
1079
  type: "inline_code",
1013
- code: token.content || "",
1014
- raw: token.content || ""
1080
+ code,
1081
+ raw: code
1015
1082
  };
1016
1083
  }
1017
1084
 
@@ -1023,7 +1090,7 @@ function parseInsertToken(tokens, startIndex) {
1023
1090
  let i = startIndex + 1;
1024
1091
  const innerTokens = [];
1025
1092
  while (i < tokens.length && tokens[i].type !== "ins_close") {
1026
- insText += tokens[i].content || "";
1093
+ insText += String(tokens[i].content ?? "");
1027
1094
  innerTokens.push(tokens[i]);
1028
1095
  i++;
1029
1096
  }
@@ -1032,7 +1099,7 @@ function parseInsertToken(tokens, startIndex) {
1032
1099
  node: {
1033
1100
  type: "insert",
1034
1101
  children,
1035
- raw: `++${insText}++`
1102
+ raw: `++${String(insText)}++`
1036
1103
  },
1037
1104
  nextIndex: i < tokens.length ? i + 1 : tokens.length
1038
1105
  };
@@ -1041,9 +1108,10 @@ function parseInsertToken(tokens, startIndex) {
1041
1108
  //#endregion
1042
1109
  //#region src/parser/inline-parsers/link-parser.ts
1043
1110
  function parseLinkToken(tokens, startIndex) {
1044
- const openToken = tokens[startIndex];
1045
- const href = openToken.attrs?.find((attr) => attr[0] === "href")?.[1] || "";
1046
- const title = openToken.attrs?.find((attr) => attr[0] === "title")?.[1] || null;
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);
1047
1115
  let i = startIndex + 1;
1048
1116
  const linkTokens = [];
1049
1117
  const loading = true;
@@ -1053,8 +1121,9 @@ function parseLinkToken(tokens, startIndex) {
1053
1121
  }
1054
1122
  const children = parseInlineTokens(linkTokens);
1055
1123
  const linkText = children.map((node) => {
1056
- if ("content" in node) return node.content;
1057
- return node.raw;
1124
+ const nodeAny = node;
1125
+ if ("content" in node) return String(nodeAny.content ?? "");
1126
+ return String(nodeAny.raw ?? "");
1058
1127
  }).join("");
1059
1128
  return {
1060
1129
  node: {
@@ -1063,7 +1132,7 @@ function parseLinkToken(tokens, startIndex) {
1063
1132
  title,
1064
1133
  text: linkText,
1065
1134
  children,
1066
- raw: `[${linkText}](${href}${title ? ` "${title}"` : ""})`,
1135
+ raw: String(`[${linkText}](${href}${title ? ` "${title}"` : ""})`),
1067
1136
  loading
1068
1137
  },
1069
1138
  nextIndex: i < tokens.length ? i + 1 : tokens.length
@@ -1075,7 +1144,7 @@ function parseLinkToken(tokens, startIndex) {
1075
1144
  function parseMathInlineToken(token) {
1076
1145
  return {
1077
1146
  type: "math_inline",
1078
- content: token.content || "",
1147
+ content: String(token.content ?? ""),
1079
1148
  loading: !!token.loading,
1080
1149
  raw: token.raw
1081
1150
  };
@@ -1086,8 +1155,8 @@ function parseMathInlineToken(token) {
1086
1155
  function parseReferenceToken(token) {
1087
1156
  return {
1088
1157
  type: "reference",
1089
- id: token.content || "",
1090
- raw: token.markup || `[${token.content}]`
1158
+ id: String(token.content ?? ""),
1159
+ raw: String(token.markup ?? `[${token.content ?? ""}]`)
1091
1160
  };
1092
1161
  }
1093
1162
 
@@ -1099,7 +1168,7 @@ function parseStrikethroughToken(tokens, startIndex) {
1099
1168
  let i = startIndex + 1;
1100
1169
  const innerTokens = [];
1101
1170
  while (i < tokens.length && tokens[i].type !== "s_close") {
1102
- sText += tokens[i].content || "";
1171
+ sText += String(tokens[i].content ?? "");
1103
1172
  innerTokens.push(tokens[i]);
1104
1173
  i++;
1105
1174
  }
@@ -1122,7 +1191,7 @@ function parseStrongToken(tokens, startIndex, raw) {
1122
1191
  let i = startIndex + 1;
1123
1192
  const innerTokens = [];
1124
1193
  while (i < tokens.length && tokens[i].type !== "strong_close") {
1125
- strongText += tokens[i].content || "";
1194
+ strongText += String(tokens[i].content ?? "");
1126
1195
  innerTokens.push(tokens[i]);
1127
1196
  i++;
1128
1197
  }
@@ -1131,7 +1200,7 @@ function parseStrongToken(tokens, startIndex, raw) {
1131
1200
  node: {
1132
1201
  type: "strong",
1133
1202
  children,
1134
- raw: `**${strongText}**`
1203
+ raw: `**${String(strongText)}**`
1135
1204
  },
1136
1205
  nextIndex: i < tokens.length ? i + 1 : tokens.length
1137
1206
  };
@@ -1145,20 +1214,22 @@ function parseSubscriptToken(tokens, startIndex) {
1145
1214
  let i = startIndex + 1;
1146
1215
  const innerTokens = [];
1147
1216
  while (i < tokens.length && tokens[i].type !== "sub_close") {
1148
- subText += tokens[i].content || "";
1217
+ subText += String(tokens[i].content ?? "");
1149
1218
  innerTokens.push(tokens[i]);
1150
1219
  i++;
1151
1220
  }
1152
1221
  children.push(...parseInlineTokens(innerTokens));
1222
+ const startContent = String(tokens[startIndex].content ?? "");
1223
+ const display = subText || startContent;
1153
1224
  return {
1154
1225
  node: {
1155
1226
  type: "subscript",
1156
1227
  children: children.length > 0 ? children : [{
1157
1228
  type: "text",
1158
- content: subText || tokens[startIndex].content || "",
1159
- raw: subText || tokens[startIndex].content || ""
1229
+ content: display,
1230
+ raw: display
1160
1231
  }],
1161
- raw: `~${subText || tokens[startIndex].content || ""}~`
1232
+ raw: `~${display}~`
1162
1233
  },
1163
1234
  nextIndex: i < tokens.length ? i + 1 : tokens.length
1164
1235
  };
@@ -1172,7 +1243,7 @@ function parseSuperscriptToken(tokens, startIndex) {
1172
1243
  let i = startIndex + 1;
1173
1244
  const innerTokens = [];
1174
1245
  while (i < tokens.length && tokens[i].type !== "sup_close") {
1175
- supText += tokens[i].content || "";
1246
+ supText += String(tokens[i].content ?? "");
1176
1247
  innerTokens.push(tokens[i]);
1177
1248
  i++;
1178
1249
  }
@@ -1182,10 +1253,10 @@ function parseSuperscriptToken(tokens, startIndex) {
1182
1253
  type: "superscript",
1183
1254
  children: children.length > 0 ? children : [{
1184
1255
  type: "text",
1185
- content: supText || tokens[startIndex].content || "",
1186
- raw: supText || tokens[startIndex].content || ""
1256
+ content: supText || String(tokens[startIndex].content ?? ""),
1257
+ raw: supText || String(tokens[startIndex].content ?? "")
1187
1258
  }],
1188
- raw: `^${supText || tokens[startIndex].content || ""}^`
1259
+ raw: `^${supText || String(tokens[startIndex].content ?? "")}^`
1189
1260
  },
1190
1261
  nextIndex: i < tokens.length ? i + 1 : tokens.length
1191
1262
  };
@@ -1194,10 +1265,11 @@ function parseSuperscriptToken(tokens, startIndex) {
1194
1265
  //#endregion
1195
1266
  //#region src/parser/inline-parsers/text-parser.ts
1196
1267
  function parseTextToken(token) {
1268
+ const content = String(token.content ?? "");
1197
1269
  return {
1198
1270
  type: "text",
1199
- content: token.content || "",
1200
- raw: token.content || ""
1271
+ content,
1272
+ raw: content
1201
1273
  };
1202
1274
  }
1203
1275
 
@@ -1211,314 +1283,232 @@ function parseInlineTokens(tokens, raw, pPreToken) {
1211
1283
  tokens = fixStrongTokens(tokens);
1212
1284
  tokens = fixListItem(tokens);
1213
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
+ }
1214
1503
  while (i < tokens.length) {
1215
1504
  const token = tokens[i];
1216
1505
  handleToken(token);
1217
1506
  }
1218
1507
  function handleToken(token) {
1219
1508
  switch (token.type) {
1220
- case "text": {
1221
- let index = result.length - 1;
1222
- let content = token.content.replace(/\\/g, "") || "";
1223
- if (content.startsWith(")") && result[result.length - 1]?.type === "link") content = content.slice(1);
1224
- for (; index >= 0; index--) {
1225
- const item = result[index];
1226
- if (item.type === "text") {
1227
- currentTextNode = null;
1228
- content = item.content + content;
1229
- continue;
1230
- }
1231
- break;
1232
- }
1233
- if (index < result.length - 1) result.splice(index + 1);
1234
- const nextToken = tokens[i + 1];
1235
- if (content === "`" || content === "|" || content === "$" || content === "1" || /^\*+$/.test(content) || /^\d$/.test(content)) {
1236
- i++;
1237
- break;
1238
- }
1239
- if (!nextToken && /[^\]]\s*\(\s*$/.test(content)) content = content.replace(/\(\s*$/, "");
1240
- if (raw?.startsWith("[") && pPreToken?.type === "list_item_open") {
1241
- const w = content.slice(1).match(/[^\s\]]/);
1242
- if (w === null) {
1243
- i++;
1244
- break;
1245
- }
1246
- if (w && /x/i.test(w[0]) || !w) {
1247
- const checked = w ? w[0] === "x" || w[0] === "X" : false;
1248
- result.push({
1249
- type: "checkbox_input",
1250
- checked,
1251
- raw: checked ? "[x]" : "[ ]"
1252
- });
1253
- i++;
1254
- break;
1255
- }
1256
- }
1257
- if (/`[^`]*/.test(content)) {
1258
- currentTextNode = null;
1259
- const index$1 = content.indexOf("`");
1260
- const _text = content.slice(0, index$1);
1261
- const codeContent = content.slice(index$1);
1262
- if (_text) result.push({
1263
- type: "text",
1264
- content: _text || "",
1265
- raw: _text || ""
1266
- });
1267
- result.push({
1268
- type: "inline_code",
1269
- code: codeContent.replace(/`/g, ""),
1270
- raw: codeContent || ""
1271
- });
1272
- i++;
1273
- break;
1274
- }
1275
- if (content === "[") {
1276
- i++;
1277
- break;
1278
- }
1279
- if (/[^~]*~{2,}[^~]+/.test(content)) {
1280
- const index$1 = content.indexOf("~~") || 0;
1281
- const _text = content.slice(0, index$1);
1282
- if (_text) if (currentTextNode) {
1283
- currentTextNode.content += _text;
1284
- currentTextNode.raw += _text;
1285
- } else {
1286
- currentTextNode = {
1287
- type: "text",
1288
- content: _text || "",
1289
- raw: token.content || ""
1290
- };
1291
- result.push(currentTextNode);
1292
- }
1293
- const strikethroughContent = content.slice(index$1);
1294
- currentTextNode = null;
1295
- const { node } = parseStrikethroughToken([
1296
- {
1297
- type: "s_open",
1298
- tag: "s",
1299
- content: "",
1300
- markup: "*",
1301
- info: "",
1302
- meta: null
1303
- },
1304
- {
1305
- type: "text",
1306
- tag: "",
1307
- content: strikethroughContent.replace(/~/g, ""),
1308
- markup: "",
1309
- info: "",
1310
- meta: null
1311
- },
1312
- {
1313
- type: "s_close",
1314
- tag: "s",
1315
- content: "",
1316
- markup: "*",
1317
- info: "",
1318
- meta: null
1319
- }
1320
- ], 0);
1321
- result.push(node);
1322
- i++;
1323
- break;
1324
- }
1325
- if (/[^*]*\*\*[^*]+/.test(content)) {
1326
- const index$1 = content.indexOf("*") || 0;
1327
- const _text = content.slice(0, index$1);
1328
- if (_text) if (currentTextNode) {
1329
- currentTextNode.content += _text;
1330
- currentTextNode.raw += _text;
1331
- } else {
1332
- currentTextNode = {
1333
- type: "text",
1334
- content: _text || "",
1335
- raw: token.content || ""
1336
- };
1337
- result.push(currentTextNode);
1338
- }
1339
- const strongContent = content.slice(index$1);
1340
- currentTextNode = null;
1341
- const { node } = parseStrongToken([
1342
- {
1343
- type: "strong_open",
1344
- tag: "strong",
1345
- content: "",
1346
- markup: "*",
1347
- info: "",
1348
- meta: null
1349
- },
1350
- {
1351
- type: "text",
1352
- tag: "",
1353
- content: strongContent.replace(/\*/g, ""),
1354
- markup: "",
1355
- info: "",
1356
- meta: null
1357
- },
1358
- {
1359
- type: "strong_close",
1360
- tag: "strong",
1361
- content: "",
1362
- markup: "*",
1363
- info: "",
1364
- meta: null
1365
- }
1366
- ], 0, raw);
1367
- result.push(node);
1368
- i++;
1369
- break;
1370
- } else if (/[^*]*\*[^*]+/.test(content)) {
1371
- const index$1 = content.indexOf("*") || 0;
1372
- const _text = content.slice(0, index$1);
1373
- if (_text) if (currentTextNode) {
1374
- currentTextNode.content += _text;
1375
- currentTextNode.raw += _text;
1376
- } else {
1377
- currentTextNode = {
1378
- type: "text",
1379
- content: _text || "",
1380
- raw: token.content || ""
1381
- };
1382
- result.push(currentTextNode);
1383
- }
1384
- const emphasisContent = content.slice(index$1);
1385
- currentTextNode = null;
1386
- const { node } = parseEmphasisToken([
1387
- {
1388
- type: "em_open",
1389
- tag: "em",
1390
- content: "",
1391
- markup: "*",
1392
- info: "",
1393
- meta: null
1394
- },
1395
- {
1396
- type: "text",
1397
- tag: "",
1398
- content: emphasisContent.replace(/\*/g, ""),
1399
- markup: "",
1400
- info: "",
1401
- meta: null
1402
- },
1403
- {
1404
- type: "em_close",
1405
- tag: "em",
1406
- content: "",
1407
- markup: "*",
1408
- info: "",
1409
- meta: null
1410
- }
1411
- ], 0);
1412
- result.push(node);
1413
- i++;
1414
- break;
1415
- }
1416
- const imageStart = content.indexOf("![");
1417
- if (imageStart !== -1) {
1418
- const textNodeContent = content.slice(0, imageStart);
1419
- if (!currentTextNode) currentTextNode = {
1420
- type: "text",
1421
- content: textNodeContent,
1422
- raw: textNodeContent
1423
- };
1424
- else currentTextNode.content += textNodeContent;
1425
- result.push(currentTextNode);
1426
- currentTextNode = null;
1427
- result.push(parseImageToken(token, true));
1428
- i++;
1429
- break;
1430
- }
1431
- let linkStart = content.indexOf("[");
1432
- if (content.endsWith("undefined") && !raw?.endsWith("undefined")) content = content.slice(0, -9);
1433
- const textNode = parseTextToken({
1434
- ...token,
1435
- content
1436
- });
1437
- if (linkStart !== -1) {
1438
- let textNodeContent = content.slice(0, linkStart);
1439
- const linkEnd = content.indexOf("](", linkStart);
1440
- if (linkEnd !== -1) {
1441
- const textToken = tokens[i + 2];
1442
- let text = content.slice(linkStart + 1, linkEnd);
1443
- if (text.includes("[")) {
1444
- const secondLinkStart = text.indexOf("[");
1445
- linkStart = linkStart + secondLinkStart + 1;
1446
- textNodeContent += content.slice(0, linkStart);
1447
- text = content.slice(linkStart + 1, linkEnd);
1448
- }
1449
- if (content.endsWith("](") && nextToken?.type === "link_open" && textToken) {
1450
- const last = tokens[i + 4];
1451
- let index$1 = 4;
1452
- let loading$1 = true;
1453
- if (last?.type === "text" && last.content === ")") {
1454
- index$1++;
1455
- loading$1 = false;
1456
- } else if (last?.type === "text" && last.content === ".") i++;
1457
- if (textNodeContent) result.push({
1458
- type: "text",
1459
- content: textNodeContent,
1460
- raw: textNodeContent
1461
- });
1462
- result.push({
1463
- type: "link",
1464
- href: textToken.content || "",
1465
- text,
1466
- children: [{
1467
- type: "text",
1468
- content: text,
1469
- raw: text
1470
- }],
1471
- loading: loading$1
1472
- });
1473
- i += index$1;
1474
- break;
1475
- }
1476
- const linkContentEnd = content.indexOf(")", linkEnd);
1477
- const href = linkContentEnd !== -1 ? content.slice(linkEnd + 2, linkContentEnd) : "";
1478
- const loading = linkContentEnd === -1;
1479
- if (textNodeContent) result.push({
1480
- type: "text",
1481
- content: textNodeContent,
1482
- raw: textNodeContent
1483
- });
1484
- result.push({
1485
- type: "link",
1486
- href,
1487
- text,
1488
- children: [{
1489
- type: "text",
1490
- content: text,
1491
- raw: text
1492
- }],
1493
- loading
1494
- });
1495
- const afterText = linkContentEnd !== -1 ? content.slice(linkContentEnd + 1) : "";
1496
- if (afterText) {
1497
- handleToken({
1498
- type: "text",
1499
- content: afterText,
1500
- raw: afterText
1501
- });
1502
- i--;
1503
- }
1504
- i++;
1505
- break;
1506
- }
1507
- }
1508
- const preToken = tokens[i - 1];
1509
- if (currentTextNode) {
1510
- currentTextNode.content += textNode.content.replace(/(\*+|\(|\\)$/, "");
1511
- currentTextNode.raw += textNode.raw;
1512
- } else {
1513
- const maybeMath = preToken?.tag === "br" && tokens[i - 2]?.content === "[";
1514
- if (!tokens[i + 1]) textNode.content = textNode.content.replace(/(\*+|\(|\\)$/, "");
1515
- currentTextNode = textNode;
1516
- currentTextNode.center = maybeMath;
1517
- result.push(currentTextNode);
1518
- }
1519
- i++;
1509
+ case "text":
1510
+ handleTextToken(token);
1520
1511
  break;
1521
- }
1522
1512
  case "softbreak":
1523
1513
  if (currentTextNode) {
1524
1514
  currentTextNode.content += "\n";
@@ -1527,193 +1517,358 @@ function parseInlineTokens(tokens, raw, pPreToken) {
1527
1517
  i++;
1528
1518
  break;
1529
1519
  case "code_inline":
1530
- currentTextNode = null;
1531
- result.push(parseInlineCodeToken(token));
1520
+ pushNode(parseInlineCodeToken(token));
1532
1521
  i++;
1533
1522
  break;
1534
- case "link_open": {
1535
- currentTextNode = null;
1536
- const href = token.attrs?.find((attr) => attr[0] === "href")?.[1];
1537
- if (raw && tokens[i + 1].type === "text") {
1538
- const text = tokens[i + 1]?.content || "";
1539
- if (!(/* @__PURE__ */ new RegExp(`\\[${text}\\s*\\]`)).test(raw)) {
1540
- result.push({
1541
- type: "text",
1542
- content: text,
1543
- raw: text
1544
- });
1545
- i += 3;
1546
- break;
1547
- }
1548
- }
1549
- if (raw && href) {
1550
- const loadingMath = /* @__PURE__ */ new RegExp(`\\(\\s*${href}\\s*\\)`);
1551
- const pre = result.length > 0 ? result[result.length - 1] : null;
1552
- const loading = !loadingMath.test(raw);
1553
- if (loading && pre) {
1554
- if ((/* @__PURE__ */ new RegExp(`\\[${pre.text}\\s*\\]\\(`)).test(raw)) {
1555
- const text = pre?.text || pre?.content?.slice(1, -1) || "";
1556
- result.splice(result.length - 1, 1, {
1557
- type: "link",
1558
- href: "",
1559
- text,
1560
- loading
1561
- });
1562
- i += 3;
1563
- if (tokens[i]?.content === ".") i++;
1564
- break;
1565
- }
1566
- }
1567
- }
1568
- const { node, nextIndex } = parseLinkToken(tokens, i);
1569
- i = nextIndex;
1570
- node.loading = false;
1571
- result.push(node);
1523
+ case "link_open":
1524
+ handleLinkOpen(token);
1572
1525
  break;
1573
- }
1574
1526
  case "image":
1575
- currentTextNode = null;
1576
- result.push(parseImageToken(token));
1527
+ resetCurrentTextNode();
1528
+ pushNode(parseImageToken(token));
1577
1529
  i++;
1578
1530
  break;
1579
1531
  case "strong_open": {
1580
- currentTextNode = null;
1532
+ resetCurrentTextNode();
1581
1533
  const { node, nextIndex } = parseStrongToken(tokens, i, token.content);
1582
- result.push(node);
1534
+ pushNode(node);
1583
1535
  i = nextIndex;
1584
1536
  break;
1585
1537
  }
1586
1538
  case "em_open": {
1587
- currentTextNode = null;
1539
+ resetCurrentTextNode();
1588
1540
  const { node, nextIndex } = parseEmphasisToken(tokens, i);
1589
- result.push(node);
1541
+ pushNode(node);
1590
1542
  i = nextIndex;
1591
1543
  break;
1592
1544
  }
1593
1545
  case "s_open": {
1594
- currentTextNode = null;
1546
+ resetCurrentTextNode();
1595
1547
  const { node, nextIndex } = parseStrikethroughToken(tokens, i);
1596
- result.push(node);
1548
+ pushNode(node);
1597
1549
  i = nextIndex;
1598
1550
  break;
1599
1551
  }
1600
1552
  case "mark_open": {
1601
- currentTextNode = null;
1553
+ resetCurrentTextNode();
1602
1554
  const { node, nextIndex } = parseHighlightToken(tokens, i);
1603
- result.push(node);
1555
+ pushNode(node);
1604
1556
  i = nextIndex;
1605
1557
  break;
1606
1558
  }
1607
1559
  case "ins_open": {
1608
- currentTextNode = null;
1560
+ resetCurrentTextNode();
1609
1561
  const { node, nextIndex } = parseInsertToken(tokens, i);
1610
- result.push(node);
1562
+ pushNode(node);
1611
1563
  i = nextIndex;
1612
1564
  break;
1613
1565
  }
1614
1566
  case "sub_open": {
1615
- currentTextNode = null;
1567
+ resetCurrentTextNode();
1616
1568
  const { node, nextIndex } = parseSubscriptToken(tokens, i);
1617
- result.push(node);
1569
+ pushNode(node);
1618
1570
  i = nextIndex;
1619
1571
  break;
1620
1572
  }
1621
1573
  case "sup_open": {
1622
- currentTextNode = null;
1574
+ resetCurrentTextNode();
1623
1575
  const { node, nextIndex } = parseSuperscriptToken(tokens, i);
1624
- result.push(node);
1576
+ pushNode(node);
1625
1577
  i = nextIndex;
1626
1578
  break;
1627
1579
  }
1628
1580
  case "sub":
1629
- currentTextNode = null;
1630
- result.push({
1581
+ resetCurrentTextNode();
1582
+ pushNode({
1631
1583
  type: "subscript",
1632
1584
  children: [{
1633
1585
  type: "text",
1634
- content: token.content || "",
1635
- raw: token.content || ""
1586
+ content: String(token.content ?? ""),
1587
+ raw: String(token.content ?? "")
1636
1588
  }],
1637
- raw: `~${token.content || ""}~`
1589
+ raw: `~${String(token.content ?? "")}~`
1638
1590
  });
1639
1591
  i++;
1640
1592
  break;
1641
1593
  case "sup":
1642
- currentTextNode = null;
1643
- result.push({
1594
+ resetCurrentTextNode();
1595
+ pushNode({
1644
1596
  type: "superscript",
1645
1597
  children: [{
1646
1598
  type: "text",
1647
- content: token.content || "",
1648
- raw: token.content || ""
1599
+ content: String(token.content ?? ""),
1600
+ raw: String(token.content ?? "")
1649
1601
  }],
1650
- raw: `^${token.content || ""}^`
1602
+ raw: `^${String(token.content ?? "")}^`
1651
1603
  });
1652
1604
  i++;
1653
1605
  break;
1654
1606
  case "emoji": {
1655
- currentTextNode = null;
1607
+ resetCurrentTextNode();
1656
1608
  const preToken = tokens[i - 1];
1657
- if (preToken?.type === "text" && /\|:-+/.test(preToken.content || "")) result.push({
1658
- type: "text",
1659
- content: "",
1660
- raw: ""
1661
- });
1662
- else result.push(parseEmojiToken(token));
1609
+ if (preToken?.type === "text" && /\|:-+/.test(String(preToken.content ?? ""))) pushText("", "");
1610
+ else pushNode(parseEmojiToken(token));
1663
1611
  i++;
1664
1612
  break;
1665
1613
  }
1666
1614
  case "checkbox":
1667
- currentTextNode = null;
1668
- result.push(parseCheckboxToken(token));
1615
+ resetCurrentTextNode();
1616
+ pushNode(parseCheckboxToken(token));
1669
1617
  i++;
1670
1618
  break;
1671
1619
  case "checkbox_input":
1672
- currentTextNode = null;
1673
- result.push(parseCheckboxInputToken(token));
1620
+ resetCurrentTextNode();
1621
+ pushNode(parseCheckboxInputToken(token));
1674
1622
  i++;
1675
1623
  break;
1676
1624
  case "footnote_ref":
1677
- currentTextNode = null;
1678
- result.push(parseFootnoteRefToken(token));
1625
+ resetCurrentTextNode();
1626
+ pushNode(parseFootnoteRefToken(token));
1679
1627
  i++;
1680
1628
  break;
1681
1629
  case "hardbreak":
1682
- currentTextNode = null;
1683
- result.push(parseHardbreakToken());
1630
+ resetCurrentTextNode();
1631
+ pushNode(parseHardbreakToken());
1684
1632
  i++;
1685
1633
  break;
1686
1634
  case "fence":
1687
- currentTextNode = null;
1688
- result.push(parseFenceToken(tokens[i]));
1635
+ resetCurrentTextNode();
1636
+ pushNode(parseFenceToken(tokens[i]));
1689
1637
  i++;
1690
1638
  break;
1691
1639
  case "math_inline":
1692
- currentTextNode = null;
1693
- result.push(parseMathInlineToken(token));
1640
+ resetCurrentTextNode();
1641
+ pushNode(parseMathInlineToken(token));
1694
1642
  i++;
1695
1643
  break;
1696
- case "reference": {
1697
- currentTextNode = null;
1698
- const nextToken = tokens[i + 1];
1699
- const preToken = tokens[i - 1];
1700
- const preResult = result[result.length - 1];
1701
- if (nextToken?.type === "text" && !nextToken.content?.startsWith("(") || preToken.type === "text" && /\]$|^\s*$/.test(preToken.content || "")) result.push(parseReferenceToken(token));
1702
- else if (nextToken && nextToken.type === "text") nextToken.content = token.markup + nextToken.content;
1703
- else if (preResult.type === "text") {
1704
- preResult.content = preResult.content + token.markup;
1705
- preResult.raw = preResult.raw + token.markup;
1706
- }
1707
- i++;
1644
+ case "reference":
1645
+ handleReference(token);
1708
1646
  break;
1709
- }
1710
1647
  default:
1711
- result.push(token);
1712
- currentTextNode = null;
1648
+ pushToken(token);
1713
1649
  i++;
1714
1650
  break;
1715
1651
  }
1716
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
+ }
1717
1872
  return result;
1718
1873
  }
1719
1874
 
@@ -1727,7 +1882,7 @@ function parseBlockquote(tokens, index) {
1727
1882
  blockquoteChildren.push({
1728
1883
  type: "paragraph",
1729
1884
  children: parseInlineTokens(contentToken.children || []),
1730
- raw: contentToken.content || ""
1885
+ raw: String(contentToken.content ?? "")
1731
1886
  });
1732
1887
  j += 3;
1733
1888
  } else if (tokens[j].type === "bullet_list_open" || tokens[j].type === "ordered_list_open") {
@@ -1746,14 +1901,15 @@ function parseBlockquote(tokens, index) {
1746
1901
  //#region src/parser/node-parsers/code-block-parser.ts
1747
1902
  function parseCodeBlock(token) {
1748
1903
  if (token.info?.startsWith("diff")) return parseFenceToken(token);
1749
- const match = token.content.match(/ type="application\/vnd\.ant\.([^"]+)"/);
1750
- if (match?.[1]) token.content = token.content.replace(/<antArtifact[^>]*>/g, "").replace(/<\/antArtifact>/g, "");
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, "");
1751
1907
  const hasMap = Array.isArray(token.map) && token.map.length === 2;
1752
1908
  return {
1753
1909
  type: "code_block",
1754
- language: match ? match[1] : token.info || "",
1755
- code: token.content || "",
1756
- raw: token.content || "",
1910
+ language: match ? match[1] : String(token.info ?? ""),
1911
+ code: String(token.content ?? ""),
1912
+ raw: String(token.content ?? ""),
1757
1913
  loading: !hasMap
1758
1914
  };
1759
1915
  }
@@ -1776,8 +1932,8 @@ function parseDefinitionList(tokens, index) {
1776
1932
  const contentToken = tokens[k + 1];
1777
1933
  definitionNodes.push({
1778
1934
  type: "paragraph",
1779
- children: parseInlineTokens(contentToken.children || [], contentToken.content || ""),
1780
- raw: contentToken.content || ""
1935
+ children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? "")),
1936
+ raw: String(contentToken.content ?? "")
1781
1937
  });
1782
1938
  k += 3;
1783
1939
  } else k++;
@@ -1802,7 +1958,8 @@ function parseDefinitionList(tokens, index) {
1802
1958
  //#endregion
1803
1959
  //#region src/parser/node-parsers/footnote-parser.ts
1804
1960
  function parseFootnote(tokens, index) {
1805
- const id = tokens[index].meta?.label ?? 0;
1961
+ const meta = tokens[index].meta ?? {};
1962
+ const id = String(meta?.label ?? "0");
1806
1963
  const footnoteChildren = [];
1807
1964
  let j = index + 1;
1808
1965
  while (j < tokens.length && tokens[j].type !== "footnote_close") if (tokens[j].type === "paragraph_open") {
@@ -1810,7 +1967,7 @@ function parseFootnote(tokens, index) {
1810
1967
  footnoteChildren.push({
1811
1968
  type: "paragraph",
1812
1969
  children: parseInlineTokens(contentToken.children || []),
1813
- raw: contentToken.content || ""
1970
+ raw: String(contentToken.content ?? "")
1814
1971
  });
1815
1972
  j += 3;
1816
1973
  } else j++;
@@ -1826,9 +1983,10 @@ function parseFootnote(tokens, index) {
1826
1983
  //#region src/parser/node-parsers/heading-parser.ts
1827
1984
  function parseHeading(tokens, index) {
1828
1985
  const token = tokens[index];
1829
- const headingLevel = Number.parseInt(token.tag?.substring(1) || "1");
1986
+ const levelStr = String(token.tag?.substring(1) ?? "1");
1987
+ const headingLevel = Number.parseInt(levelStr, 10);
1830
1988
  const headingContentToken = tokens[index + 1];
1831
- const headingContent = headingContentToken.content || "";
1989
+ const headingContent = String(headingContentToken.content ?? "");
1832
1990
  return {
1833
1991
  type: "heading",
1834
1992
  level: headingLevel,
@@ -1843,9 +2001,9 @@ function parseHeading(tokens, index) {
1843
2001
  function parseMathBlock(token) {
1844
2002
  return {
1845
2003
  type: "math_block",
1846
- content: token.content || "",
2004
+ content: String(token.content ?? ""),
1847
2005
  loading: !!token.loading,
1848
- raw: token.raw || ""
2006
+ raw: String(token.raw ?? "")
1849
2007
  };
1850
2008
  }
1851
2009
 
@@ -1869,7 +2027,7 @@ function parseTable(tokens, index) {
1869
2027
  while (k < tokens.length && tokens[k].type !== "tr_close") if (tokens[k].type === "th_open" || tokens[k].type === "td_open") {
1870
2028
  const isHeaderCell = tokens[k].type === "th_open";
1871
2029
  const contentToken = tokens[k + 1];
1872
- const content = contentToken.content || "";
2030
+ const content = String(contentToken.content ?? "");
1873
2031
  cells.push({
1874
2032
  type: "table_cell",
1875
2033
  header: isHeaderCell || isHeader,
@@ -1896,7 +2054,7 @@ function parseTable(tokens, index) {
1896
2054
  type: "table",
1897
2055
  header: headerRow,
1898
2056
  rows,
1899
- loading: tokens[index].loading || false,
2057
+ loading: tokens[index].loading ?? false,
1900
2058
  raw: [headerRow, ...rows].map((row) => row.raw).join("\n")
1901
2059
  }, j + 1];
1902
2060
  }
@@ -1917,23 +2075,20 @@ function parseList(tokens, index) {
1917
2075
  const listItems = [];
1918
2076
  let j = index + 1;
1919
2077
  while (j < tokens.length && tokens[j].type !== "bullet_list_close" && tokens[j].type !== "ordered_list_close") if (tokens[j].type === "list_item_open") {
1920
- if (tokens[j].markup === "*") {
1921
- j++;
1922
- continue;
1923
- }
1924
2078
  const itemChildren = [];
1925
2079
  let k = j + 1;
1926
2080
  while (k < tokens.length && tokens[k].type !== "list_item_close") if (tokens[k].type === "paragraph_open") {
1927
2081
  const contentToken = tokens[k + 1];
1928
2082
  const preToken = tokens[k - 1];
1929
- if (/\n\d+$/.test(contentToken.content || "")) {
1930
- contentToken.content = contentToken.content?.replace(/\n\d+$/, "");
2083
+ const contentStr = String(contentToken.content ?? "");
2084
+ if (/\n\d+$/.test(contentStr)) {
2085
+ contentToken.content = contentStr.replace(/\n\d+$/, "");
1931
2086
  contentToken.children?.splice(-1, 1);
1932
2087
  }
1933
2088
  itemChildren.push({
1934
2089
  type: "paragraph",
1935
- children: parseInlineTokens(contentToken.children || [], contentToken.content || "", preToken),
1936
- raw: contentToken.content || ""
2090
+ children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? ""), preToken),
2091
+ raw: String(contentToken.content ?? "")
1937
2092
  });
1938
2093
  k += 3;
1939
2094
  } else if (tokens[k].type === "blockquote_open") {
@@ -1977,7 +2132,7 @@ function parseList(tokens, index) {
1977
2132
  itemChildren.push(parseThematicBreak());
1978
2133
  k += 1;
1979
2134
  } else if (tokens[k].type === "container_open") {
1980
- 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 ?? ""));
1981
2136
  if (match) {
1982
2137
  const [admonitionNode, newIndex] = parseAdmonition(tokens, k, match);
1983
2138
  itemChildren.push(admonitionNode);
@@ -1997,7 +2152,10 @@ function parseList(tokens, index) {
1997
2152
  start: (() => {
1998
2153
  if (token.attrs && token.attrs.length) {
1999
2154
  const found = token.attrs.find((a) => a[0] === "start");
2000
- if (found) return Number(found[1]) || 1;
2155
+ if (found) {
2156
+ const parsed = Number(found[1]);
2157
+ return Number.isFinite(parsed) && parsed !== 0 ? parsed : 1;
2158
+ }
2001
2159
  }
2002
2160
  })(),
2003
2161
  items: listItems,
@@ -2009,10 +2167,6 @@ function parseNestedList(tokens, index) {
2009
2167
  const nestedItems = [];
2010
2168
  let j = index + 1;
2011
2169
  while (j < tokens.length && tokens[j].type !== "bullet_list_close" && tokens[j].type !== "ordered_list_close") if (tokens[j].type === "list_item_open") {
2012
- if (tokens[j].markup === "*") {
2013
- j++;
2014
- continue;
2015
- }
2016
2170
  const itemChildren = [];
2017
2171
  let k = j + 1;
2018
2172
  while (k < tokens.length && tokens[k].type !== "list_item_close") if (tokens[k].type === "paragraph_open") {
@@ -2020,8 +2174,8 @@ function parseNestedList(tokens, index) {
2020
2174
  const preToken = tokens[k - 1];
2021
2175
  itemChildren.push({
2022
2176
  type: "paragraph",
2023
- children: parseInlineTokens(contentToken.children || [], contentToken.content || "", preToken),
2024
- raw: contentToken.content || ""
2177
+ children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? ""), preToken),
2178
+ raw: String(contentToken.content ?? "")
2025
2179
  });
2026
2180
  k += 3;
2027
2181
  } else if (tokens[k].type === "bullet_list_open" || tokens[k].type === "ordered_list_open") {
@@ -2055,7 +2209,10 @@ function parseNestedList(tokens, index) {
2055
2209
  start: (() => {
2056
2210
  if (nestedToken.attrs && nestedToken.attrs.length) {
2057
2211
  const found = nestedToken.attrs.find((a) => a[0] === "start");
2058
- if (found) return Number(found[1]) || 1;
2212
+ if (found) {
2213
+ const parsed = Number(found[1]);
2214
+ return Number.isFinite(parsed) && parsed !== 0 ? parsed : 1;
2215
+ }
2059
2216
  }
2060
2217
  })(),
2061
2218
  items: nestedItems,
@@ -2066,8 +2223,8 @@ function parseNestedList(tokens, index) {
2066
2223
  //#endregion
2067
2224
  //#region src/parser/node-parsers/admonition-parser.ts
2068
2225
  function parseAdmonition(tokens, index, match) {
2069
- const kind = match[1] || "note";
2070
- const title = match[2] || kind.charAt(0).toUpperCase() + kind.slice(1);
2226
+ const kind = String(match[1] ?? "note");
2227
+ const title = String(match[2] ?? kind.charAt(0).toUpperCase() + kind.slice(1));
2071
2228
  const admonitionChildren = [];
2072
2229
  let j = index + 1;
2073
2230
  while (j < tokens.length && tokens[j].type !== "container_close") if (tokens[j].type === "paragraph_open") {
@@ -2075,7 +2232,7 @@ function parseAdmonition(tokens, index, match) {
2075
2232
  if (contentToken) admonitionChildren.push({
2076
2233
  type: "paragraph",
2077
2234
  children: parseInlineTokens(contentToken.children || []),
2078
- raw: contentToken.content || ""
2235
+ raw: String(contentToken.content ?? "")
2079
2236
  });
2080
2237
  j += 3;
2081
2238
  } else if (tokens[j].type === "bullet_list_open" || tokens[j].type === "ordered_list_open") {
@@ -2101,17 +2258,17 @@ function parseContainer(tokens, index) {
2101
2258
  const typeMatch = openToken.type.match(/^container_(\w+)_open$/);
2102
2259
  if (typeMatch) {
2103
2260
  kind = typeMatch[1];
2104
- const info = (openToken.info || "").trim();
2261
+ const info = String(openToken.info ?? "").trim();
2105
2262
  if (info && !info.startsWith(":::")) {
2106
2263
  const maybe = info.replace(/* @__PURE__ */ new RegExp(`^${kind}`), "").trim();
2107
2264
  if (maybe) title = maybe;
2108
2265
  }
2109
2266
  } else {
2110
- const info = (openToken.info || "").trim();
2267
+ const info = String(openToken.info ?? "").trim();
2111
2268
  const match = /^:{1,3}\s*(warning|info|note|tip|danger|caution)\s*(.*)$/i.exec(info);
2112
2269
  if (match) {
2113
2270
  kind = match[1];
2114
- title = match[2] || "";
2271
+ title = String(match[2] ?? "");
2115
2272
  }
2116
2273
  }
2117
2274
  if (!title) title = kind.charAt(0).toUpperCase() + kind.slice(1);
@@ -2121,12 +2278,20 @@ function parseContainer(tokens, index) {
2121
2278
  while (j < tokens.length && tokens[j].type !== "container_close" && !closeType.test(tokens[j].type)) if (tokens[j].type === "paragraph_open") {
2122
2279
  const contentToken = tokens[j + 1];
2123
2280
  if (contentToken) {
2124
- const i = contentToken.children.findLastIndex((t) => t.type === "text" && /:+/.test(t.content));
2125
- const _children = i !== -1 ? contentToken.children?.slice(0, i) : contentToken.children;
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;
2126
2291
  children.push({
2127
2292
  type: "paragraph",
2128
2293
  children: parseInlineTokens(_children || []),
2129
- raw: contentToken.content?.replace(/\n:+$/, "").replace(/\n\s*:::\s*$/, "") || ""
2294
+ raw: String(contentToken.content ?? "").replace(/\n:+$/, "").replace(/\n\s*:::\s*$/, "")
2130
2295
  });
2131
2296
  }
2132
2297
  j += 3;
@@ -2157,7 +2322,7 @@ function parseHardBreak() {
2157
2322
  //#region src/parser/node-parsers/paragraph-parser.ts
2158
2323
  function parseParagraph(tokens, index) {
2159
2324
  const paragraphContentToken = tokens[index + 1];
2160
- const paragraphContent = paragraphContentToken.content || "";
2325
+ const paragraphContent = String(paragraphContentToken.content ?? "");
2161
2326
  return {
2162
2327
  type: "paragraph",
2163
2328
  children: parseInlineTokens(paragraphContentToken.children || [], paragraphContent),
@@ -2179,7 +2344,15 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
2179
2344
  let transformedTokens = tokens;
2180
2345
  if (pre && typeof pre === "function") transformedTokens = pre(tokens) || tokens;
2181
2346
  let result = processTokens(transformedTokens);
2182
- if (post && typeof post === "function") result = post(transformedTokens) || transformedTokens;
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
+ }
2183
2356
  return result;
2184
2357
  }
2185
2358
  function processTokens(tokens) {
@@ -2255,7 +2428,7 @@ function processTokens(tokens) {
2255
2428
  break;
2256
2429
  }
2257
2430
  case "container_open": {
2258
- 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 ?? ""));
2259
2432
  if (match) {
2260
2433
  const [admonitionNode, newIndex] = parseAdmonition(tokens, i, match);
2261
2434
  result.push(admonitionNode);
@@ -2290,8 +2463,14 @@ function getMarkdown(msgId = `editor-${Date.now()}`, options = {}) {
2290
2463
  const i18nMap = options.i18n;
2291
2464
  t = (key) => i18nMap[key] ?? defaultTranslations[key] ?? key;
2292
2465
  } else t = (key) => defaultTranslations[key] ?? key;
2293
- if (Array.isArray(options.plugin)) for (const p of options.plugin) if (Array.isArray(p)) md.use(p[0], p[1]);
2294
- else md.use(p);
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
+ }
2295
2474
  if (Array.isArray(options.apply)) for (const fn of options.apply) try {
2296
2475
  fn(md);
2297
2476
  } catch (e) {
@@ -2306,8 +2485,9 @@ function getMarkdown(msgId = `editor-${Date.now()}`, options = {}) {
2306
2485
  md.use(markdownItIns);
2307
2486
  md.use(markdownItFootnote);
2308
2487
  md.core.ruler.after("block", "mark_fence_closed", (state) => {
2309
- const lines = state.src.split(/\r?\n/);
2310
- for (const token of state.tokens) {
2488
+ const s = state;
2489
+ const lines = s.src.split(/\r?\n/);
2490
+ for (const token of s.tokens) {
2311
2491
  if (token.type !== "fence" || !token.map || !token.markup) continue;
2312
2492
  const openLine = token.map[0];
2313
2493
  const endLine = token.map[1];
@@ -2322,33 +2502,35 @@ function getMarkdown(msgId = `editor-${Date.now()}`, options = {}) {
2322
2502
  let j = i + count;
2323
2503
  while (j < line.length && (line[j] === " " || line[j] === " ")) j++;
2324
2504
  const closed = endLine > openLine + 1 && count >= minLen && j === line.length;
2325
- token.meta = token.meta || {};
2326
- token.meta.unclosed = !closed;
2327
- token.meta.closed = !!closed;
2505
+ const tokenShape = token;
2506
+ tokenShape.meta = tokenShape.meta ?? {};
2507
+ tokenShape.meta.unclosed = !closed;
2508
+ tokenShape.meta.closed = !!closed;
2328
2509
  }
2329
2510
  });
2330
2511
  const waveRule = (state, silent) => {
2331
- const start = state.pos;
2332
- if (state.src[start] !== "~") return false;
2333
- const prevChar = state.src[start - 1];
2334
- const nextChar = state.src[start + 1];
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];
2335
2517
  if (/\d/.test(prevChar) && /\d/.test(nextChar)) {
2336
2518
  if (!silent) {
2337
- const token = state.push("text", "", 0);
2519
+ const token = s.push("text", "", 0);
2338
2520
  token.content = "~";
2339
2521
  }
2340
- state.pos += 1;
2522
+ s.pos += 1;
2341
2523
  return true;
2342
2524
  }
2343
2525
  return false;
2344
2526
  };
2345
2527
  md.inline.ruler.before("sub", "wave", waveRule);
2346
2528
  md.renderer.rules.fence = (tokens, idx) => {
2347
- const token = tokens[idx];
2348
- const info = token.info ? token.info.trim() : "";
2349
- const str = token.content;
2529
+ const tokenShape = tokens[idx];
2530
+ const info = String(tokenShape.info ?? "").trim();
2531
+ const str = String(tokenShape.content ?? "");
2350
2532
  const encodedCode = btoa(unescape(encodeURIComponent(str)));
2351
- const language = info || "text";
2533
+ const language = String(info ?? "text");
2352
2534
  return `<div class="code-block" data-code="${encodedCode}" data-lang="${language}" id="${`editor-${msgId}-${idx}-${language}`}">
2353
2535
  <div class="code-header">
2354
2536
  <span class="code-lang">${language.toUpperCase()}</span>
@@ -2358,21 +2540,23 @@ function getMarkdown(msgId = `editor-${Date.now()}`, options = {}) {
2358
2540
  </div>`;
2359
2541
  };
2360
2542
  const referenceInline = (state, silent) => {
2361
- if (state.src[state.pos] !== "[") return false;
2362
- const match = /^\[(\d+)\]/.exec(state.src.slice(state.pos));
2543
+ const s = state;
2544
+ if (s.src[s.pos] !== "[") return false;
2545
+ const match = /^\[(\d+)\]/.exec(s.src.slice(s.pos));
2363
2546
  if (!match) return false;
2364
2547
  if (!silent) {
2365
2548
  const id = match[1];
2366
- const token = state.push("reference", "span", 0);
2549
+ const token = s.push("reference", "span", 0);
2367
2550
  token.content = id;
2368
2551
  token.markup = match[0];
2369
2552
  }
2370
- state.pos += match[0].length;
2553
+ s.pos += match[0].length;
2371
2554
  return true;
2372
2555
  };
2373
2556
  md.inline.ruler.before("escape", "reference", referenceInline);
2374
2557
  md.renderer.rules.reference = (tokens, idx) => {
2375
- const id = tokens[idx].content;
2558
+ const tokensAny = tokens;
2559
+ const id = String(tokensAny[idx].content ?? "");
2376
2560
  return `<span class="reference-link" data-reference-id="${id}" role="button" tabindex="0" title="Click to view reference">${id}</span>`;
2377
2561
  };
2378
2562
  return md;