stream-markdown-parser 0.0.8 → 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
@@ -75,6 +75,431 @@ function applyContainers(md) {
75
75
  });
76
76
  }
77
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
+
78
503
  //#endregion
79
504
  //#region src/findMatchingClose.ts
80
505
  function findMatchingClose(src, startIdx, open, close) {
@@ -524,166 +949,37 @@ function applyRenderRules(md) {
524
949
  };
525
950
  md.renderer.rules.image = (tokens, idx, options, env, self) => {
526
951
  const tokensAny = tokens;
527
- tokensAny[idx].attrSet?.("loading", "lazy");
528
- return defaultImage(tokensAny, idx, options, env, self);
529
- };
530
- md.renderer.rules.fence = md.renderer.rules.fence || ((tokens, idx) => {
531
- const tokenShape = tokens[idx];
532
- const info = String(tokenShape.info ?? "").trim();
533
- return `<pre class="${info ? `language-${md.utils.escapeHtml(info.split(/\s+/g)[0])}` : ""}"><code>${md.utils.escapeHtml(String(tokenShape.content ?? ""))}</code></pre>`;
534
- });
535
- }
536
-
537
- //#endregion
538
- //#region src/factory.ts
539
- function factory(opts = {}) {
540
- const md = new MarkdownIt({
541
- html: true,
542
- linkify: true,
543
- typographer: true,
544
- ...opts.markdownItOptions ?? {}
545
- });
546
- if (opts.enableMath ?? true) applyMath(md, {
547
- ...getDefaultMathOptions() ?? {},
548
- ...opts.mathOptions ?? {}
549
- });
550
- if (opts.enableContainers ?? true) applyContainers(md);
551
- applyRenderRules(md);
552
- return md;
553
- }
554
-
555
- //#endregion
556
- //#region src/parser/fixTableTokens.ts
557
- function createStart() {
558
- return [
559
- {
560
- type: "table_open",
561
- tag: "table",
562
- attrs: null,
563
- map: null,
564
- children: null,
565
- content: "",
566
- markup: "",
567
- info: "",
568
- level: 0,
569
- loading: true,
570
- meta: null
571
- },
572
- {
573
- type: "thead_open",
574
- tag: "thead",
575
- attrs: null,
576
- block: true,
577
- level: 1,
578
- children: null
579
- },
580
- {
581
- type: "tr_open",
582
- tag: "tr",
583
- attrs: null,
584
- block: true,
585
- level: 2,
586
- children: null
587
- }
588
- ];
589
- }
590
- function createEnd() {
591
- return [
592
- {
593
- type: "tr_close",
594
- tag: "tr",
595
- attrs: null,
596
- block: true,
597
- level: 2,
598
- children: null
599
- },
600
- {
601
- type: "thead_close",
602
- tag: "thead",
603
- attrs: null,
604
- block: true,
605
- level: 1,
606
- children: null
607
- },
608
- {
609
- type: "table_close",
610
- tag: "table",
611
- attrs: null,
612
- map: null,
613
- children: null,
614
- content: "",
615
- markup: "",
616
- info: "",
617
- level: 0,
618
- meta: null
619
- }
620
- ];
621
- }
622
- function createTh(text) {
623
- return [
624
- {
625
- type: "th_open",
626
- tag: "th",
627
- attrs: null,
628
- block: true,
629
- level: 3,
630
- children: null
631
- },
632
- {
633
- type: "inline",
634
- tag: "",
635
- children: [{
636
- tag: "",
637
- type: "text",
638
- block: false,
639
- content: text,
640
- children: null
641
- }],
642
- content: text,
643
- level: 4,
644
- attrs: null,
645
- block: true
646
- },
647
- {
648
- type: "th_close",
649
- tag: "th",
650
- attrs: null,
651
- block: true,
652
- level: 3,
653
- children: null
654
- }
655
- ];
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
+ });
656
960
  }
657
- function fixTableTokens(tokens) {
658
- const fixedTokens = [...tokens];
659
- if (tokens.length < 3) return fixedTokens;
660
- const i = tokens.length - 2;
661
- const token = tokens[i];
662
- if (token.type === "inline") {
663
- const tcontent = String(token.content ?? "");
664
- const childContent = String(token.children?.[0]?.content ?? "");
665
- if (/^\|(?:[^|\n]+\|?)+/.test(tcontent)) {
666
- const body = childContent.slice(1).split("|").map((i$1) => i$1.trim()).filter(Boolean).flatMap((i$1) => createTh(i$1));
667
- const insert = [
668
- ...createStart(),
669
- ...body,
670
- ...createEnd()
671
- ];
672
- fixedTokens.splice(i - 1, 3, ...insert);
673
- } else if (/^\|(?:[^|\n]+\|)+\n\|:?-/.test(tcontent)) {
674
- const body = childContent.slice(1, -1).split("|").map((i$1) => i$1.trim()).flatMap((i$1) => createTh(i$1));
675
- const insert = [
676
- ...createStart(),
677
- ...body,
678
- ...createEnd()
679
- ];
680
- fixedTokens.splice(i - 1, 3, ...insert);
681
- } else if (/^\|(?:[^|\n:]+\|)+\n\|:?$/.test(tcontent)) {
682
- token.content = tcontent.slice(0, -2);
683
- token.children.splice(2, 1);
684
- }
685
- }
686
- return fixedTokens;
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;
687
983
  }
688
984
 
689
985
  //#endregion
@@ -795,205 +1091,6 @@ function parseFenceToken(token) {
795
1091
  };
796
1092
  }
797
1093
 
798
- //#endregion
799
- //#region src/parser/inline-parsers/fixLinkToken.ts
800
- function isTextToken(t) {
801
- return !!t && t.type === "text" && typeof t.content === "string";
802
- }
803
- function fixLinkToken(tokens) {
804
- const tokensAny = tokens;
805
- tokens = fixLinkToken4(fixLinkToken3(tokens));
806
- if (tokens.length < 5) return tokens;
807
- const first = tokens[tokens.length - 5];
808
- const firstAny = first;
809
- const firstContent = String(firstAny.content ?? "");
810
- if (first.type !== "text" || !firstContent.endsWith("[")) return fixLinkTokens2(tokens);
811
- if (tokens[tokens.length - 4].tag !== "em") return fixLinkTokens2(tokens);
812
- const last = tokens[tokens.length - 1];
813
- const lastAny = last;
814
- const lastContent = String(lastAny.content ?? "");
815
- if (last?.type === "text" && !lastContent.startsWith("]")) return fixLinkTokens2(tokens);
816
- const thirdAny = tokens[tokens.length - 3];
817
- const thirdContent = String(thirdAny.content ?? "");
818
- const href = lastContent.replace(/^\]\(*/, "");
819
- const loading = !lastContent.includes(")");
820
- tokensAny[tokens.length - 5].content = firstContent.replace(/\[$/, "");
821
- tokens.splice(tokens.length - 3, 1, {
822
- type: "link",
823
- href,
824
- text: thirdContent,
825
- children: [{
826
- type: "text",
827
- content: thirdContent,
828
- raw: thirdContent
829
- }],
830
- loading
831
- });
832
- tokens.splice(tokens.length - 1, 1);
833
- return tokens;
834
- }
835
- function fixLinkTokens2(tokens) {
836
- const tokensAny = tokens;
837
- if (tokens.length < 8) return tokens;
838
- let length = tokens.length;
839
- let last = tokens[length - 1];
840
- if (last.type !== "link_close") {
841
- length--;
842
- last = tokens[length - 1];
843
- if (last.type !== "link_close") return tokens;
844
- }
845
- if (tokens[length - 7].type !== "em_open") return tokens;
846
- const third = tokens[length - 6];
847
- const first = tokens[length - 8];
848
- if (first.type !== "text") return tokens;
849
- let href = String(tokensAny[length - 2]?.content ?? "");
850
- let count = 4;
851
- if (length !== tokens.length) {
852
- href += String(last.content ?? "");
853
- count++;
854
- }
855
- tokens.splice(length - 4, count);
856
- const thirdAny = third;
857
- const content = String(thirdAny.content ?? "");
858
- length -= 4;
859
- const firstAny = first;
860
- tokensAny[length - 8].content = String(firstAny.content ?? "").replace(/\[$/, "");
861
- tokens.splice(length - 2, 1, {
862
- type: "link",
863
- href,
864
- text: content,
865
- children: [{
866
- type: "text",
867
- content,
868
- raw: content
869
- }],
870
- loading: true
871
- });
872
- return tokens;
873
- }
874
- function fixLinkToken3(tokens) {
875
- const tokensAny = tokens;
876
- const last = tokens[tokens.length - 1];
877
- const preLast = tokens[tokens.length - 2];
878
- const fixedTokens = [...tokens];
879
- if (last.type !== "text" || !last.content?.startsWith(")")) return tokens;
880
- if (preLast.type !== "link_close") return tokens;
881
- if (isTextToken(tokens[tokens.length - 5]) && String(tokens[tokens.length - 5].content ?? "").endsWith("(")) {
882
- const a = tokensAny[tokens.length - 5];
883
- const b = tokensAny[tokens.length - 3];
884
- const content = String(a.content ?? "") + String(b.content ?? "") + String(last.content ?? "");
885
- fixedTokens.splice(tokens.length - 5, 5, {
886
- type: "text",
887
- content,
888
- raw: content
889
- });
890
- } else {
891
- const lc = (last.content ?? "").slice(1);
892
- fixedTokens[fixedTokens.length - 1] = {
893
- ...last,
894
- content: lc
895
- };
896
- }
897
- return fixedTokens;
898
- }
899
- function fixLinkToken4(tokens) {
900
- const tokensAny = tokens;
901
- const fixedTokens = [...tokens];
902
- for (let i = tokens.length - 1; i >= 3; i--) if (tokens[i].type === "link_close") {
903
- if (tokens[i - 3]?.content?.endsWith("(")) {
904
- const nextToken = tokens[i + 1];
905
- if (nextToken?.type === "text") {
906
- if (tokens[i - 1].type === "text" && tokens[i - 3].type === "text") {
907
- const nextTokenContent = String(nextToken.content ?? "");
908
- const a = tokensAny[i - 3];
909
- const b = tokensAny[i - 1];
910
- const content = String(a.content ?? "") + String(b.content ?? "") + nextTokenContent;
911
- fixedTokens.splice(i - 3, 5, {
912
- type: "text",
913
- content,
914
- raw: content
915
- });
916
- i -= 3;
917
- }
918
- } else {
919
- if (tokens[i - 1].type === "text" && tokens[i - 3].type === "text") {
920
- const a = tokensAny[i - 3];
921
- const b = tokensAny[i - 1];
922
- const content = String(a.content ?? "") + String(b.content ?? "");
923
- fixedTokens.splice(i - 3, 4, {
924
- type: "text",
925
- content,
926
- raw: content
927
- });
928
- }
929
- i -= 3;
930
- }
931
- }
932
- }
933
- return fixedTokens;
934
- }
935
-
936
- //#endregion
937
- //#region src/parser/inline-parsers/fixListItem.ts
938
- function fixListItem(tokens) {
939
- const last = tokens[tokens.length - 1];
940
- const lastContent = String(last?.content ?? "");
941
- if (last?.type === "text" && /^\s*\d+\.\s*$/.test(lastContent) && tokens[tokens.length - 2]?.tag === "br") tokens.splice(tokens.length - 1, 1);
942
- return tokens;
943
- }
944
-
945
- //#endregion
946
- //#region src/parser/inline-parsers/fixStrongTokens.ts
947
- function fixStrongTokens(tokens) {
948
- const fixedTokens = [...tokens];
949
- if (tokens.length < 4) return fixedTokens;
950
- const i = tokens.length - 4;
951
- const token = tokens[i];
952
- const nextToken = tokens[i + 1];
953
- const tokenContent = String(token.content ?? "");
954
- if (token.type === "text" && tokenContent.endsWith("*") && nextToken.type === "em_open") {
955
- const _nextToken = tokens[i + 2];
956
- const count = _nextToken?.type === "text" ? 4 : 3;
957
- const insert = [
958
- {
959
- type: "strong_open",
960
- tag: "strong",
961
- attrs: null,
962
- map: null,
963
- children: null,
964
- content: "",
965
- markup: "**",
966
- info: "",
967
- meta: null
968
- },
969
- {
970
- type: "text",
971
- content: _nextToken?.type === "text" ? String(_nextToken.content ?? "") : ""
972
- },
973
- {
974
- type: "strong_close",
975
- tag: "strong",
976
- attrs: null,
977
- map: null,
978
- children: null,
979
- content: "",
980
- markup: "**",
981
- info: "",
982
- meta: null
983
- }
984
- ];
985
- const beforeText = tokenContent.slice(0, -1);
986
- if (beforeText) insert.unshift({
987
- type: "text",
988
- content: beforeText,
989
- raw: beforeText
990
- });
991
- fixedTokens.splice(i, count, ...insert);
992
- return fixedTokens;
993
- }
994
- return fixedTokens;
995
- }
996
-
997
1094
  //#endregion
998
1095
  //#region src/parser/inline-parsers/footnote-ref-parser.ts
999
1096
  function parseFootnoteRefToken(token) {
@@ -1280,9 +1377,6 @@ function parseInlineTokens(tokens, raw, pPreToken) {
1280
1377
  const result = [];
1281
1378
  let currentTextNode = null;
1282
1379
  let i = 0;
1283
- tokens = fixStrongTokens(tokens);
1284
- tokens = fixListItem(tokens);
1285
- tokens = fixLinkToken(tokens);
1286
1380
  function resetCurrentTextNode() {
1287
1381
  currentTextNode = null;
1288
1382
  }
@@ -1747,7 +1841,17 @@ function parseInlineTokens(tokens, raw, pPreToken) {
1747
1841
  }
1748
1842
  const { node, nextIndex } = parseLinkToken(tokens, i);
1749
1843
  i = nextIndex;
1750
- node.loading = false;
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
+ }
1751
1855
  pushParsed(node);
1752
1856
  }
1753
1857
  function handleReference(token) {
@@ -2359,7 +2463,6 @@ function processTokens(tokens) {
2359
2463
  if (!tokens || !Array.isArray(tokens)) return [];
2360
2464
  const result = [];
2361
2465
  let i = 0;
2362
- tokens = fixTableTokens(tokens);
2363
2466
  while (i < tokens.length) {
2364
2467
  const token = tokens[i];
2365
2468
  switch (token.type) {