stream-markdown-parser 0.0.7 → 0.0.9

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,44 +36,470 @@ 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
  }
76
77
 
78
+ //#endregion
79
+ //#region src/plugins/fixLinkInline.ts
80
+ function applyFixLinkInline(md) {
81
+ const rule = (state, silent) => {
82
+ const s = state;
83
+ const start = s.pos;
84
+ if (s.src[start] !== "[") return false;
85
+ if (start > 0 && s.src[start - 1] === "!") return false;
86
+ const rest = s.src.slice(start);
87
+ const m = /^\[([^\]]*)\]\(([^)\s]*)?/.exec(rest);
88
+ if (!m) return false;
89
+ if (silent) return true;
90
+ const text = m[1] ?? "";
91
+ const href = m[2] ?? "";
92
+ if (text.includes("*") || text.includes(":")) return false;
93
+ const idxClose = rest.indexOf(")");
94
+ const hasClosingParen = idxClose !== -1;
95
+ const open = s.push("link_open", "a", 1);
96
+ open.attrs = [["href", href]];
97
+ const txt = s.push("text", "", 0);
98
+ txt.content = text;
99
+ if (hasClosingParen) {
100
+ s.push("link_close", "a", -1);
101
+ s.pos += idxClose + 1;
102
+ } else s.pos += m[0].length;
103
+ return true;
104
+ };
105
+ md.inline.ruler.before("link", "fix_link_inline", rule);
106
+ }
107
+
108
+ //#endregion
109
+ //#region src/parser/inline-parsers/fixLinkToken.ts
110
+ function isTextToken(t) {
111
+ return !!t && t.type === "text" && typeof t.content === "string";
112
+ }
113
+ function fixLinkToken(tokens) {
114
+ const tokensAny = tokens;
115
+ tokens = fixLinkToken4(fixLinkToken3(tokens));
116
+ if (tokens.length < 5) return tokens;
117
+ const first = tokens[tokens.length - 5];
118
+ const firstAny = first;
119
+ const firstContent = String(firstAny.content ?? "");
120
+ if (first.type !== "text" || !firstContent.endsWith("[")) return fixLinkTokens2(tokens);
121
+ if (tokens[tokens.length - 4].tag !== "em") return fixLinkTokens2(tokens);
122
+ const last = tokens[tokens.length - 1];
123
+ const lastAny = last;
124
+ const lastContent = String(lastAny.content ?? "");
125
+ if (last?.type === "text" && !lastContent.startsWith("]")) return fixLinkTokens2(tokens);
126
+ const thirdAny = tokens[tokens.length - 3];
127
+ const thirdContent = String(thirdAny.content ?? "");
128
+ const href = lastContent.replace(/^\]\(*/, "");
129
+ const loading = !lastContent.includes(")");
130
+ tokensAny[tokens.length - 5].content = firstContent.replace(/\[$/, "");
131
+ tokens.splice(tokens.length - 3, 1, {
132
+ type: "link",
133
+ href,
134
+ text: thirdContent,
135
+ children: [{
136
+ type: "text",
137
+ content: thirdContent,
138
+ raw: thirdContent
139
+ }],
140
+ loading
141
+ });
142
+ tokens.splice(tokens.length - 1, 1);
143
+ return tokens;
144
+ }
145
+ function fixLinkTokens2(tokens) {
146
+ const tokensAny = tokens;
147
+ if (tokens.length < 8) return tokens;
148
+ let length = tokens.length;
149
+ let last = tokens[length - 1];
150
+ if (last.type !== "link_close") {
151
+ length--;
152
+ last = tokens[length - 1];
153
+ if (last.type !== "link_close") return tokens;
154
+ }
155
+ if (tokens[length - 7].type !== "em_open") return tokens;
156
+ const third = tokens[length - 6];
157
+ const first = tokens[length - 8];
158
+ if (first.type !== "text") return tokens;
159
+ let href = String(tokensAny[length - 2]?.content ?? "");
160
+ let count = 4;
161
+ if (length !== tokens.length) {
162
+ href += String(last.content ?? "");
163
+ count++;
164
+ }
165
+ tokens.splice(length - 4, count);
166
+ const thirdAny = third;
167
+ const content = String(thirdAny.content ?? "");
168
+ length -= 4;
169
+ const firstAny = first;
170
+ tokensAny[length - 8].content = String(firstAny.content ?? "").replace(/\[$/, "");
171
+ tokens.splice(length - 2, 1, {
172
+ type: "link",
173
+ href,
174
+ text: content,
175
+ children: [{
176
+ type: "text",
177
+ content,
178
+ raw: content
179
+ }],
180
+ loading: true
181
+ });
182
+ return tokens;
183
+ }
184
+ function fixLinkToken3(tokens) {
185
+ const tokensAny = tokens;
186
+ const last = tokens[tokens.length - 1];
187
+ const preLast = tokens[tokens.length - 2];
188
+ const fixedTokens = [...tokens];
189
+ if (last.type !== "text" || !last.content?.startsWith(")")) return tokens;
190
+ if (preLast.type !== "link_close") return tokens;
191
+ if (isTextToken(tokens[tokens.length - 5]) && String(tokens[tokens.length - 5].content ?? "").endsWith("(")) {
192
+ const a = tokensAny[tokens.length - 5];
193
+ const b = tokensAny[tokens.length - 3];
194
+ const content = String(a.content ?? "") + String(b.content ?? "") + String(last.content ?? "");
195
+ fixedTokens.splice(tokens.length - 5, 5, {
196
+ type: "text",
197
+ content,
198
+ raw: content
199
+ });
200
+ } else {
201
+ const lc = (last.content ?? "").slice(1);
202
+ fixedTokens[fixedTokens.length - 1] = {
203
+ ...last,
204
+ content: lc
205
+ };
206
+ }
207
+ return fixedTokens;
208
+ }
209
+ function fixLinkToken4(tokens) {
210
+ const tokensAny = tokens;
211
+ const fixedTokens = [...tokens];
212
+ for (let i = tokens.length - 1; i >= 3; i--) if (tokens[i].type === "link_close") {
213
+ if (tokens[i - 3]?.content?.endsWith("(")) {
214
+ const nextToken = tokens[i + 1];
215
+ if (nextToken?.type === "text") {
216
+ if (tokens[i - 1].type === "text" && tokens[i - 3].type === "text") {
217
+ const nextTokenContent = String(nextToken.content ?? "");
218
+ const a = tokensAny[i - 3];
219
+ const b = tokensAny[i - 1];
220
+ const content = String(a.content ?? "") + String(b.content ?? "") + nextTokenContent;
221
+ fixedTokens.splice(i - 3, 5, {
222
+ type: "text",
223
+ content,
224
+ raw: content
225
+ });
226
+ i -= 3;
227
+ }
228
+ } else {
229
+ if (tokens[i - 1].type === "text" && tokens[i - 3].type === "text") {
230
+ const a = tokensAny[i - 3];
231
+ const b = tokensAny[i - 1];
232
+ const content = String(a.content ?? "") + String(b.content ?? "");
233
+ fixedTokens.splice(i - 3, 4, {
234
+ type: "text",
235
+ content,
236
+ raw: content
237
+ });
238
+ }
239
+ i -= 3;
240
+ }
241
+ }
242
+ }
243
+ return fixedTokens;
244
+ }
245
+
246
+ //#endregion
247
+ //#region src/plugins/fixLinkTokens.ts
248
+ function applyFixLinkTokens(md) {
249
+ md.core.ruler.after("inline", "fix_link_tokens", (state) => {
250
+ const toks = state.tokens ?? [];
251
+ for (let i = 0; i < toks.length; i++) {
252
+ const t = toks[i];
253
+ if (t && t.type === "inline" && Array.isArray(t.children)) try {
254
+ t.children = fixLinkToken(t.children);
255
+ } catch (e) {
256
+ console.error("[applyFixLinkTokens] failed to fix inline children", e);
257
+ }
258
+ }
259
+ });
260
+ }
261
+
262
+ //#endregion
263
+ //#region src/parser/inline-parsers/fixListItem.ts
264
+ function fixListItem(tokens) {
265
+ const last = tokens[tokens.length - 1];
266
+ const lastContent = String(last?.content ?? "");
267
+ if (last?.type === "text" && /^\s*\d+\.\s*$/.test(lastContent) && tokens[tokens.length - 2]?.tag === "br") tokens.splice(tokens.length - 1, 1);
268
+ return tokens;
269
+ }
270
+
271
+ //#endregion
272
+ //#region src/plugins/fixListItem.ts
273
+ function applyFixListItem(md) {
274
+ md.core.ruler.after("inline", "fix_list_item_tokens", (state) => {
275
+ const toks = state.tokens ?? [];
276
+ for (let i = 0; i < toks.length; i++) {
277
+ const t = toks[i];
278
+ if (t && t.type === "inline" && Array.isArray(t.children)) try {
279
+ t.children = fixListItem(t.children);
280
+ } catch (e) {
281
+ console.error("[applyFixListItem] failed to fix inline children", e);
282
+ }
283
+ }
284
+ });
285
+ }
286
+
287
+ //#endregion
288
+ //#region src/parser/inline-parsers/fixStrongTokens.ts
289
+ function fixStrongTokens(tokens) {
290
+ const fixedTokens = [...tokens];
291
+ if (tokens.length < 4) return fixedTokens;
292
+ const i = tokens.length - 4;
293
+ const token = tokens[i];
294
+ const nextToken = tokens[i + 1];
295
+ const tokenContent = String(token.content ?? "");
296
+ if (token.type === "text" && tokenContent.endsWith("*") && nextToken.type === "em_open") {
297
+ const _nextToken = tokens[i + 2];
298
+ const count = _nextToken?.type === "text" ? 4 : 3;
299
+ const insert = [
300
+ {
301
+ type: "strong_open",
302
+ tag: "strong",
303
+ attrs: null,
304
+ map: null,
305
+ children: null,
306
+ content: "",
307
+ markup: "**",
308
+ info: "",
309
+ meta: null
310
+ },
311
+ {
312
+ type: "text",
313
+ content: _nextToken?.type === "text" ? String(_nextToken.content ?? "") : ""
314
+ },
315
+ {
316
+ type: "strong_close",
317
+ tag: "strong",
318
+ attrs: null,
319
+ map: null,
320
+ children: null,
321
+ content: "",
322
+ markup: "**",
323
+ info: "",
324
+ meta: null
325
+ }
326
+ ];
327
+ const beforeText = tokenContent.slice(0, -1);
328
+ if (beforeText) insert.unshift({
329
+ type: "text",
330
+ content: beforeText,
331
+ raw: beforeText
332
+ });
333
+ fixedTokens.splice(i, count, ...insert);
334
+ return fixedTokens;
335
+ }
336
+ return fixedTokens;
337
+ }
338
+
339
+ //#endregion
340
+ //#region src/plugins/fixStrongTokens.ts
341
+ function applyFixStrongTokens(md) {
342
+ md.core.ruler.after("inline", "fix_strong_tokens", (state) => {
343
+ const toks = state.tokens ?? [];
344
+ for (let i = 0; i < toks.length; i++) {
345
+ const t = toks[i];
346
+ if (t && t.type === "inline" && Array.isArray(t.children)) try {
347
+ t.children = fixStrongTokens(t.children);
348
+ } catch (e) {
349
+ console.error("[applyFixStrongTokens] failed to fix inline children", e);
350
+ }
351
+ }
352
+ });
353
+ }
354
+
355
+ //#endregion
356
+ //#region src/parser/fixTableTokens.ts
357
+ function createStart() {
358
+ return [
359
+ {
360
+ type: "table_open",
361
+ tag: "table",
362
+ attrs: null,
363
+ map: null,
364
+ children: null,
365
+ content: "",
366
+ markup: "",
367
+ info: "",
368
+ level: 0,
369
+ loading: true,
370
+ meta: null
371
+ },
372
+ {
373
+ type: "thead_open",
374
+ tag: "thead",
375
+ attrs: null,
376
+ block: true,
377
+ level: 1,
378
+ children: null
379
+ },
380
+ {
381
+ type: "tr_open",
382
+ tag: "tr",
383
+ attrs: null,
384
+ block: true,
385
+ level: 2,
386
+ children: null
387
+ }
388
+ ];
389
+ }
390
+ function createEnd() {
391
+ return [
392
+ {
393
+ type: "tr_close",
394
+ tag: "tr",
395
+ attrs: null,
396
+ block: true,
397
+ level: 2,
398
+ children: null
399
+ },
400
+ {
401
+ type: "thead_close",
402
+ tag: "thead",
403
+ attrs: null,
404
+ block: true,
405
+ level: 1,
406
+ children: null
407
+ },
408
+ {
409
+ type: "table_close",
410
+ tag: "table",
411
+ attrs: null,
412
+ map: null,
413
+ children: null,
414
+ content: "",
415
+ markup: "",
416
+ info: "",
417
+ level: 0,
418
+ meta: null
419
+ }
420
+ ];
421
+ }
422
+ function createTh(text) {
423
+ return [
424
+ {
425
+ type: "th_open",
426
+ tag: "th",
427
+ attrs: null,
428
+ block: true,
429
+ level: 3,
430
+ children: null
431
+ },
432
+ {
433
+ type: "inline",
434
+ tag: "",
435
+ children: [{
436
+ tag: "",
437
+ type: "text",
438
+ block: false,
439
+ content: text,
440
+ children: null
441
+ }],
442
+ content: text,
443
+ level: 4,
444
+ attrs: null,
445
+ block: true
446
+ },
447
+ {
448
+ type: "th_close",
449
+ tag: "th",
450
+ attrs: null,
451
+ block: true,
452
+ level: 3,
453
+ children: null
454
+ }
455
+ ];
456
+ }
457
+ function fixTableTokens(tokens) {
458
+ const fixedTokens = [...tokens];
459
+ if (tokens.length < 3) return fixedTokens;
460
+ const i = tokens.length - 2;
461
+ const token = tokens[i];
462
+ if (token.type === "inline") {
463
+ const tcontent = String(token.content ?? "");
464
+ const childContent = String(token.children?.[0]?.content ?? "");
465
+ if (/^\|(?:[^|\n]+\|?)+/.test(tcontent)) {
466
+ const body = childContent.slice(1).split("|").map((i$1) => i$1.trim()).filter(Boolean).flatMap((i$1) => createTh(i$1));
467
+ const insert = [
468
+ ...createStart(),
469
+ ...body,
470
+ ...createEnd()
471
+ ];
472
+ fixedTokens.splice(i - 1, 3, ...insert);
473
+ } else if (/^\|(?:[^|\n]+\|)+\n\|:?-/.test(tcontent)) {
474
+ const body = childContent.slice(1, -1).split("|").map((i$1) => i$1.trim()).flatMap((i$1) => createTh(i$1));
475
+ const insert = [
476
+ ...createStart(),
477
+ ...body,
478
+ ...createEnd()
479
+ ];
480
+ fixedTokens.splice(i - 1, 3, ...insert);
481
+ } else if (/^\|(?:[^|\n:]+\|)+\n\|:?$/.test(tcontent)) {
482
+ token.content = tcontent.slice(0, -2);
483
+ token.children.splice(2, 1);
484
+ }
485
+ }
486
+ return fixedTokens;
487
+ }
488
+
489
+ //#endregion
490
+ //#region src/plugins/fixTableTokens.ts
491
+ function applyFixTableTokens(md) {
492
+ md.core.ruler.after("block", "fix_table_tokens", (state) => {
493
+ const s = state;
494
+ try {
495
+ const fixed = fixTableTokens(s.tokens ?? []);
496
+ if (Array.isArray(fixed)) s.tokens = fixed;
497
+ } catch (e) {
498
+ console.error("[applyFixTableTokens] failed to fix table tokens", e);
499
+ }
500
+ });
501
+ }
502
+
77
503
  //#endregion
78
504
  //#region src/findMatchingClose.ts
79
505
  function findMatchingClose(src, startIdx, open, close) {
@@ -278,7 +704,8 @@ function normalizeStandaloneBackslashT(s, opts) {
278
704
  }
279
705
  function applyMath(md, mathOpts) {
280
706
  const mathInline = (state, silent) => {
281
- if (/^\*[^*]+/.test(state.src)) return false;
707
+ const s = state;
708
+ if (/^\*[^*]+/.test(s.src)) return false;
282
709
  const delimiters = [
283
710
  ["$$", "$$"],
284
711
  ["\\(", "\\)"],
@@ -287,28 +714,28 @@ function applyMath(md, mathOpts) {
287
714
  let searchPos = 0;
288
715
  let preMathPos = 0;
289
716
  for (const [open, close] of delimiters) {
290
- const src = state.src;
717
+ const src = s.src;
291
718
  let foundAny = false;
292
719
  const pushText = (text) => {
293
720
  if (text === "undefined" || text == null) text = "";
294
721
  if (text === "\\") {
295
- state.pos = state.pos + text.length;
296
- searchPos = state.pos;
722
+ s.pos = s.pos + text.length;
723
+ searchPos = s.pos;
297
724
  return;
298
725
  }
299
726
  if (text === "\\)" || text === "\\(") {
300
- const t$1 = state.push("text_special", "", 0);
727
+ const t$1 = s.push("text_special", "", 0);
301
728
  t$1.content = text === "\\)" ? ")" : "(";
302
729
  t$1.markup = text;
303
- state.pos = state.pos + text.length;
304
- searchPos = state.pos;
730
+ s.pos = s.pos + text.length;
731
+ searchPos = s.pos;
305
732
  return;
306
733
  }
307
734
  if (!text) return;
308
- const t = state.push("text", "", 0);
735
+ const t = s.push("text", "", 0);
309
736
  t.content = text;
310
- state.pos = state.pos + text.length;
311
- searchPos = state.pos;
737
+ s.pos = s.pos + text.length;
738
+ searchPos = s.pos;
312
739
  };
313
740
  while (true) {
314
741
  if (searchPos >= src.length) break;
@@ -326,28 +753,28 @@ function applyMath(md, mathOpts) {
326
753
  searchPos = index + open.length;
327
754
  foundAny = true;
328
755
  if (!silent) {
329
- state.pending = "";
756
+ s.pending = "";
330
757
  const isStrongPrefix = countUnescapedStrong(preMathPos ? src.slice(preMathPos, searchPos) : src.slice(0, searchPos)) % 2 === 1;
331
758
  if (preMathPos) pushText(src.slice(preMathPos, searchPos));
332
759
  else pushText(src.slice(0, searchPos));
333
760
  if (isStrongPrefix) {
334
- const strongToken = state.push("strong_open", "", 0);
761
+ const strongToken = s.push("strong_open", "", 0);
335
762
  strongToken.markup = src.slice(0, index + 2);
336
- const token = state.push("math_inline", "math", 0);
763
+ const token = s.push("math_inline", "math", 0);
337
764
  token.content = normalizeStandaloneBackslashT(content$1, mathOpts);
338
765
  token.markup = open === "$$" ? "$$" : open === "\\(" ? "\\(\\)" : open === "$" ? "$" : "()";
339
766
  token.raw = `${open}${content$1}${close}`;
340
767
  token.loading = true;
341
768
  strongToken.content = content$1;
342
- state.push("strong_close", "", 0);
769
+ s.push("strong_close", "", 0);
343
770
  } else {
344
- const token = state.push("math_inline", "math", 0);
771
+ const token = s.push("math_inline", "math", 0);
345
772
  token.content = normalizeStandaloneBackslashT(content$1, mathOpts);
346
773
  token.markup = open === "$$" ? "$$" : open === "\\(" ? "\\(\\)" : open === "$" ? "$" : "()";
347
774
  token.raw = `${open}${content$1}${close}`;
348
775
  token.loading = true;
349
776
  }
350
- state.pos = src.length;
777
+ s.pos = src.length;
351
778
  }
352
779
  searchPos = src.length;
353
780
  preMathPos = searchPos;
@@ -357,8 +784,8 @@ function applyMath(md, mathOpts) {
357
784
  const content = src.slice(index + open.length, endIdx);
358
785
  if (!isMathLike(content)) {
359
786
  searchPos = endIdx + close.length;
360
- const text = src.slice(state.pos, searchPos);
361
- if (!state.pending) pushText(text);
787
+ const text = src.slice(s.pos, searchPos);
788
+ if (!s.pending) pushText(text);
362
789
  continue;
363
790
  }
364
791
  foundAny = true;
@@ -366,42 +793,42 @@ function applyMath(md, mathOpts) {
366
793
  const before = src.slice(0, index);
367
794
  let toPushBefore = src.slice(0, searchPos) ? src.slice(preMathPos, index) : before;
368
795
  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 = "";
796
+ if (index !== s.pos && isStrongPrefix) toPushBefore = s.pending + src.slice(s.pos, index);
797
+ if (s.pending !== toPushBefore) {
798
+ s.pending = "";
372
799
  if (isStrongPrefix) {
373
800
  const _match = toPushBefore.match(/(\*+)/);
374
801
  const after = toPushBefore.slice(_match.index + _match[0].length);
375
802
  pushText(toPushBefore.slice(0, _match.index));
376
- const strongToken = state.push("strong_open", "", 0);
803
+ const strongToken = s.push("strong_open", "", 0);
377
804
  strongToken.markup = _match[0];
378
- const textToken = state.push("text", "", 0);
805
+ const textToken = s.push("text", "", 0);
379
806
  textToken.content = after;
380
- state.push("strong_close", "", 0);
807
+ s.push("strong_close", "", 0);
381
808
  } else pushText(toPushBefore);
382
809
  }
383
810
  if (isStrongPrefix) {
384
- const strongToken = state.push("strong_open", "", 0);
811
+ const strongToken = s.push("strong_open", "", 0);
385
812
  strongToken.markup = "**";
386
- const token = state.push("math_inline", "math", 0);
813
+ const token = s.push("math_inline", "math", 0);
387
814
  token.content = normalizeStandaloneBackslashT(content, mathOpts);
388
815
  token.markup = open === "$$" ? "$$" : open === "\\(" ? "\\(\\)" : open === "$" ? "$" : "()";
389
816
  token.raw = `${open}${content}${close}`;
390
817
  token.loading = false;
391
818
  const raw = src.slice(endIdx + close.length);
392
819
  const isBeforeClose = raw.startsWith("*");
393
- if (isBeforeClose) state.push("strong_close", "", 0);
820
+ if (isBeforeClose) s.push("strong_close", "", 0);
394
821
  if (raw) {
395
- const textContentToken = state.push("text", "", 0);
822
+ const textContentToken = s.push("text", "", 0);
396
823
  textContentToken.content = (raw == null ? "" : String(raw)).replace(/^\*+/, "");
397
824
  }
398
- if (!isBeforeClose) state.push("strong_close", "", 0);
399
- state.pos = src.length;
825
+ if (!isBeforeClose) s.push("strong_close", "", 0);
826
+ s.pos = src.length;
400
827
  searchPos = src.length;
401
828
  preMathPos = searchPos;
402
829
  continue;
403
830
  } else {
404
- const token = state.push("math_inline", "math", 0);
831
+ const token = s.push("math_inline", "math", 0);
405
832
  token.content = normalizeStandaloneBackslashT(content, mathOpts);
406
833
  token.markup = open === "$$" ? "$$" : open === "\\(" ? "\\(\\)" : open === "$" ? "$" : "()";
407
834
  token.raw = `${open}${content}${close}`;
@@ -410,26 +837,27 @@ function applyMath(md, mathOpts) {
410
837
  }
411
838
  searchPos = endIdx + close.length;
412
839
  preMathPos = searchPos;
413
- state.pos = searchPos;
840
+ s.pos = searchPos;
414
841
  }
415
842
  if (foundAny) {
416
843
  if (!silent) {
417
844
  if (searchPos < src.length) pushText(src.slice(searchPos));
418
- state.pos = src.length;
419
- } else state.pos = searchPos;
845
+ s.pos = src.length;
846
+ } else s.pos = searchPos;
420
847
  return true;
421
848
  }
422
849
  }
423
850
  return false;
424
851
  };
425
852
  const mathBlock = (state, startLine, endLine, silent) => {
853
+ const s = state;
426
854
  const delimiters = [
427
855
  ["\\[", "\\]"],
428
856
  ["[", "]"],
429
857
  ["$$", "$$"]
430
858
  ];
431
- const startPos = state.bMarks[startLine] + state.tShift[startLine];
432
- const lineText = state.src.slice(startPos, state.eMarks[startLine]).trim();
859
+ const startPos = s.bMarks[startLine] + s.tShift[startLine];
860
+ const lineText = s.src.slice(startPos, s.eMarks[startLine]).trim();
433
861
  let matched = false;
434
862
  let openDelim = "";
435
863
  let closeDelim = "";
@@ -455,14 +883,14 @@ function applyMath(md, mathOpts) {
455
883
  const startDelimIndex = lineText.indexOf(openDelim);
456
884
  const endDelimIndex = lineText.indexOf(closeDelim, startDelimIndex + openDelim.length);
457
885
  const content$1 = lineText.slice(startDelimIndex + openDelim.length, endDelimIndex);
458
- const token$1 = state.push("math_block", "math", 0);
886
+ const token$1 = s.push("math_block", "math", 0);
459
887
  token$1.content = normalizeStandaloneBackslashT(content$1);
460
888
  token$1.markup = openDelim === "$$" ? "$$" : openDelim === "[" ? "[]" : "\\[\\]";
461
889
  token$1.map = [startLine, startLine + 1];
462
890
  token$1.raw = `${openDelim}${content$1}${closeDelim}`;
463
891
  token$1.block = true;
464
892
  token$1.loading = false;
465
- state.line = startLine + 1;
893
+ s.line = startLine + 1;
466
894
  return true;
467
895
  }
468
896
  let nextLine = startLine;
@@ -476,233 +904,114 @@ function applyMath(md, mathOpts) {
476
904
  nextLine = startLine;
477
905
  } else {
478
906
  if (firstLineContent) content = firstLineContent;
479
- 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
- if (currentLine.trim() === closeDelim) {
484
- found = true;
485
- break;
486
- } else if (currentLine.includes(closeDelim)) {
487
- found = true;
488
- const endIndex = currentLine.indexOf(closeDelim);
489
- content += (content ? "\n" : "") + currentLine.slice(0, endIndex);
490
- break;
491
- }
492
- content += (content ? "\n" : "") + currentLine;
493
- }
494
- }
495
- const token = state.push("math_block", "math", 0);
496
- token.content = normalizeStandaloneBackslashT(content);
497
- token.markup = openDelim === "$$" ? "$$" : openDelim === "[" ? "[]" : "\\[\\]";
498
- token.raw = `${openDelim}${content}${content.startsWith("\n") ? "\n" : ""}${closeDelim}`;
499
- token.map = [startLine, nextLine + 1];
500
- token.block = true;
501
- token.loading = !found;
502
- state.line = nextLine + 1;
503
- return true;
504
- };
505
- md.inline.ruler.before("escape", "math", mathInline);
506
- md.block.ruler.before("paragraph", "math_block", mathBlock, { alt: [
507
- "paragraph",
508
- "reference",
509
- "blockquote",
510
- "list"
511
- ] });
512
- }
513
-
514
- //#endregion
515
- //#region src/renderers/index.ts
516
- function applyRenderRules(md) {
517
- const defaultImage = md.renderer.rules.image || function(tokens, idx, options, env, self) {
518
- return self.renderToken(tokens, idx, options);
519
- };
520
- md.renderer.rules.image = (tokens, idx, options, env, self) => {
521
- tokens[idx].attrSet?.("loading", "lazy");
522
- return defaultImage(tokens, idx, options, env, self);
523
- };
524
- 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>`;
528
- });
529
- }
530
-
531
- //#endregion
532
- //#region src/factory.ts
533
- function factory(opts = {}) {
534
- const md = new MarkdownIt({
535
- html: true,
536
- linkify: true,
537
- typographer: true,
538
- ...opts.markdownItOptions ?? {}
539
- });
540
- if (opts.enableMath ?? true) applyMath(md, {
541
- ...getDefaultMathOptions() ?? {},
542
- ...opts.mathOptions ?? {}
543
- });
544
- if (opts.enableContainers ?? true) applyContainers(md);
545
- applyRenderRules(md);
546
- return md;
547
- }
548
-
549
- //#endregion
550
- //#region src/parser/fixTableTokens.ts
551
- function createStart() {
552
- return [
553
- {
554
- type: "table_open",
555
- tag: "table",
556
- attrs: null,
557
- map: null,
558
- children: null,
559
- content: "",
560
- markup: "",
561
- info: "",
562
- level: 0,
563
- loading: true,
564
- meta: null
565
- },
566
- {
567
- type: "thead_open",
568
- tag: "thead",
569
- attrs: null,
570
- block: true,
571
- level: 1,
572
- children: null
573
- },
574
- {
575
- type: "tr_open",
576
- tag: "tr",
577
- attrs: null,
578
- block: true,
579
- level: 2,
580
- children: null
581
- }
582
- ];
583
- }
584
- function createEnd() {
585
- return [
586
- {
587
- type: "tr_close",
588
- tag: "tr",
589
- attrs: null,
590
- block: true,
591
- level: 2,
592
- children: null
593
- },
594
- {
595
- type: "thead_close",
596
- tag: "thead",
597
- attrs: null,
598
- block: true,
599
- level: 1,
600
- children: null
601
- },
602
- {
603
- type: "table_close",
604
- tag: "table",
605
- attrs: null,
606
- map: null,
607
- children: null,
608
- content: "",
609
- markup: "",
610
- info: "",
611
- level: 0,
612
- meta: null
613
- }
614
- ];
615
- }
616
- function createTh(text) {
617
- return [
618
- {
619
- type: "th_open",
620
- tag: "th",
621
- attrs: null,
622
- block: true,
623
- level: 3,
624
- children: null
625
- },
626
- {
627
- type: "inline",
628
- tag: "",
629
- children: [{
630
- tag: "",
631
- type: "text",
632
- block: false,
633
- content: text,
634
- children: null
635
- }],
636
- content: text,
637
- level: 4,
638
- attrs: null,
639
- block: true
640
- },
641
- {
642
- type: "th_close",
643
- tag: "th",
644
- attrs: null,
645
- block: true,
646
- level: 3,
647
- children: null
648
- }
649
- ];
650
- }
651
- function fixTableTokens(tokens) {
652
- const fixedTokens = [...tokens];
653
- if (tokens.length < 3) return fixedTokens;
654
- const i = tokens.length - 2;
655
- const token = tokens[i];
656
- 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));
659
- const insert = [
660
- ...createStart(),
661
- ...body,
662
- ...createEnd()
663
- ];
664
- 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));
667
- const insert = [
668
- ...createStart(),
669
- ...body,
670
- ...createEnd()
671
- ];
672
- fixedTokens.splice(i - 1, 3, ...insert);
673
- } else if (/^\|(?:[^|\n:]+\|)+\n\|:?$/.test(token.content)) {
674
- token.content = token.content.slice(0, -2);
675
- token.children.splice(2, 1);
907
+ for (nextLine = startLine + 1; nextLine < endLine; nextLine++) {
908
+ const lineStart = s.bMarks[nextLine] + s.tShift[nextLine];
909
+ const lineEnd = s.eMarks[nextLine];
910
+ const currentLine = s.src.slice(lineStart - 1, lineEnd);
911
+ if (currentLine.trim() === closeDelim) {
912
+ found = true;
913
+ break;
914
+ } else if (currentLine.includes(closeDelim)) {
915
+ found = true;
916
+ const endIndex = currentLine.indexOf(closeDelim);
917
+ content += (content ? "\n" : "") + currentLine.slice(0, endIndex);
918
+ break;
919
+ }
920
+ content += (content ? "\n" : "") + currentLine;
921
+ }
676
922
  }
677
- }
678
- return fixedTokens;
923
+ const token = s.push("math_block", "math", 0);
924
+ token.content = normalizeStandaloneBackslashT(content);
925
+ token.markup = openDelim === "$$" ? "$$" : openDelim === "[" ? "[]" : "\\[\\]";
926
+ token.raw = `${openDelim}${content}${content.startsWith("\n") ? "\n" : ""}${closeDelim}`;
927
+ token.map = [startLine, nextLine + 1];
928
+ token.block = true;
929
+ token.loading = !found;
930
+ s.line = nextLine + 1;
931
+ return true;
932
+ };
933
+ md.inline.ruler.before("escape", "math", mathInline);
934
+ md.block.ruler.before("paragraph", "math_block", mathBlock, { alt: [
935
+ "paragraph",
936
+ "reference",
937
+ "blockquote",
938
+ "list"
939
+ ] });
940
+ }
941
+
942
+ //#endregion
943
+ //#region src/renderers/index.ts
944
+ function applyRenderRules(md) {
945
+ const defaultImage = md.renderer.rules.image || function(tokens, idx, options, env, self) {
946
+ const tokensAny = tokens;
947
+ const selfShape = self;
948
+ return selfShape.renderToken ? selfShape.renderToken(tokensAny, idx, options) : "";
949
+ };
950
+ md.renderer.rules.image = (tokens, idx, options, env, self) => {
951
+ const tokensAny = tokens;
952
+ tokensAny[idx].attrSet?.("loading", "lazy");
953
+ return defaultImage(tokensAny, idx, options, env, self);
954
+ };
955
+ md.renderer.rules.fence = md.renderer.rules.fence || ((tokens, idx) => {
956
+ const tokenShape = tokens[idx];
957
+ const info = String(tokenShape.info ?? "").trim();
958
+ return `<pre class="${info ? `language-${md.utils.escapeHtml(info.split(/\s+/g)[0])}` : ""}"><code>${md.utils.escapeHtml(String(tokenShape.content ?? ""))}</code></pre>`;
959
+ });
960
+ }
961
+
962
+ //#endregion
963
+ //#region src/factory.ts
964
+ function factory(opts = {}) {
965
+ const md = new MarkdownIt({
966
+ html: true,
967
+ linkify: true,
968
+ typographer: true,
969
+ ...opts.markdownItOptions ?? {}
970
+ });
971
+ if (opts.enableMath ?? true) applyMath(md, {
972
+ ...getDefaultMathOptions() ?? {},
973
+ ...opts.mathOptions ?? {}
974
+ });
975
+ if (opts.enableContainers ?? true) applyContainers(md);
976
+ applyFixLinkInline(md);
977
+ applyFixLinkTokens(md);
978
+ applyFixStrongTokens(md);
979
+ applyFixListItem(md);
980
+ applyFixTableTokens(md);
981
+ applyRenderRules(md);
982
+ return md;
679
983
  }
680
984
 
681
985
  //#endregion
682
986
  //#region src/parser/inline-parsers/checkbox-parser.ts
683
987
  function parseCheckboxToken(token) {
988
+ const tokenMeta = token.meta ?? {};
684
989
  return {
685
990
  type: "checkbox",
686
- checked: token.meta?.checked === true,
687
- raw: token.meta?.checked ? "[x]" : "[ ]"
991
+ checked: tokenMeta.checked === true,
992
+ raw: tokenMeta.checked ? "[x]" : "[ ]"
688
993
  };
689
994
  }
690
995
  function parseCheckboxInputToken(token) {
996
+ const tokenAny = token;
997
+ const rawAttr = tokenAny.attrGet ? tokenAny.attrGet("checked") : void 0;
998
+ const checked = rawAttr === "" || rawAttr === "true";
691
999
  return {
692
1000
  type: "checkbox_input",
693
- checked: token.attrGet("checked") === "" || token.attrGet("checked") === "true",
694
- raw: token.attrGet("checked") === "" || token.attrGet("checked") === "true" ? "[x]" : "[ ]"
1001
+ checked,
1002
+ raw: checked ? "[x]" : "[ ]"
695
1003
  };
696
1004
  }
697
1005
 
698
1006
  //#endregion
699
1007
  //#region src/parser/inline-parsers/emoji-parser.ts
700
1008
  function parseEmojiToken(token) {
1009
+ const name = String(token.content ?? "");
701
1010
  return {
702
1011
  type: "emoji",
703
- name: token.content || "",
704
- markup: token.markup || "",
705
- raw: `:${token.content || ""}:`
1012
+ name,
1013
+ markup: String(token.markup ?? ""),
1014
+ raw: `:${name}:`
706
1015
  };
707
1016
  }
708
1017
 
@@ -714,7 +1023,7 @@ function parseEmphasisToken(tokens, startIndex) {
714
1023
  let i = startIndex + 1;
715
1024
  const innerTokens = [];
716
1025
  while (i < tokens.length && tokens[i].type !== "em_close") {
717
- emText += tokens[i].content || "";
1026
+ emText += String(tokens[i].content ?? "");
718
1027
  innerTokens.push(tokens[i]);
719
1028
  i++;
720
1029
  }
@@ -730,244 +1039,66 @@ function parseEmphasisToken(tokens, startIndex) {
730
1039
  }
731
1040
 
732
1041
  //#endregion
733
- //#region src/parser/inline-parsers/fence-parser.ts
734
- function splitUnifiedDiff(content) {
735
- const orig = [];
736
- const updated = [];
737
- for (const rawLine of content.split(/\r?\n/)) {
738
- const line = rawLine;
739
- if (/^(?:diff |index |--- |\+\+\+ |@@ )/.test(line)) continue;
740
- if (line.startsWith("- ")) orig.push(` ${line.slice(1)}`);
741
- else if (line.startsWith("+ ")) updated.push(` ${line.slice(1)}`);
742
- else {
743
- orig.push(line);
744
- updated.push(line);
745
- }
746
- }
747
- return {
748
- original: orig.join("\n"),
749
- updated: updated.join("\n")
750
- };
751
- }
752
- function parseFenceToken(token) {
753
- 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 || "";
759
- const trailingFenceLine = /\r?\n[ \t]*`+\s*$/;
760
- if (trailingFenceLine.test(content)) content = content.replace(trailingFenceLine, "");
761
- if (diff) {
762
- const { original, updated } = splitUnifiedDiff(content);
763
- return {
764
- type: "code_block",
765
- language,
766
- code: updated || "",
767
- raw: content,
768
- diff,
769
- loading: closed === true ? false : closed === false ? true : !hasMap,
770
- originalCode: original,
771
- updatedCode: updated
772
- };
773
- }
774
- return {
775
- type: "code_block",
776
- language,
777
- code: content || "",
778
- raw: content || "",
779
- diff,
780
- loading: closed === true ? false : closed === false ? true : !hasMap
781
- };
782
- }
783
-
784
- //#endregion
785
- //#region src/parser/inline-parsers/fixLinkToken.ts
786
- function isTextToken(t) {
787
- return !!t && t.type === "text" && typeof t.content === "string";
788
- }
789
- function fixLinkToken(tokens) {
790
- tokens = fixLinkToken4(fixLinkToken3(tokens));
791
- if (tokens.length < 5) return tokens;
792
- const first = tokens[tokens.length - 5];
793
- if (first.type !== "text" || !first.content?.endsWith("[")) return fixLinkTokens2(tokens);
794
- if (tokens[tokens.length - 4].tag !== "em") return fixLinkTokens2(tokens);
795
- const last = tokens[tokens.length - 1];
796
- if (last?.type === "text" && !last.content?.startsWith("]")) return fixLinkTokens2(tokens);
797
- const third = tokens[tokens.length - 3];
798
- const lastContent = last.content ?? "";
799
- const href = lastContent.replace(/^\]\(*/, "");
800
- const loading = !lastContent.includes(")");
801
- first.content = first.content?.replace(/\[$/, "");
802
- tokens.splice(tokens.length - 3, 1, {
803
- type: "link",
804
- href,
805
- text: third.content,
806
- children: [{
807
- type: "text",
808
- content: third.content,
809
- raw: third.content
810
- }],
811
- loading
812
- });
813
- tokens.splice(tokens.length - 1, 1);
814
- return tokens;
815
- }
816
- function fixLinkTokens2(tokens) {
817
- if (tokens.length < 8) return tokens;
818
- let length = tokens.length;
819
- let last = tokens[length - 1];
820
- if (last.type !== "link_close") {
821
- length--;
822
- last = tokens[length - 1];
823
- if (last.type !== "link_close") return tokens;
824
- }
825
- if (tokens[length - 7].type !== "em_open") return tokens;
826
- const third = tokens[length - 6];
827
- const first = tokens[length - 8];
828
- if (first.type !== "text") return tokens;
829
- let href = tokens[length - 2].content ?? "";
830
- let count = 4;
831
- if (length !== tokens.length) {
832
- href += last.content || "";
833
- count++;
834
- }
835
- tokens.splice(length - 4, count);
836
- const content = third.content;
837
- length -= 4;
838
- first.content = first.content?.replace(/\[$/, "");
839
- tokens.splice(length - 2, 1, {
840
- type: "link",
841
- href,
842
- text: content,
843
- children: [{
844
- type: "text",
845
- content,
846
- raw: content
847
- }],
848
- loading: true
849
- });
850
- return tokens;
851
- }
852
- function fixLinkToken3(tokens) {
853
- const last = tokens[tokens.length - 1];
854
- const preLast = tokens[tokens.length - 2];
855
- const fixedTokens = [...tokens];
856
- if (last.type !== "text" || !last.content?.startsWith(")")) return tokens;
857
- if (preLast.type !== "link_close") return tokens;
858
- if (isTextToken(tokens[tokens.length - 5]) && tokens[tokens.length - 5].content?.endsWith("(")) {
859
- const content = tokens[tokens.length - 5].content + tokens[tokens.length - 3].content + last.content;
860
- fixedTokens.splice(tokens.length - 5, 5, {
861
- type: "text",
862
- content,
863
- raw: content
864
- });
865
- } else {
866
- const lc = (last.content ?? "").slice(1);
867
- fixedTokens[fixedTokens.length - 1] = {
868
- ...last,
869
- content: lc
870
- };
871
- }
872
- return fixedTokens;
873
- }
874
- function fixLinkToken4(tokens) {
875
- const fixedTokens = [...tokens];
876
- for (let i = tokens.length - 1; i >= 3; i--) if (tokens[i].type === "link_close") {
877
- if (tokens[i - 3]?.content?.endsWith("(")) {
878
- const nextToken = tokens[i + 1];
879
- if (nextToken?.type === "text") {
880
- if (tokens[i - 1].type === "text" && tokens[i - 3].type === "text") {
881
- const content = tokens[i - 3].content + tokens[i - 1].content + nextToken.content;
882
- fixedTokens.splice(i - 3, 5, {
883
- type: "text",
884
- content,
885
- raw: content
886
- });
887
- i -= 3;
888
- }
889
- } else {
890
- if (tokens[i - 1].type === "text" && tokens[i - 3].type === "text") {
891
- const content = tokens[i - 3].content + tokens[i - 1].content;
892
- fixedTokens.splice(i - 3, 4, {
893
- type: "text",
894
- content,
895
- raw: content
896
- });
897
- }
898
- i -= 3;
899
- }
900
- }
901
- }
902
- return fixedTokens;
903
- }
904
-
905
- //#endregion
906
- //#region src/parser/inline-parsers/fixListItem.ts
907
- function fixListItem(tokens) {
908
- const last = tokens[tokens.length - 1];
909
- if (last?.type === "text" && /^\s*\d+\.\s*$/.test(last.content || "") && tokens[tokens.length - 2]?.tag === "br") tokens.splice(tokens.length - 1, 1);
910
- return tokens;
911
- }
912
-
913
- //#endregion
914
- //#region src/parser/inline-parsers/fixStrongTokens.ts
915
- function fixStrongTokens(tokens) {
916
- const fixedTokens = [...tokens];
917
- if (tokens.length < 4) return fixedTokens;
918
- const i = tokens.length - 4;
919
- const token = tokens[i];
920
- const nextToken = tokens[i + 1];
921
- if (token.type === "text" && token.content?.endsWith("*") && nextToken.type === "em_open") {
922
- const _nextToken = tokens[i + 2];
923
- const count = _nextToken?.type === "text" ? 4 : 3;
924
- const insert = [
925
- {
926
- type: "strong_open",
927
- tag: "strong",
928
- attrs: null,
929
- map: null,
930
- children: null,
931
- content: "",
932
- markup: "**",
933
- info: "",
934
- meta: null
935
- },
936
- {
937
- type: "text",
938
- content: _nextToken?.type === "text" ? _nextToken.content : ""
939
- },
940
- {
941
- type: "strong_close",
942
- tag: "strong",
943
- attrs: null,
944
- map: null,
945
- children: null,
946
- content: "",
947
- markup: "**",
948
- info: "",
949
- meta: null
950
- }
951
- ];
952
- const beforeText = token.content?.slice(0, -1);
953
- if (beforeText) insert.unshift({
954
- type: "text",
955
- content: beforeText,
956
- raw: beforeText
957
- });
958
- fixedTokens.splice(i, count, ...insert);
959
- return fixedTokens;
1042
+ //#region src/parser/inline-parsers/fence-parser.ts
1043
+ function splitUnifiedDiff(content) {
1044
+ const orig = [];
1045
+ const updated = [];
1046
+ for (const rawLine of content.split(/\r?\n/)) {
1047
+ const line = rawLine;
1048
+ if (/^(?:diff |index |--- |\+\+\+ |@@ )/.test(line)) continue;
1049
+ if (line.startsWith("- ")) orig.push(` ${line.slice(1)}`);
1050
+ else if (line.startsWith("+ ")) updated.push(` ${line.slice(1)}`);
1051
+ else {
1052
+ orig.push(line);
1053
+ updated.push(line);
1054
+ }
960
1055
  }
961
- return fixedTokens;
1056
+ return {
1057
+ original: orig.join("\n"),
1058
+ updated: updated.join("\n")
1059
+ };
1060
+ }
1061
+ function parseFenceToken(token) {
1062
+ const hasMap = Array.isArray(token.map) && token.map.length === 2;
1063
+ const tokenMeta = token.meta ?? {};
1064
+ const closed = typeof tokenMeta.closed === "boolean" ? tokenMeta.closed : void 0;
1065
+ const info = String(token.info ?? "");
1066
+ const diff = info.startsWith("diff");
1067
+ const language = diff ? String(info.split(" ")[1] ?? "") : info;
1068
+ let content = String(token.content ?? "");
1069
+ const trailingFenceLine = /\r?\n[ \t]*`+\s*$/;
1070
+ if (trailingFenceLine.test(content)) content = content.replace(trailingFenceLine, "");
1071
+ if (diff) {
1072
+ const { original, updated } = splitUnifiedDiff(content);
1073
+ return {
1074
+ type: "code_block",
1075
+ language,
1076
+ code: String(updated ?? ""),
1077
+ raw: String(content ?? ""),
1078
+ diff,
1079
+ loading: closed === true ? false : closed === false ? true : !hasMap,
1080
+ originalCode: original,
1081
+ updatedCode: updated
1082
+ };
1083
+ }
1084
+ return {
1085
+ type: "code_block",
1086
+ language,
1087
+ code: String(content ?? ""),
1088
+ raw: String(content ?? ""),
1089
+ diff,
1090
+ loading: closed === true ? false : closed === false ? true : !hasMap
1091
+ };
962
1092
  }
963
1093
 
964
1094
  //#endregion
965
1095
  //#region src/parser/inline-parsers/footnote-ref-parser.ts
966
1096
  function parseFootnoteRefToken(token) {
1097
+ const tokenMeta = token.meta ?? {};
967
1098
  return {
968
1099
  type: "footnote_reference",
969
- id: token.meta?.label || "",
970
- raw: `[^${token.meta?.label || ""}]`
1100
+ id: String(tokenMeta.label ?? ""),
1101
+ raw: `[^${String(tokenMeta.label ?? "")}]`
971
1102
  };
972
1103
  }
973
1104
 
@@ -988,7 +1119,7 @@ function parseHighlightToken(tokens, startIndex) {
988
1119
  let i = startIndex + 1;
989
1120
  const innerTokens = [];
990
1121
  while (i < tokens.length && tokens[i].type !== "mark_close") {
991
- markText += tokens[i].content || "";
1122
+ markText += String(tokens[i].content ?? "");
992
1123
  innerTokens.push(tokens[i]);
993
1124
  i++;
994
1125
  }
@@ -1006,12 +1137,33 @@ function parseHighlightToken(tokens, startIndex) {
1006
1137
  //#endregion
1007
1138
  //#region src/parser/inline-parsers/image-parser.ts
1008
1139
  function parseImageToken(token, loading = false) {
1140
+ let attrs = token.attrs ?? [];
1141
+ let childWithAttrs = null;
1142
+ if ((!attrs || attrs.length === 0) && Array.isArray(token.children)) for (const child of token.children) {
1143
+ const childAttrs = child?.attrs;
1144
+ if (Array.isArray(childAttrs) && childAttrs.length > 0) {
1145
+ attrs = childAttrs;
1146
+ childWithAttrs = child;
1147
+ break;
1148
+ }
1149
+ }
1150
+ const src = String(attrs.find((attr) => attr[0] === "src")?.[1] ?? "");
1151
+ const altAttr = attrs.find((attr) => attr[0] === "alt")?.[1];
1152
+ let alt = "";
1153
+ if (altAttr != null && String(altAttr).length > 0) alt = String(altAttr);
1154
+ else if (childWithAttrs?.content != null && String(childWithAttrs.content).length > 0) alt = String(childWithAttrs.content);
1155
+ else if (Array.isArray(childWithAttrs?.children) && childWithAttrs.children[0]?.content) alt = String(childWithAttrs.children[0].content);
1156
+ else if (Array.isArray(token.children) && token.children[0]?.content) alt = String(token.children[0].content);
1157
+ else if (token.content != null && String(token.content).length > 0) alt = String(token.content);
1158
+ const _title = attrs.find((attr) => attr[0] === "title")?.[1] ?? null;
1159
+ const title = _title === null ? null : String(_title);
1160
+ const raw = String(token.content ?? "");
1009
1161
  return {
1010
1162
  type: "image",
1011
- src: token.attrs?.find((attr) => attr[0] === "src")?.[1] || "",
1012
- alt: token.attrs?.find((attr) => attr[0] === "alt")?.[1] || "",
1013
- title: token.attrs?.find((attr) => attr[0] === "title")?.[1] || null,
1014
- raw: token.content || "",
1163
+ src,
1164
+ alt,
1165
+ title,
1166
+ raw,
1015
1167
  loading
1016
1168
  };
1017
1169
  }
@@ -1019,10 +1171,11 @@ function parseImageToken(token, loading = false) {
1019
1171
  //#endregion
1020
1172
  //#region src/parser/inline-parsers/inline-code-parser.ts
1021
1173
  function parseInlineCodeToken(token) {
1174
+ const code = String(token.content ?? "");
1022
1175
  return {
1023
1176
  type: "inline_code",
1024
- code: token.content || "",
1025
- raw: token.content || ""
1177
+ code,
1178
+ raw: code
1026
1179
  };
1027
1180
  }
1028
1181
 
@@ -1034,7 +1187,7 @@ function parseInsertToken(tokens, startIndex) {
1034
1187
  let i = startIndex + 1;
1035
1188
  const innerTokens = [];
1036
1189
  while (i < tokens.length && tokens[i].type !== "ins_close") {
1037
- insText += tokens[i].content || "";
1190
+ insText += String(tokens[i].content ?? "");
1038
1191
  innerTokens.push(tokens[i]);
1039
1192
  i++;
1040
1193
  }
@@ -1043,7 +1196,7 @@ function parseInsertToken(tokens, startIndex) {
1043
1196
  node: {
1044
1197
  type: "insert",
1045
1198
  children,
1046
- raw: `++${insText}++`
1199
+ raw: `++${String(insText)}++`
1047
1200
  },
1048
1201
  nextIndex: i < tokens.length ? i + 1 : tokens.length
1049
1202
  };
@@ -1052,9 +1205,10 @@ function parseInsertToken(tokens, startIndex) {
1052
1205
  //#endregion
1053
1206
  //#region src/parser/inline-parsers/link-parser.ts
1054
1207
  function parseLinkToken(tokens, startIndex) {
1055
- const openToken = tokens[startIndex];
1056
- const href = openToken.attrs?.find((attr) => attr[0] === "href")?.[1] || "";
1057
- const title = openToken.attrs?.find((attr) => attr[0] === "title")?.[1] || null;
1208
+ const attrs = tokens[startIndex].attrs ?? [];
1209
+ const href = String(attrs.find((attr) => attr[0] === "href")?.[1] ?? "");
1210
+ const _title = attrs.find((attr) => attr[0] === "title")?.[1] ?? null;
1211
+ const title = _title === null ? null : String(_title);
1058
1212
  let i = startIndex + 1;
1059
1213
  const linkTokens = [];
1060
1214
  const loading = true;
@@ -1064,8 +1218,9 @@ function parseLinkToken(tokens, startIndex) {
1064
1218
  }
1065
1219
  const children = parseInlineTokens(linkTokens);
1066
1220
  const linkText = children.map((node) => {
1067
- if ("content" in node) return node.content;
1068
- return node.raw;
1221
+ const nodeAny = node;
1222
+ if ("content" in node) return String(nodeAny.content ?? "");
1223
+ return String(nodeAny.raw ?? "");
1069
1224
  }).join("");
1070
1225
  return {
1071
1226
  node: {
@@ -1074,7 +1229,7 @@ function parseLinkToken(tokens, startIndex) {
1074
1229
  title,
1075
1230
  text: linkText,
1076
1231
  children,
1077
- raw: `[${linkText}](${href}${title ? ` "${title}"` : ""})`,
1232
+ raw: String(`[${linkText}](${href}${title ? ` "${title}"` : ""})`),
1078
1233
  loading
1079
1234
  },
1080
1235
  nextIndex: i < tokens.length ? i + 1 : tokens.length
@@ -1086,7 +1241,7 @@ function parseLinkToken(tokens, startIndex) {
1086
1241
  function parseMathInlineToken(token) {
1087
1242
  return {
1088
1243
  type: "math_inline",
1089
- content: token.content || "",
1244
+ content: String(token.content ?? ""),
1090
1245
  loading: !!token.loading,
1091
1246
  raw: token.raw
1092
1247
  };
@@ -1097,8 +1252,8 @@ function parseMathInlineToken(token) {
1097
1252
  function parseReferenceToken(token) {
1098
1253
  return {
1099
1254
  type: "reference",
1100
- id: token.content || "",
1101
- raw: token.markup || `[${token.content}]`
1255
+ id: String(token.content ?? ""),
1256
+ raw: String(token.markup ?? `[${token.content ?? ""}]`)
1102
1257
  };
1103
1258
  }
1104
1259
 
@@ -1110,7 +1265,7 @@ function parseStrikethroughToken(tokens, startIndex) {
1110
1265
  let i = startIndex + 1;
1111
1266
  const innerTokens = [];
1112
1267
  while (i < tokens.length && tokens[i].type !== "s_close") {
1113
- sText += tokens[i].content || "";
1268
+ sText += String(tokens[i].content ?? "");
1114
1269
  innerTokens.push(tokens[i]);
1115
1270
  i++;
1116
1271
  }
@@ -1133,7 +1288,7 @@ function parseStrongToken(tokens, startIndex, raw) {
1133
1288
  let i = startIndex + 1;
1134
1289
  const innerTokens = [];
1135
1290
  while (i < tokens.length && tokens[i].type !== "strong_close") {
1136
- strongText += tokens[i].content || "";
1291
+ strongText += String(tokens[i].content ?? "");
1137
1292
  innerTokens.push(tokens[i]);
1138
1293
  i++;
1139
1294
  }
@@ -1142,7 +1297,7 @@ function parseStrongToken(tokens, startIndex, raw) {
1142
1297
  node: {
1143
1298
  type: "strong",
1144
1299
  children,
1145
- raw: `**${strongText}**`
1300
+ raw: `**${String(strongText)}**`
1146
1301
  },
1147
1302
  nextIndex: i < tokens.length ? i + 1 : tokens.length
1148
1303
  };
@@ -1156,20 +1311,22 @@ function parseSubscriptToken(tokens, startIndex) {
1156
1311
  let i = startIndex + 1;
1157
1312
  const innerTokens = [];
1158
1313
  while (i < tokens.length && tokens[i].type !== "sub_close") {
1159
- subText += tokens[i].content || "";
1314
+ subText += String(tokens[i].content ?? "");
1160
1315
  innerTokens.push(tokens[i]);
1161
1316
  i++;
1162
1317
  }
1163
1318
  children.push(...parseInlineTokens(innerTokens));
1319
+ const startContent = String(tokens[startIndex].content ?? "");
1320
+ const display = subText || startContent;
1164
1321
  return {
1165
1322
  node: {
1166
1323
  type: "subscript",
1167
1324
  children: children.length > 0 ? children : [{
1168
1325
  type: "text",
1169
- content: subText || tokens[startIndex].content || "",
1170
- raw: subText || tokens[startIndex].content || ""
1326
+ content: display,
1327
+ raw: display
1171
1328
  }],
1172
- raw: `~${subText || tokens[startIndex].content || ""}~`
1329
+ raw: `~${display}~`
1173
1330
  },
1174
1331
  nextIndex: i < tokens.length ? i + 1 : tokens.length
1175
1332
  };
@@ -1183,7 +1340,7 @@ function parseSuperscriptToken(tokens, startIndex) {
1183
1340
  let i = startIndex + 1;
1184
1341
  const innerTokens = [];
1185
1342
  while (i < tokens.length && tokens[i].type !== "sup_close") {
1186
- supText += tokens[i].content || "";
1343
+ supText += String(tokens[i].content ?? "");
1187
1344
  innerTokens.push(tokens[i]);
1188
1345
  i++;
1189
1346
  }
@@ -1193,10 +1350,10 @@ function parseSuperscriptToken(tokens, startIndex) {
1193
1350
  type: "superscript",
1194
1351
  children: children.length > 0 ? children : [{
1195
1352
  type: "text",
1196
- content: supText || tokens[startIndex].content || "",
1197
- raw: supText || tokens[startIndex].content || ""
1353
+ content: supText || String(tokens[startIndex].content ?? ""),
1354
+ raw: supText || String(tokens[startIndex].content ?? "")
1198
1355
  }],
1199
- raw: `^${supText || tokens[startIndex].content || ""}^`
1356
+ raw: `^${supText || String(tokens[startIndex].content ?? "")}^`
1200
1357
  },
1201
1358
  nextIndex: i < tokens.length ? i + 1 : tokens.length
1202
1359
  };
@@ -1205,10 +1362,11 @@ function parseSuperscriptToken(tokens, startIndex) {
1205
1362
  //#endregion
1206
1363
  //#region src/parser/inline-parsers/text-parser.ts
1207
1364
  function parseTextToken(token) {
1365
+ const content = String(token.content ?? "");
1208
1366
  return {
1209
1367
  type: "text",
1210
- content: token.content || "",
1211
- raw: token.content || ""
1368
+ content,
1369
+ raw: content
1212
1370
  };
1213
1371
  }
1214
1372
 
@@ -1219,317 +1377,232 @@ function parseInlineTokens(tokens, raw, pPreToken) {
1219
1377
  const result = [];
1220
1378
  let currentTextNode = null;
1221
1379
  let i = 0;
1222
- tokens = fixStrongTokens(tokens);
1223
- tokens = fixListItem(tokens);
1224
- tokens = fixLinkToken(tokens);
1380
+ function resetCurrentTextNode() {
1381
+ currentTextNode = null;
1382
+ }
1383
+ function handleEmphasisAndStrikethrough(content, token) {
1384
+ if (/[^~]*~{2,}[^~]+/.test(content)) {
1385
+ let idx = content.indexOf("~~");
1386
+ if (idx === -1) idx = 0;
1387
+ const _text = content.slice(0, idx);
1388
+ if (_text) if (currentTextNode) {
1389
+ currentTextNode.content += _text;
1390
+ currentTextNode.raw += _text;
1391
+ } else {
1392
+ currentTextNode = {
1393
+ type: "text",
1394
+ content: String(_text ?? ""),
1395
+ raw: String(token.content ?? "")
1396
+ };
1397
+ result.push(currentTextNode);
1398
+ }
1399
+ const { node } = parseStrikethroughToken([
1400
+ {
1401
+ type: "s_open",
1402
+ tag: "s",
1403
+ content: "",
1404
+ markup: "*",
1405
+ info: "",
1406
+ meta: null
1407
+ },
1408
+ {
1409
+ type: "text",
1410
+ tag: "",
1411
+ content: content.slice(idx).replace(/~/g, ""),
1412
+ markup: "",
1413
+ info: "",
1414
+ meta: null
1415
+ },
1416
+ {
1417
+ type: "s_close",
1418
+ tag: "s",
1419
+ content: "",
1420
+ markup: "*",
1421
+ info: "",
1422
+ meta: null
1423
+ }
1424
+ ], 0);
1425
+ resetCurrentTextNode();
1426
+ pushNode(node);
1427
+ i++;
1428
+ return true;
1429
+ }
1430
+ if (/\*\*/.test(content)) {
1431
+ const openIdx = content.indexOf("**");
1432
+ const beforeText = openIdx > -1 ? content.slice(0, openIdx) : "";
1433
+ if (beforeText) pushText(beforeText, beforeText);
1434
+ if (openIdx === -1) {
1435
+ i++;
1436
+ return true;
1437
+ }
1438
+ const exec = /\*\*([\s\S]*?)\*\*/.exec(content);
1439
+ let inner = "";
1440
+ let after = "";
1441
+ if (exec && typeof exec.index === "number") {
1442
+ inner = exec[1];
1443
+ after = content.slice(exec.index + exec[0].length);
1444
+ } else {
1445
+ inner = content.slice(openIdx + 2);
1446
+ after = "";
1447
+ }
1448
+ const { node } = parseStrongToken([
1449
+ {
1450
+ type: "strong_open",
1451
+ tag: "strong",
1452
+ content: "",
1453
+ markup: "*",
1454
+ info: "",
1455
+ meta: null
1456
+ },
1457
+ {
1458
+ type: "text",
1459
+ tag: "",
1460
+ content: inner,
1461
+ markup: "",
1462
+ info: "",
1463
+ meta: null
1464
+ },
1465
+ {
1466
+ type: "strong_close",
1467
+ tag: "strong",
1468
+ content: "",
1469
+ markup: "*",
1470
+ info: "",
1471
+ meta: null
1472
+ }
1473
+ ], 0, raw);
1474
+ resetCurrentTextNode();
1475
+ pushNode(node);
1476
+ if (after) {
1477
+ handleToken({
1478
+ type: "text",
1479
+ content: after,
1480
+ raw: after
1481
+ });
1482
+ i--;
1483
+ }
1484
+ i++;
1485
+ return true;
1486
+ }
1487
+ if (/[^*]*\*[^*]+/.test(content)) {
1488
+ let idx = content.indexOf("*");
1489
+ if (idx === -1) idx = 0;
1490
+ const _text = content.slice(0, idx);
1491
+ if (_text) if (currentTextNode) {
1492
+ currentTextNode.content += _text;
1493
+ currentTextNode.raw += _text;
1494
+ } else {
1495
+ currentTextNode = {
1496
+ type: "text",
1497
+ content: String(_text ?? ""),
1498
+ raw: String(token.content ?? "")
1499
+ };
1500
+ result.push(currentTextNode);
1501
+ }
1502
+ const { node } = parseEmphasisToken([
1503
+ {
1504
+ type: "em_open",
1505
+ tag: "em",
1506
+ content: "",
1507
+ markup: "*",
1508
+ info: "",
1509
+ meta: null
1510
+ },
1511
+ {
1512
+ type: "text",
1513
+ tag: "",
1514
+ content: content.slice(idx).replace(/\*/g, ""),
1515
+ markup: "",
1516
+ info: "",
1517
+ meta: null
1518
+ },
1519
+ {
1520
+ type: "em_close",
1521
+ tag: "em",
1522
+ content: "",
1523
+ markup: "*",
1524
+ info: "",
1525
+ meta: null
1526
+ }
1527
+ ], 0);
1528
+ resetCurrentTextNode();
1529
+ pushNode(node);
1530
+ i++;
1531
+ return true;
1532
+ }
1533
+ return false;
1534
+ }
1535
+ function handleInlineCodeContent(content, _token) {
1536
+ if (!/`[^`]*/.test(content)) return false;
1537
+ resetCurrentTextNode();
1538
+ const code_start = content.indexOf("`");
1539
+ const code_end = content.indexOf("`", code_start + 1);
1540
+ const _text = content.slice(0, code_start);
1541
+ const codeContent = code_end === -1 ? content.slice(code_start) : content.slice(code_start, code_end);
1542
+ const after = code_end === -1 ? "" : content.slice(code_end + 1);
1543
+ if (_text) if (!handleEmphasisAndStrikethrough(_text, _token)) pushText(_text, _text);
1544
+ else i--;
1545
+ const code = codeContent.replace(/`/g, "");
1546
+ pushParsed({
1547
+ type: "inline_code",
1548
+ code,
1549
+ raw: String(code ?? "")
1550
+ });
1551
+ if (after) {
1552
+ handleToken({
1553
+ type: "text",
1554
+ content: after,
1555
+ raw: String(after ?? "")
1556
+ });
1557
+ i--;
1558
+ } else if (code_end === -1) {
1559
+ if (tokens[i + 1]) {
1560
+ let fixedAfter = after;
1561
+ for (let j = i + 1; j < tokens.length; j++) fixedAfter += String((tokens[j].content ?? "") + (tokens[j].markup ?? ""));
1562
+ i = tokens.length - 1;
1563
+ handleToken({
1564
+ type: "text",
1565
+ content: fixedAfter,
1566
+ raw: String(fixedAfter ?? "")
1567
+ });
1568
+ }
1569
+ }
1570
+ i++;
1571
+ return true;
1572
+ }
1573
+ function pushParsed(node) {
1574
+ resetCurrentTextNode();
1575
+ result.push(node);
1576
+ }
1577
+ function pushToken(token) {
1578
+ resetCurrentTextNode();
1579
+ result.push(token);
1580
+ }
1581
+ function pushNode(node) {
1582
+ pushParsed(node);
1583
+ }
1584
+ function pushText(content, raw$1) {
1585
+ if (currentTextNode) {
1586
+ currentTextNode.content += content;
1587
+ currentTextNode.raw += raw$1 ?? content;
1588
+ } else {
1589
+ currentTextNode = {
1590
+ type: "text",
1591
+ content: String(content ?? ""),
1592
+ raw: String(raw$1 ?? content ?? "")
1593
+ };
1594
+ result.push(currentTextNode);
1595
+ }
1596
+ }
1225
1597
  while (i < tokens.length) {
1226
1598
  const token = tokens[i];
1227
1599
  handleToken(token);
1228
1600
  }
1229
1601
  function handleToken(token) {
1230
1602
  switch (token.type) {
1231
- case "text": {
1232
- let index = result.length - 1;
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("![");
1428
- if (imageStart !== -1) {
1429
- const textNodeContent = content.slice(0, imageStart);
1430
- if (!currentTextNode) currentTextNode = {
1431
- type: "text",
1432
- content: textNodeContent,
1433
- raw: textNodeContent
1434
- };
1435
- else currentTextNode.content += textNodeContent;
1436
- result.push(currentTextNode);
1437
- currentTextNode = null;
1438
- result.push(parseImageToken(token, true));
1439
- i++;
1440
- break;
1441
- }
1442
- let linkStart = content.indexOf("[");
1443
- if (content.endsWith("undefined") && !raw?.endsWith("undefined")) content = content.slice(0, -9);
1444
- const textNode = parseTextToken({
1445
- ...token,
1446
- content
1447
- });
1448
- if (linkStart !== -1) {
1449
- let textNodeContent = content.slice(0, linkStart);
1450
- const linkEnd = content.indexOf("](", linkStart);
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++;
1603
+ case "text":
1604
+ handleTextToken(token);
1531
1605
  break;
1532
- }
1533
1606
  case "softbreak":
1534
1607
  if (currentTextNode) {
1535
1608
  currentTextNode.content += "\n";
@@ -1538,193 +1611,368 @@ function parseInlineTokens(tokens, raw, pPreToken) {
1538
1611
  i++;
1539
1612
  break;
1540
1613
  case "code_inline":
1541
- currentTextNode = null;
1542
- result.push(parseInlineCodeToken(token));
1614
+ pushNode(parseInlineCodeToken(token));
1543
1615
  i++;
1544
1616
  break;
1545
- case "link_open": {
1546
- currentTextNode = null;
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);
1617
+ case "link_open":
1618
+ handleLinkOpen(token);
1583
1619
  break;
1584
- }
1585
1620
  case "image":
1586
- currentTextNode = null;
1587
- result.push(parseImageToken(token));
1621
+ resetCurrentTextNode();
1622
+ pushNode(parseImageToken(token));
1588
1623
  i++;
1589
1624
  break;
1590
1625
  case "strong_open": {
1591
- currentTextNode = null;
1626
+ resetCurrentTextNode();
1592
1627
  const { node, nextIndex } = parseStrongToken(tokens, i, token.content);
1593
- result.push(node);
1628
+ pushNode(node);
1594
1629
  i = nextIndex;
1595
1630
  break;
1596
1631
  }
1597
1632
  case "em_open": {
1598
- currentTextNode = null;
1633
+ resetCurrentTextNode();
1599
1634
  const { node, nextIndex } = parseEmphasisToken(tokens, i);
1600
- result.push(node);
1635
+ pushNode(node);
1601
1636
  i = nextIndex;
1602
1637
  break;
1603
1638
  }
1604
1639
  case "s_open": {
1605
- currentTextNode = null;
1640
+ resetCurrentTextNode();
1606
1641
  const { node, nextIndex } = parseStrikethroughToken(tokens, i);
1607
- result.push(node);
1642
+ pushNode(node);
1608
1643
  i = nextIndex;
1609
1644
  break;
1610
1645
  }
1611
1646
  case "mark_open": {
1612
- currentTextNode = null;
1647
+ resetCurrentTextNode();
1613
1648
  const { node, nextIndex } = parseHighlightToken(tokens, i);
1614
- result.push(node);
1649
+ pushNode(node);
1615
1650
  i = nextIndex;
1616
1651
  break;
1617
1652
  }
1618
1653
  case "ins_open": {
1619
- currentTextNode = null;
1654
+ resetCurrentTextNode();
1620
1655
  const { node, nextIndex } = parseInsertToken(tokens, i);
1621
- result.push(node);
1656
+ pushNode(node);
1622
1657
  i = nextIndex;
1623
1658
  break;
1624
1659
  }
1625
1660
  case "sub_open": {
1626
- currentTextNode = null;
1661
+ resetCurrentTextNode();
1627
1662
  const { node, nextIndex } = parseSubscriptToken(tokens, i);
1628
- result.push(node);
1663
+ pushNode(node);
1629
1664
  i = nextIndex;
1630
1665
  break;
1631
1666
  }
1632
1667
  case "sup_open": {
1633
- currentTextNode = null;
1668
+ resetCurrentTextNode();
1634
1669
  const { node, nextIndex } = parseSuperscriptToken(tokens, i);
1635
- result.push(node);
1670
+ pushNode(node);
1636
1671
  i = nextIndex;
1637
1672
  break;
1638
1673
  }
1639
1674
  case "sub":
1640
- currentTextNode = null;
1641
- result.push({
1675
+ resetCurrentTextNode();
1676
+ pushNode({
1642
1677
  type: "subscript",
1643
1678
  children: [{
1644
1679
  type: "text",
1645
- content: token.content || "",
1646
- raw: token.content || ""
1680
+ content: String(token.content ?? ""),
1681
+ raw: String(token.content ?? "")
1647
1682
  }],
1648
- raw: `~${token.content || ""}~`
1683
+ raw: `~${String(token.content ?? "")}~`
1649
1684
  });
1650
1685
  i++;
1651
1686
  break;
1652
1687
  case "sup":
1653
- currentTextNode = null;
1654
- result.push({
1688
+ resetCurrentTextNode();
1689
+ pushNode({
1655
1690
  type: "superscript",
1656
1691
  children: [{
1657
1692
  type: "text",
1658
- content: token.content || "",
1659
- raw: token.content || ""
1693
+ content: String(token.content ?? ""),
1694
+ raw: String(token.content ?? "")
1660
1695
  }],
1661
- raw: `^${token.content || ""}^`
1696
+ raw: `^${String(token.content ?? "")}^`
1662
1697
  });
1663
1698
  i++;
1664
1699
  break;
1665
1700
  case "emoji": {
1666
- currentTextNode = null;
1701
+ resetCurrentTextNode();
1667
1702
  const preToken = tokens[i - 1];
1668
- if (preToken?.type === "text" && /\|:-+/.test(preToken.content || "")) result.push({
1669
- type: "text",
1670
- content: "",
1671
- raw: ""
1672
- });
1673
- else result.push(parseEmojiToken(token));
1703
+ if (preToken?.type === "text" && /\|:-+/.test(String(preToken.content ?? ""))) pushText("", "");
1704
+ else pushNode(parseEmojiToken(token));
1674
1705
  i++;
1675
1706
  break;
1676
1707
  }
1677
1708
  case "checkbox":
1678
- currentTextNode = null;
1679
- result.push(parseCheckboxToken(token));
1709
+ resetCurrentTextNode();
1710
+ pushNode(parseCheckboxToken(token));
1680
1711
  i++;
1681
1712
  break;
1682
1713
  case "checkbox_input":
1683
- currentTextNode = null;
1684
- result.push(parseCheckboxInputToken(token));
1714
+ resetCurrentTextNode();
1715
+ pushNode(parseCheckboxInputToken(token));
1685
1716
  i++;
1686
1717
  break;
1687
1718
  case "footnote_ref":
1688
- currentTextNode = null;
1689
- result.push(parseFootnoteRefToken(token));
1719
+ resetCurrentTextNode();
1720
+ pushNode(parseFootnoteRefToken(token));
1690
1721
  i++;
1691
1722
  break;
1692
1723
  case "hardbreak":
1693
- currentTextNode = null;
1694
- result.push(parseHardbreakToken());
1724
+ resetCurrentTextNode();
1725
+ pushNode(parseHardbreakToken());
1695
1726
  i++;
1696
1727
  break;
1697
1728
  case "fence":
1698
- currentTextNode = null;
1699
- result.push(parseFenceToken(tokens[i]));
1729
+ resetCurrentTextNode();
1730
+ pushNode(parseFenceToken(tokens[i]));
1700
1731
  i++;
1701
1732
  break;
1702
1733
  case "math_inline":
1703
- currentTextNode = null;
1704
- result.push(parseMathInlineToken(token));
1734
+ resetCurrentTextNode();
1735
+ pushNode(parseMathInlineToken(token));
1705
1736
  i++;
1706
1737
  break;
1707
- case "reference": {
1708
- currentTextNode = null;
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++;
1738
+ case "reference":
1739
+ handleReference(token);
1719
1740
  break;
1720
- }
1721
1741
  default:
1722
- result.push(token);
1723
- currentTextNode = null;
1742
+ pushToken(token);
1724
1743
  i++;
1725
1744
  break;
1726
1745
  }
1727
1746
  }
1747
+ function handleTextToken(token) {
1748
+ let index = result.length - 1;
1749
+ let content = String(token.content ?? "").replace(/\\/g, "");
1750
+ if (content.startsWith(")") && result[result.length - 1]?.type === "link") content = content.slice(1);
1751
+ if (content.endsWith("undefined") && !raw?.endsWith("undefined")) content = content.slice(0, -9);
1752
+ for (; index >= 0; index--) {
1753
+ const item = result[index];
1754
+ if (item.type === "text") {
1755
+ currentTextNode = null;
1756
+ content = item.content + content;
1757
+ continue;
1758
+ }
1759
+ break;
1760
+ }
1761
+ if (index < result.length - 1) result.splice(index + 1);
1762
+ const nextToken = tokens[i + 1];
1763
+ if (content === "`" || content === "|" || content === "$" || content === "1" || /^\*+$/.test(content) || /^\d$/.test(content)) {
1764
+ i++;
1765
+ return;
1766
+ }
1767
+ if (!nextToken && /[^\]]\s*\(\s*$/.test(content)) content = content.replace(/\(\s*$/, "");
1768
+ if (handleCheckboxLike(content)) return;
1769
+ if (content === "[") {
1770
+ i++;
1771
+ return;
1772
+ }
1773
+ if (handleInlineCodeContent(content, token)) return;
1774
+ if (handleEmphasisAndStrikethrough(content, token)) return;
1775
+ if (handleInlineImageContent(content, token)) return;
1776
+ const textNode = parseTextToken({
1777
+ ...token,
1778
+ content
1779
+ });
1780
+ if (handleInlineLinkContent(content, token)) return;
1781
+ const preToken = tokens[i - 1];
1782
+ if (currentTextNode) {
1783
+ currentTextNode.content += textNode.content.replace(/(\*+|\(|\\)$/, "");
1784
+ currentTextNode.raw += textNode.raw;
1785
+ } else {
1786
+ const maybeMath = preToken?.tag === "br" && tokens[i - 2]?.content === "[";
1787
+ if (!tokens[i + 1]) textNode.content = textNode.content.replace(/(\*+|\(|\\)$/, "");
1788
+ currentTextNode = textNode;
1789
+ currentTextNode.center = maybeMath;
1790
+ result.push(currentTextNode);
1791
+ }
1792
+ i++;
1793
+ }
1794
+ function handleLinkOpen(token) {
1795
+ resetCurrentTextNode();
1796
+ const href = token.attrs?.find(([name]) => name === "href")?.[1];
1797
+ function escapeRegExp(str) {
1798
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1799
+ }
1800
+ if (raw && tokens[i + 1].type === "text") {
1801
+ const text = String(tokens[i + 1]?.content ?? "");
1802
+ const escText = escapeRegExp(text);
1803
+ if (!(/* @__PURE__ */ new RegExp(`\\[${escText}\\s*\\]`)).test(raw)) {
1804
+ pushText(text, text);
1805
+ i += 3;
1806
+ return;
1807
+ }
1808
+ }
1809
+ if (raw && href) {
1810
+ const loadingMath = /* @__PURE__ */ new RegExp(`\\(\\s*${escapeRegExp(href)}\\s*\\)`);
1811
+ const pre = result.length > 0 ? result[result.length - 1] : void 0;
1812
+ const loading = !loadingMath.test(raw);
1813
+ if (loading && pre) {
1814
+ let preText = "";
1815
+ if (pre) {
1816
+ if (pre.type === "link") preText = String(pre.text ?? "");
1817
+ else if (pre.type === "text") preText = String(pre.content ?? "");
1818
+ else if (pre.content && typeof pre.content === "string") preText = String(pre.content ?? "").slice(1, -1);
1819
+ }
1820
+ if ((/* @__PURE__ */ new RegExp(`\\[${escapeRegExp(preText)}\\s*\\]\\(`)).test(raw)) {
1821
+ const text = String(preText ?? "");
1822
+ resetCurrentTextNode();
1823
+ const node$1 = {
1824
+ type: "link",
1825
+ href: "",
1826
+ title: null,
1827
+ text,
1828
+ children: [{
1829
+ type: "text",
1830
+ content: text,
1831
+ raw: text
1832
+ }],
1833
+ loading
1834
+ };
1835
+ result.splice(result.length - 1, 1, node$1);
1836
+ i += 3;
1837
+ if (String(tokens[i]?.content ?? "") === ".") i++;
1838
+ return;
1839
+ }
1840
+ }
1841
+ }
1842
+ const { node, nextIndex } = parseLinkToken(tokens, i);
1843
+ i = nextIndex;
1844
+ const hrefAttr = token.attrs?.find(([name]) => name === "href")?.[1];
1845
+ const hrefStr = String(hrefAttr ?? "");
1846
+ if (raw && hrefStr) {
1847
+ const openIdx = raw.indexOf("](");
1848
+ if (openIdx === -1) {} else {
1849
+ const closeIdx = raw.indexOf(")", openIdx + 2);
1850
+ if (closeIdx === -1) node.loading = true;
1851
+ else if (raw.slice(openIdx + 2, closeIdx).includes(hrefStr)) node.loading = false;
1852
+ else node.loading = true;
1853
+ }
1854
+ }
1855
+ pushParsed(node);
1856
+ }
1857
+ function handleReference(token) {
1858
+ resetCurrentTextNode();
1859
+ const nextToken = tokens[i + 1];
1860
+ const preToken = tokens[i - 1];
1861
+ const preResult = result[result.length - 1];
1862
+ const nextIsTextNotStartingParens = nextToken?.type === "text" && !String(nextToken.content ?? "").startsWith("(");
1863
+ const preIsTextEndingBracketOrOnlySpace = preToken?.type === "text" && /\]$|^\s*$/.test(String(preToken.content ?? ""));
1864
+ if (nextIsTextNotStartingParens || preIsTextEndingBracketOrOnlySpace) pushNode(parseReferenceToken(token));
1865
+ else if (nextToken && nextToken.type === "text") nextToken.content = String(token.markup ?? "") + String(nextToken.content ?? "");
1866
+ else if (preResult && preResult.type === "text") {
1867
+ preResult.content = String(preResult.content ?? "") + String(token.markup ?? "");
1868
+ preResult.raw = String(preResult.raw ?? "") + String(token.markup ?? "");
1869
+ }
1870
+ i++;
1871
+ }
1872
+ function handleInlineLinkContent(content, _token) {
1873
+ const linkStart = content.indexOf("[");
1874
+ if (linkStart === -1) return false;
1875
+ let textNodeContent = content.slice(0, linkStart);
1876
+ const linkEnd = content.indexOf("](", linkStart);
1877
+ if (linkEnd !== -1) {
1878
+ const textToken = tokens[i + 2];
1879
+ let text = content.slice(linkStart + 1, linkEnd);
1880
+ if (text.includes("[")) {
1881
+ const secondLinkStart = text.indexOf("[");
1882
+ textNodeContent += content.slice(0, linkStart + secondLinkStart + 1);
1883
+ const newLinkStart = linkStart + secondLinkStart + 1;
1884
+ text = content.slice(newLinkStart + 1, linkEnd);
1885
+ }
1886
+ const nextToken = tokens[i + 1];
1887
+ if (content.endsWith("](") && nextToken?.type === "link_open" && textToken) {
1888
+ const last = tokens[i + 4];
1889
+ let index = 4;
1890
+ let loading$1 = true;
1891
+ if (last?.type === "text" && last.content === ")") {
1892
+ index++;
1893
+ loading$1 = false;
1894
+ } else if (last?.type === "text" && last.content === ".") i++;
1895
+ if (textNodeContent) pushText(textNodeContent, textNodeContent);
1896
+ pushParsed({
1897
+ type: "link",
1898
+ href: String(textToken.content ?? ""),
1899
+ title: null,
1900
+ text,
1901
+ children: [{
1902
+ type: "text",
1903
+ content: text,
1904
+ raw: text
1905
+ }],
1906
+ loading: loading$1
1907
+ });
1908
+ i += index;
1909
+ return true;
1910
+ }
1911
+ const linkContentEnd = content.indexOf(")", linkEnd);
1912
+ const href = linkContentEnd !== -1 ? content.slice(linkEnd + 2, linkContentEnd) : "";
1913
+ const loading = linkContentEnd === -1;
1914
+ if (textNodeContent) pushText(textNodeContent, textNodeContent);
1915
+ pushParsed({
1916
+ type: "link",
1917
+ href,
1918
+ title: null,
1919
+ text,
1920
+ children: [{
1921
+ type: "text",
1922
+ content: text,
1923
+ raw: text
1924
+ }],
1925
+ loading
1926
+ });
1927
+ const afterText = linkContentEnd !== -1 ? content.slice(linkContentEnd + 1) : "";
1928
+ if (afterText) {
1929
+ handleToken({
1930
+ type: "text",
1931
+ content: afterText,
1932
+ raw: afterText
1933
+ });
1934
+ i--;
1935
+ }
1936
+ i++;
1937
+ return true;
1938
+ }
1939
+ return false;
1940
+ }
1941
+ function handleInlineImageContent(content, token) {
1942
+ const imageStart = content.indexOf("![");
1943
+ if (imageStart === -1) return false;
1944
+ const textNodeContent = content.slice(0, imageStart);
1945
+ if (!currentTextNode) currentTextNode = {
1946
+ type: "text",
1947
+ content: textNodeContent,
1948
+ raw: textNodeContent
1949
+ };
1950
+ else currentTextNode.content += textNodeContent;
1951
+ result.push(currentTextNode);
1952
+ currentTextNode = null;
1953
+ pushParsed(parseImageToken(token, true));
1954
+ i++;
1955
+ return true;
1956
+ }
1957
+ function handleCheckboxLike(content) {
1958
+ if (!(content?.startsWith("[") && pPreToken?.type === "list_item_open")) return false;
1959
+ const w = content.slice(1).match(/[^\s\]]/);
1960
+ if (w === null) {
1961
+ i++;
1962
+ return true;
1963
+ }
1964
+ if (w && /x/i.test(w[0])) {
1965
+ const checked = w[0] === "x" || w[0] === "X";
1966
+ pushParsed({
1967
+ type: "checkbox_input",
1968
+ checked,
1969
+ raw: checked ? "[x]" : "[ ]"
1970
+ });
1971
+ i++;
1972
+ return true;
1973
+ }
1974
+ return false;
1975
+ }
1728
1976
  return result;
1729
1977
  }
1730
1978
 
@@ -1738,7 +1986,7 @@ function parseBlockquote(tokens, index) {
1738
1986
  blockquoteChildren.push({
1739
1987
  type: "paragraph",
1740
1988
  children: parseInlineTokens(contentToken.children || []),
1741
- raw: contentToken.content || ""
1989
+ raw: String(contentToken.content ?? "")
1742
1990
  });
1743
1991
  j += 3;
1744
1992
  } else if (tokens[j].type === "bullet_list_open" || tokens[j].type === "ordered_list_open") {
@@ -1757,14 +2005,15 @@ function parseBlockquote(tokens, index) {
1757
2005
  //#region src/parser/node-parsers/code-block-parser.ts
1758
2006
  function parseCodeBlock(token) {
1759
2007
  if (token.info?.startsWith("diff")) return parseFenceToken(token);
1760
- const match = token.content.match(/ type="application\/vnd\.ant\.([^"]+)"/);
1761
- if (match?.[1]) token.content = token.content.replace(/<antArtifact[^>]*>/g, "").replace(/<\/antArtifact>/g, "");
2008
+ const contentStr = String(token.content ?? "");
2009
+ const match = contentStr.match(/ type="application\/vnd\.ant\.([^"]+)"/);
2010
+ if (match?.[1]) token.content = contentStr.replace(/<antArtifact[^>]*>/g, "").replace(/<\/antArtifact>/g, "");
1762
2011
  const hasMap = Array.isArray(token.map) && token.map.length === 2;
1763
2012
  return {
1764
2013
  type: "code_block",
1765
- language: match ? match[1] : token.info || "",
1766
- code: token.content || "",
1767
- raw: token.content || "",
2014
+ language: match ? match[1] : String(token.info ?? ""),
2015
+ code: String(token.content ?? ""),
2016
+ raw: String(token.content ?? ""),
1768
2017
  loading: !hasMap
1769
2018
  };
1770
2019
  }
@@ -1787,8 +2036,8 @@ function parseDefinitionList(tokens, index) {
1787
2036
  const contentToken = tokens[k + 1];
1788
2037
  definitionNodes.push({
1789
2038
  type: "paragraph",
1790
- children: parseInlineTokens(contentToken.children || [], contentToken.content || ""),
1791
- raw: contentToken.content || ""
2039
+ children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? "")),
2040
+ raw: String(contentToken.content ?? "")
1792
2041
  });
1793
2042
  k += 3;
1794
2043
  } else k++;
@@ -1813,7 +2062,8 @@ function parseDefinitionList(tokens, index) {
1813
2062
  //#endregion
1814
2063
  //#region src/parser/node-parsers/footnote-parser.ts
1815
2064
  function parseFootnote(tokens, index) {
1816
- const id = tokens[index].meta?.label ?? 0;
2065
+ const meta = tokens[index].meta ?? {};
2066
+ const id = String(meta?.label ?? "0");
1817
2067
  const footnoteChildren = [];
1818
2068
  let j = index + 1;
1819
2069
  while (j < tokens.length && tokens[j].type !== "footnote_close") if (tokens[j].type === "paragraph_open") {
@@ -1821,7 +2071,7 @@ function parseFootnote(tokens, index) {
1821
2071
  footnoteChildren.push({
1822
2072
  type: "paragraph",
1823
2073
  children: parseInlineTokens(contentToken.children || []),
1824
- raw: contentToken.content || ""
2074
+ raw: String(contentToken.content ?? "")
1825
2075
  });
1826
2076
  j += 3;
1827
2077
  } else j++;
@@ -1837,9 +2087,10 @@ function parseFootnote(tokens, index) {
1837
2087
  //#region src/parser/node-parsers/heading-parser.ts
1838
2088
  function parseHeading(tokens, index) {
1839
2089
  const token = tokens[index];
1840
- const headingLevel = Number.parseInt(token.tag?.substring(1) || "1");
2090
+ const levelStr = String(token.tag?.substring(1) ?? "1");
2091
+ const headingLevel = Number.parseInt(levelStr, 10);
1841
2092
  const headingContentToken = tokens[index + 1];
1842
- const headingContent = headingContentToken.content || "";
2093
+ const headingContent = String(headingContentToken.content ?? "");
1843
2094
  return {
1844
2095
  type: "heading",
1845
2096
  level: headingLevel,
@@ -1854,9 +2105,9 @@ function parseHeading(tokens, index) {
1854
2105
  function parseMathBlock(token) {
1855
2106
  return {
1856
2107
  type: "math_block",
1857
- content: token.content || "",
2108
+ content: String(token.content ?? ""),
1858
2109
  loading: !!token.loading,
1859
- raw: token.raw || ""
2110
+ raw: String(token.raw ?? "")
1860
2111
  };
1861
2112
  }
1862
2113
 
@@ -1880,7 +2131,7 @@ function parseTable(tokens, index) {
1880
2131
  while (k < tokens.length && tokens[k].type !== "tr_close") if (tokens[k].type === "th_open" || tokens[k].type === "td_open") {
1881
2132
  const isHeaderCell = tokens[k].type === "th_open";
1882
2133
  const contentToken = tokens[k + 1];
1883
- const content = contentToken.content || "";
2134
+ const content = String(contentToken.content ?? "");
1884
2135
  cells.push({
1885
2136
  type: "table_cell",
1886
2137
  header: isHeaderCell || isHeader,
@@ -1907,7 +2158,7 @@ function parseTable(tokens, index) {
1907
2158
  type: "table",
1908
2159
  header: headerRow,
1909
2160
  rows,
1910
- loading: tokens[index].loading || false,
2161
+ loading: tokens[index].loading ?? false,
1911
2162
  raw: [headerRow, ...rows].map((row) => row.raw).join("\n")
1912
2163
  }, j + 1];
1913
2164
  }
@@ -1933,14 +2184,15 @@ function parseList(tokens, index) {
1933
2184
  while (k < tokens.length && tokens[k].type !== "list_item_close") if (tokens[k].type === "paragraph_open") {
1934
2185
  const contentToken = tokens[k + 1];
1935
2186
  const preToken = tokens[k - 1];
1936
- if (/\n\d+$/.test(contentToken.content || "")) {
1937
- contentToken.content = contentToken.content?.replace(/\n\d+$/, "");
2187
+ const contentStr = String(contentToken.content ?? "");
2188
+ if (/\n\d+$/.test(contentStr)) {
2189
+ contentToken.content = contentStr.replace(/\n\d+$/, "");
1938
2190
  contentToken.children?.splice(-1, 1);
1939
2191
  }
1940
2192
  itemChildren.push({
1941
2193
  type: "paragraph",
1942
- children: parseInlineTokens(contentToken.children || [], contentToken.content || "", preToken),
1943
- raw: contentToken.content || ""
2194
+ children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? ""), preToken),
2195
+ raw: String(contentToken.content ?? "")
1944
2196
  });
1945
2197
  k += 3;
1946
2198
  } else if (tokens[k].type === "blockquote_open") {
@@ -1984,7 +2236,7 @@ function parseList(tokens, index) {
1984
2236
  itemChildren.push(parseThematicBreak());
1985
2237
  k += 1;
1986
2238
  } else if (tokens[k].type === "container_open") {
1987
- const match = /^::: ?(warning|info|note|tip|danger|caution) ?(.*)$/.exec(tokens[k].info || "");
2239
+ const match = /^::: ?(warning|info|note|tip|danger|caution) ?(.*)$/.exec(String(tokens[k].info ?? ""));
1988
2240
  if (match) {
1989
2241
  const [admonitionNode, newIndex] = parseAdmonition(tokens, k, match);
1990
2242
  itemChildren.push(admonitionNode);
@@ -2004,7 +2256,10 @@ function parseList(tokens, index) {
2004
2256
  start: (() => {
2005
2257
  if (token.attrs && token.attrs.length) {
2006
2258
  const found = token.attrs.find((a) => a[0] === "start");
2007
- if (found) return Number(found[1]) || 1;
2259
+ if (found) {
2260
+ const parsed = Number(found[1]);
2261
+ return Number.isFinite(parsed) && parsed !== 0 ? parsed : 1;
2262
+ }
2008
2263
  }
2009
2264
  })(),
2010
2265
  items: listItems,
@@ -2023,8 +2278,8 @@ function parseNestedList(tokens, index) {
2023
2278
  const preToken = tokens[k - 1];
2024
2279
  itemChildren.push({
2025
2280
  type: "paragraph",
2026
- children: parseInlineTokens(contentToken.children || [], contentToken.content || "", preToken),
2027
- raw: contentToken.content || ""
2281
+ children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? ""), preToken),
2282
+ raw: String(contentToken.content ?? "")
2028
2283
  });
2029
2284
  k += 3;
2030
2285
  } else if (tokens[k].type === "bullet_list_open" || tokens[k].type === "ordered_list_open") {
@@ -2058,7 +2313,10 @@ function parseNestedList(tokens, index) {
2058
2313
  start: (() => {
2059
2314
  if (nestedToken.attrs && nestedToken.attrs.length) {
2060
2315
  const found = nestedToken.attrs.find((a) => a[0] === "start");
2061
- if (found) return Number(found[1]) || 1;
2316
+ if (found) {
2317
+ const parsed = Number(found[1]);
2318
+ return Number.isFinite(parsed) && parsed !== 0 ? parsed : 1;
2319
+ }
2062
2320
  }
2063
2321
  })(),
2064
2322
  items: nestedItems,
@@ -2069,8 +2327,8 @@ function parseNestedList(tokens, index) {
2069
2327
  //#endregion
2070
2328
  //#region src/parser/node-parsers/admonition-parser.ts
2071
2329
  function parseAdmonition(tokens, index, match) {
2072
- const kind = match[1] || "note";
2073
- const title = match[2] || kind.charAt(0).toUpperCase() + kind.slice(1);
2330
+ const kind = String(match[1] ?? "note");
2331
+ const title = String(match[2] ?? kind.charAt(0).toUpperCase() + kind.slice(1));
2074
2332
  const admonitionChildren = [];
2075
2333
  let j = index + 1;
2076
2334
  while (j < tokens.length && tokens[j].type !== "container_close") if (tokens[j].type === "paragraph_open") {
@@ -2078,7 +2336,7 @@ function parseAdmonition(tokens, index, match) {
2078
2336
  if (contentToken) admonitionChildren.push({
2079
2337
  type: "paragraph",
2080
2338
  children: parseInlineTokens(contentToken.children || []),
2081
- raw: contentToken.content || ""
2339
+ raw: String(contentToken.content ?? "")
2082
2340
  });
2083
2341
  j += 3;
2084
2342
  } else if (tokens[j].type === "bullet_list_open" || tokens[j].type === "ordered_list_open") {
@@ -2104,17 +2362,17 @@ function parseContainer(tokens, index) {
2104
2362
  const typeMatch = openToken.type.match(/^container_(\w+)_open$/);
2105
2363
  if (typeMatch) {
2106
2364
  kind = typeMatch[1];
2107
- const info = (openToken.info || "").trim();
2365
+ const info = String(openToken.info ?? "").trim();
2108
2366
  if (info && !info.startsWith(":::")) {
2109
2367
  const maybe = info.replace(/* @__PURE__ */ new RegExp(`^${kind}`), "").trim();
2110
2368
  if (maybe) title = maybe;
2111
2369
  }
2112
2370
  } else {
2113
- const info = (openToken.info || "").trim();
2371
+ const info = String(openToken.info ?? "").trim();
2114
2372
  const match = /^:{1,3}\s*(warning|info|note|tip|danger|caution)\s*(.*)$/i.exec(info);
2115
2373
  if (match) {
2116
2374
  kind = match[1];
2117
- title = match[2] || "";
2375
+ title = String(match[2] ?? "");
2118
2376
  }
2119
2377
  }
2120
2378
  if (!title) title = kind.charAt(0).toUpperCase() + kind.slice(1);
@@ -2124,12 +2382,20 @@ function parseContainer(tokens, index) {
2124
2382
  while (j < tokens.length && tokens[j].type !== "container_close" && !closeType.test(tokens[j].type)) if (tokens[j].type === "paragraph_open") {
2125
2383
  const contentToken = tokens[j + 1];
2126
2384
  if (contentToken) {
2127
- const i = contentToken.children.findLastIndex((t) => t.type === "text" && /:+/.test(t.content));
2128
- const _children = i !== -1 ? contentToken.children?.slice(0, i) : contentToken.children;
2385
+ const childrenArr = contentToken.children || [];
2386
+ let i = -1;
2387
+ for (let k = childrenArr.length - 1; k >= 0; k--) {
2388
+ const t = childrenArr[k];
2389
+ if (t.type === "text" && /:+/.test(t.content)) {
2390
+ i = k;
2391
+ break;
2392
+ }
2393
+ }
2394
+ const _children = i !== -1 ? childrenArr.slice(0, i) : childrenArr;
2129
2395
  children.push({
2130
2396
  type: "paragraph",
2131
2397
  children: parseInlineTokens(_children || []),
2132
- raw: contentToken.content?.replace(/\n:+$/, "").replace(/\n\s*:::\s*$/, "") || ""
2398
+ raw: String(contentToken.content ?? "").replace(/\n:+$/, "").replace(/\n\s*:::\s*$/, "")
2133
2399
  });
2134
2400
  }
2135
2401
  j += 3;
@@ -2160,7 +2426,7 @@ function parseHardBreak() {
2160
2426
  //#region src/parser/node-parsers/paragraph-parser.ts
2161
2427
  function parseParagraph(tokens, index) {
2162
2428
  const paragraphContentToken = tokens[index + 1];
2163
- const paragraphContent = paragraphContentToken.content || "";
2429
+ const paragraphContent = String(paragraphContentToken.content ?? "");
2164
2430
  return {
2165
2431
  type: "paragraph",
2166
2432
  children: parseInlineTokens(paragraphContentToken.children || [], paragraphContent),
@@ -2182,14 +2448,21 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
2182
2448
  let transformedTokens = tokens;
2183
2449
  if (pre && typeof pre === "function") transformedTokens = pre(tokens) || tokens;
2184
2450
  let result = processTokens(transformedTokens);
2185
- if (post && typeof post === "function") result = post(transformedTokens) || transformedTokens;
2451
+ if (post && typeof post === "function") {
2452
+ const postResult = post(transformedTokens);
2453
+ if (Array.isArray(postResult)) {
2454
+ const first = postResult[0];
2455
+ const firstType = first?.type;
2456
+ if (first && typeof firstType === "string") result = processTokens(postResult);
2457
+ else result = postResult;
2458
+ }
2459
+ }
2186
2460
  return result;
2187
2461
  }
2188
2462
  function processTokens(tokens) {
2189
2463
  if (!tokens || !Array.isArray(tokens)) return [];
2190
2464
  const result = [];
2191
2465
  let i = 0;
2192
- tokens = fixTableTokens(tokens);
2193
2466
  while (i < tokens.length) {
2194
2467
  const token = tokens[i];
2195
2468
  switch (token.type) {
@@ -2258,7 +2531,7 @@ function processTokens(tokens) {
2258
2531
  break;
2259
2532
  }
2260
2533
  case "container_open": {
2261
- const match = /^::: ?(warning|info|note|tip|danger|caution|error) ?(.*)$/.exec(token.info || "");
2534
+ const match = /^::: ?(warning|info|note|tip|danger|caution|error) ?(.*)$/.exec(String(token.info ?? ""));
2262
2535
  if (match) {
2263
2536
  const [admonitionNode, newIndex] = parseAdmonition(tokens, i, match);
2264
2537
  result.push(admonitionNode);
@@ -2293,8 +2566,14 @@ function getMarkdown(msgId = `editor-${Date.now()}`, options = {}) {
2293
2566
  const i18nMap = options.i18n;
2294
2567
  t = (key) => i18nMap[key] ?? defaultTranslations[key] ?? key;
2295
2568
  } else t = (key) => defaultTranslations[key] ?? key;
2296
- if (Array.isArray(options.plugin)) for (const p of options.plugin) if (Array.isArray(p)) md.use(p[0], p[1]);
2297
- else md.use(p);
2569
+ if (Array.isArray(options.plugin)) for (const p of options.plugin) {
2570
+ const pluginItem = p;
2571
+ if (Array.isArray(pluginItem)) {
2572
+ const fn = pluginItem[0];
2573
+ const opts = pluginItem[1];
2574
+ if (typeof fn === "function") md.use(fn, opts);
2575
+ } else if (typeof pluginItem === "function") md.use(pluginItem);
2576
+ }
2298
2577
  if (Array.isArray(options.apply)) for (const fn of options.apply) try {
2299
2578
  fn(md);
2300
2579
  } catch (e) {
@@ -2309,8 +2588,9 @@ function getMarkdown(msgId = `editor-${Date.now()}`, options = {}) {
2309
2588
  md.use(markdownItIns);
2310
2589
  md.use(markdownItFootnote);
2311
2590
  md.core.ruler.after("block", "mark_fence_closed", (state) => {
2312
- const lines = state.src.split(/\r?\n/);
2313
- for (const token of state.tokens) {
2591
+ const s = state;
2592
+ const lines = s.src.split(/\r?\n/);
2593
+ for (const token of s.tokens) {
2314
2594
  if (token.type !== "fence" || !token.map || !token.markup) continue;
2315
2595
  const openLine = token.map[0];
2316
2596
  const endLine = token.map[1];
@@ -2325,33 +2605,35 @@ function getMarkdown(msgId = `editor-${Date.now()}`, options = {}) {
2325
2605
  let j = i + count;
2326
2606
  while (j < line.length && (line[j] === " " || line[j] === " ")) j++;
2327
2607
  const closed = endLine > openLine + 1 && count >= minLen && j === line.length;
2328
- token.meta = token.meta || {};
2329
- token.meta.unclosed = !closed;
2330
- token.meta.closed = !!closed;
2608
+ const tokenShape = token;
2609
+ tokenShape.meta = tokenShape.meta ?? {};
2610
+ tokenShape.meta.unclosed = !closed;
2611
+ tokenShape.meta.closed = !!closed;
2331
2612
  }
2332
2613
  });
2333
2614
  const waveRule = (state, silent) => {
2334
- const start = state.pos;
2335
- if (state.src[start] !== "~") return false;
2336
- const prevChar = state.src[start - 1];
2337
- const nextChar = state.src[start + 1];
2615
+ const s = state;
2616
+ const start = s.pos;
2617
+ if (s.src[start] !== "~") return false;
2618
+ const prevChar = s.src[start - 1];
2619
+ const nextChar = s.src[start + 1];
2338
2620
  if (/\d/.test(prevChar) && /\d/.test(nextChar)) {
2339
2621
  if (!silent) {
2340
- const token = state.push("text", "", 0);
2622
+ const token = s.push("text", "", 0);
2341
2623
  token.content = "~";
2342
2624
  }
2343
- state.pos += 1;
2625
+ s.pos += 1;
2344
2626
  return true;
2345
2627
  }
2346
2628
  return false;
2347
2629
  };
2348
2630
  md.inline.ruler.before("sub", "wave", waveRule);
2349
2631
  md.renderer.rules.fence = (tokens, idx) => {
2350
- const token = tokens[idx];
2351
- const info = token.info ? token.info.trim() : "";
2352
- const str = token.content;
2632
+ const tokenShape = tokens[idx];
2633
+ const info = String(tokenShape.info ?? "").trim();
2634
+ const str = String(tokenShape.content ?? "");
2353
2635
  const encodedCode = btoa(unescape(encodeURIComponent(str)));
2354
- const language = info || "text";
2636
+ const language = String(info ?? "text");
2355
2637
  return `<div class="code-block" data-code="${encodedCode}" data-lang="${language}" id="${`editor-${msgId}-${idx}-${language}`}">
2356
2638
  <div class="code-header">
2357
2639
  <span class="code-lang">${language.toUpperCase()}</span>
@@ -2361,21 +2643,23 @@ function getMarkdown(msgId = `editor-${Date.now()}`, options = {}) {
2361
2643
  </div>`;
2362
2644
  };
2363
2645
  const referenceInline = (state, silent) => {
2364
- if (state.src[state.pos] !== "[") return false;
2365
- const match = /^\[(\d+)\]/.exec(state.src.slice(state.pos));
2646
+ const s = state;
2647
+ if (s.src[s.pos] !== "[") return false;
2648
+ const match = /^\[(\d+)\]/.exec(s.src.slice(s.pos));
2366
2649
  if (!match) return false;
2367
2650
  if (!silent) {
2368
2651
  const id = match[1];
2369
- const token = state.push("reference", "span", 0);
2652
+ const token = s.push("reference", "span", 0);
2370
2653
  token.content = id;
2371
2654
  token.markup = match[0];
2372
2655
  }
2373
- state.pos += match[0].length;
2656
+ s.pos += match[0].length;
2374
2657
  return true;
2375
2658
  };
2376
2659
  md.inline.ruler.before("escape", "reference", referenceInline);
2377
2660
  md.renderer.rules.reference = (tokens, idx) => {
2378
- const id = tokens[idx].content;
2661
+ const tokensAny = tokens;
2662
+ const id = String(tokensAny[idx].content ?? "");
2379
2663
  return `<span class="reference-link" data-reference-id="${id}" role="button" tabindex="0" title="Click to view reference">${id}</span>`;
2380
2664
  };
2381
2665
  return md;