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.d.ts +35 -35
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1271 -987
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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
|
|
40
|
-
const
|
|
41
|
-
const
|
|
39
|
+
const s = state;
|
|
40
|
+
const startPos = s.bMarks[startLine] + s.tShift[startLine];
|
|
41
|
+
const lineMax = s.eMarks[startLine];
|
|
42
|
+
const markerMatch = s.src.slice(startPos, lineMax).match(/^:::\s*(\w+)/);
|
|
42
43
|
if (!markerMatch) return false;
|
|
43
44
|
if (silent) return true;
|
|
44
45
|
const name = markerMatch[1];
|
|
45
46
|
let nextLine = startLine + 1;
|
|
46
47
|
let found = false;
|
|
47
48
|
while (nextLine <= endLine) {
|
|
48
|
-
const sPos =
|
|
49
|
-
const ePos =
|
|
50
|
-
if (
|
|
49
|
+
const sPos = s.bMarks[nextLine] + s.tShift[nextLine];
|
|
50
|
+
const ePos = s.eMarks[nextLine];
|
|
51
|
+
if (s.src.slice(sPos, ePos).trim() === ":::") {
|
|
51
52
|
found = true;
|
|
52
53
|
break;
|
|
53
54
|
}
|
|
54
55
|
nextLine++;
|
|
55
56
|
}
|
|
56
57
|
if (!found) return false;
|
|
57
|
-
|
|
58
|
+
s.push("vmr_container_open", "div", 1).attrSet("class", `vmr-container vmr-container-${name}`);
|
|
58
59
|
const contentLines = [];
|
|
59
60
|
for (let i = startLine + 1; i < nextLine; i++) {
|
|
60
|
-
const sPos =
|
|
61
|
-
const ePos =
|
|
62
|
-
contentLines.push(
|
|
61
|
+
const sPos = s.bMarks[i] + s.tShift[i];
|
|
62
|
+
const ePos = s.eMarks[i];
|
|
63
|
+
contentLines.push(s.src.slice(sPos, ePos));
|
|
63
64
|
}
|
|
64
|
-
|
|
65
|
-
const inlineToken =
|
|
65
|
+
s.push("paragraph_open", "p", 1);
|
|
66
|
+
const inlineToken = s.push("inline", "", 0);
|
|
66
67
|
inlineToken.content = contentLines.join("\n");
|
|
67
68
|
inlineToken.map = [startLine + 1, nextLine];
|
|
68
69
|
inlineToken.children = [];
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
s.md.inline.parse(inlineToken.content, s.md, s.env, inlineToken.children);
|
|
71
|
+
s.push("paragraph_close", "p", -1);
|
|
72
|
+
s.push("vmr_container_close", "div", -1);
|
|
73
|
+
s.line = nextLine + 1;
|
|
73
74
|
return true;
|
|
74
75
|
});
|
|
75
76
|
}
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
296
|
-
searchPos =
|
|
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 =
|
|
727
|
+
const t$1 = s.push("text_special", "", 0);
|
|
301
728
|
t$1.content = text === "\\)" ? ")" : "(";
|
|
302
729
|
t$1.markup = text;
|
|
303
|
-
|
|
304
|
-
searchPos =
|
|
730
|
+
s.pos = s.pos + text.length;
|
|
731
|
+
searchPos = s.pos;
|
|
305
732
|
return;
|
|
306
733
|
}
|
|
307
734
|
if (!text) return;
|
|
308
|
-
const t =
|
|
735
|
+
const t = s.push("text", "", 0);
|
|
309
736
|
t.content = text;
|
|
310
|
-
|
|
311
|
-
searchPos =
|
|
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
|
-
|
|
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 =
|
|
761
|
+
const strongToken = s.push("strong_open", "", 0);
|
|
335
762
|
strongToken.markup = src.slice(0, index + 2);
|
|
336
|
-
const token =
|
|
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
|
-
|
|
769
|
+
s.push("strong_close", "", 0);
|
|
343
770
|
} else {
|
|
344
|
-
const token =
|
|
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
|
-
|
|
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(
|
|
361
|
-
if (!
|
|
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 !==
|
|
370
|
-
if (
|
|
371
|
-
|
|
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 =
|
|
803
|
+
const strongToken = s.push("strong_open", "", 0);
|
|
377
804
|
strongToken.markup = _match[0];
|
|
378
|
-
const textToken =
|
|
805
|
+
const textToken = s.push("text", "", 0);
|
|
379
806
|
textToken.content = after;
|
|
380
|
-
|
|
807
|
+
s.push("strong_close", "", 0);
|
|
381
808
|
} else pushText(toPushBefore);
|
|
382
809
|
}
|
|
383
810
|
if (isStrongPrefix) {
|
|
384
|
-
const strongToken =
|
|
811
|
+
const strongToken = s.push("strong_open", "", 0);
|
|
385
812
|
strongToken.markup = "**";
|
|
386
|
-
const token =
|
|
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)
|
|
820
|
+
if (isBeforeClose) s.push("strong_close", "", 0);
|
|
394
821
|
if (raw) {
|
|
395
|
-
const textContentToken =
|
|
822
|
+
const textContentToken = s.push("text", "", 0);
|
|
396
823
|
textContentToken.content = (raw == null ? "" : String(raw)).replace(/^\*+/, "");
|
|
397
824
|
}
|
|
398
|
-
if (!isBeforeClose)
|
|
399
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
419
|
-
} else
|
|
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 =
|
|
432
|
-
const lineText =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
481
|
-
const lineEnd =
|
|
482
|
-
const currentLine =
|
|
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
|
-
|
|
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:
|
|
687
|
-
raw:
|
|
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
|
|
694
|
-
raw:
|
|
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
|
|
704
|
-
markup: token.markup
|
|
705
|
-
raw: `:${
|
|
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
|
|
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:
|
|
970
|
-
raw: `[^${
|
|
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
|
|
1012
|
-
alt
|
|
1013
|
-
title
|
|
1014
|
-
raw
|
|
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
|
|
1025
|
-
raw:
|
|
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
|
|
1056
|
-
const href =
|
|
1057
|
-
const
|
|
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
|
-
|
|
1068
|
-
return
|
|
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
|
|
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:
|
|
1170
|
-
raw:
|
|
1326
|
+
content: display,
|
|
1327
|
+
raw: display
|
|
1171
1328
|
}],
|
|
1172
|
-
raw: `~${
|
|
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
|
|
1211
|
-
raw:
|
|
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
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
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
|
-
|
|
1233
|
-
let content = token.content.replace(/\\/g, "") || "";
|
|
1234
|
-
if (content.startsWith(")") && result[result.length - 1]?.type === "link") content = content.slice(1);
|
|
1235
|
-
for (; index >= 0; index--) {
|
|
1236
|
-
const item = result[index];
|
|
1237
|
-
if (item.type === "text") {
|
|
1238
|
-
currentTextNode = null;
|
|
1239
|
-
content = item.content + content;
|
|
1240
|
-
continue;
|
|
1241
|
-
}
|
|
1242
|
-
break;
|
|
1243
|
-
}
|
|
1244
|
-
if (index < result.length - 1) result.splice(index + 1);
|
|
1245
|
-
const nextToken = tokens[i + 1];
|
|
1246
|
-
if (content === "`" || content === "|" || content === "$" || content === "1" || /^\*+$/.test(content) || /^\d$/.test(content)) {
|
|
1247
|
-
i++;
|
|
1248
|
-
break;
|
|
1249
|
-
}
|
|
1250
|
-
if (!nextToken && /[^\]]\s*\(\s*$/.test(content)) content = content.replace(/\(\s*$/, "");
|
|
1251
|
-
if (raw?.startsWith("[") && pPreToken?.type === "list_item_open") {
|
|
1252
|
-
const w = content.slice(1).match(/[^\s\]]/);
|
|
1253
|
-
if (w === null) {
|
|
1254
|
-
i++;
|
|
1255
|
-
break;
|
|
1256
|
-
}
|
|
1257
|
-
if (w && /x/i.test(w[0]) || !w) {
|
|
1258
|
-
const checked = w ? w[0] === "x" || w[0] === "X" : false;
|
|
1259
|
-
result.push({
|
|
1260
|
-
type: "checkbox_input",
|
|
1261
|
-
checked,
|
|
1262
|
-
raw: checked ? "[x]" : "[ ]"
|
|
1263
|
-
});
|
|
1264
|
-
i++;
|
|
1265
|
-
break;
|
|
1266
|
-
}
|
|
1267
|
-
}
|
|
1268
|
-
if (/`[^`]*/.test(content)) {
|
|
1269
|
-
currentTextNode = null;
|
|
1270
|
-
const index$1 = content.indexOf("`");
|
|
1271
|
-
const _text = content.slice(0, index$1);
|
|
1272
|
-
const codeContent = content.slice(index$1);
|
|
1273
|
-
if (_text) result.push({
|
|
1274
|
-
type: "text",
|
|
1275
|
-
content: _text || "",
|
|
1276
|
-
raw: _text || ""
|
|
1277
|
-
});
|
|
1278
|
-
result.push({
|
|
1279
|
-
type: "inline_code",
|
|
1280
|
-
code: codeContent.replace(/`/g, ""),
|
|
1281
|
-
raw: codeContent || ""
|
|
1282
|
-
});
|
|
1283
|
-
i++;
|
|
1284
|
-
break;
|
|
1285
|
-
}
|
|
1286
|
-
if (content === "[") {
|
|
1287
|
-
i++;
|
|
1288
|
-
break;
|
|
1289
|
-
}
|
|
1290
|
-
if (/[^~]*~{2,}[^~]+/.test(content)) {
|
|
1291
|
-
const index$1 = content.indexOf("~~") || 0;
|
|
1292
|
-
const _text = content.slice(0, index$1);
|
|
1293
|
-
if (_text) if (currentTextNode) {
|
|
1294
|
-
currentTextNode.content += _text;
|
|
1295
|
-
currentTextNode.raw += _text;
|
|
1296
|
-
} else {
|
|
1297
|
-
currentTextNode = {
|
|
1298
|
-
type: "text",
|
|
1299
|
-
content: _text || "",
|
|
1300
|
-
raw: token.content || ""
|
|
1301
|
-
};
|
|
1302
|
-
result.push(currentTextNode);
|
|
1303
|
-
}
|
|
1304
|
-
const strikethroughContent = content.slice(index$1);
|
|
1305
|
-
currentTextNode = null;
|
|
1306
|
-
const { node } = parseStrikethroughToken([
|
|
1307
|
-
{
|
|
1308
|
-
type: "s_open",
|
|
1309
|
-
tag: "s",
|
|
1310
|
-
content: "",
|
|
1311
|
-
markup: "*",
|
|
1312
|
-
info: "",
|
|
1313
|
-
meta: null
|
|
1314
|
-
},
|
|
1315
|
-
{
|
|
1316
|
-
type: "text",
|
|
1317
|
-
tag: "",
|
|
1318
|
-
content: strikethroughContent.replace(/~/g, ""),
|
|
1319
|
-
markup: "",
|
|
1320
|
-
info: "",
|
|
1321
|
-
meta: null
|
|
1322
|
-
},
|
|
1323
|
-
{
|
|
1324
|
-
type: "s_close",
|
|
1325
|
-
tag: "s",
|
|
1326
|
-
content: "",
|
|
1327
|
-
markup: "*",
|
|
1328
|
-
info: "",
|
|
1329
|
-
meta: null
|
|
1330
|
-
}
|
|
1331
|
-
], 0);
|
|
1332
|
-
result.push(node);
|
|
1333
|
-
i++;
|
|
1334
|
-
break;
|
|
1335
|
-
}
|
|
1336
|
-
if (/[^*]*\*\*[^*]+/.test(content)) {
|
|
1337
|
-
const index$1 = content.indexOf("*") || 0;
|
|
1338
|
-
const _text = content.slice(0, index$1);
|
|
1339
|
-
if (_text) if (currentTextNode) {
|
|
1340
|
-
currentTextNode.content += _text;
|
|
1341
|
-
currentTextNode.raw += _text;
|
|
1342
|
-
} else {
|
|
1343
|
-
currentTextNode = {
|
|
1344
|
-
type: "text",
|
|
1345
|
-
content: _text || "",
|
|
1346
|
-
raw: token.content || ""
|
|
1347
|
-
};
|
|
1348
|
-
result.push(currentTextNode);
|
|
1349
|
-
}
|
|
1350
|
-
const strongContent = content.slice(index$1);
|
|
1351
|
-
currentTextNode = null;
|
|
1352
|
-
const { node } = parseStrongToken([
|
|
1353
|
-
{
|
|
1354
|
-
type: "strong_open",
|
|
1355
|
-
tag: "strong",
|
|
1356
|
-
content: "",
|
|
1357
|
-
markup: "*",
|
|
1358
|
-
info: "",
|
|
1359
|
-
meta: null
|
|
1360
|
-
},
|
|
1361
|
-
{
|
|
1362
|
-
type: "text",
|
|
1363
|
-
tag: "",
|
|
1364
|
-
content: strongContent.replace(/\*/g, ""),
|
|
1365
|
-
markup: "",
|
|
1366
|
-
info: "",
|
|
1367
|
-
meta: null
|
|
1368
|
-
},
|
|
1369
|
-
{
|
|
1370
|
-
type: "strong_close",
|
|
1371
|
-
tag: "strong",
|
|
1372
|
-
content: "",
|
|
1373
|
-
markup: "*",
|
|
1374
|
-
info: "",
|
|
1375
|
-
meta: null
|
|
1376
|
-
}
|
|
1377
|
-
], 0, raw);
|
|
1378
|
-
result.push(node);
|
|
1379
|
-
i++;
|
|
1380
|
-
break;
|
|
1381
|
-
} else if (/[^*]*\*[^*]+/.test(content)) {
|
|
1382
|
-
const index$1 = content.indexOf("*") || 0;
|
|
1383
|
-
const _text = content.slice(0, index$1);
|
|
1384
|
-
if (_text) if (currentTextNode) {
|
|
1385
|
-
currentTextNode.content += _text;
|
|
1386
|
-
currentTextNode.raw += _text;
|
|
1387
|
-
} else {
|
|
1388
|
-
currentTextNode = {
|
|
1389
|
-
type: "text",
|
|
1390
|
-
content: _text || "",
|
|
1391
|
-
raw: token.content || ""
|
|
1392
|
-
};
|
|
1393
|
-
result.push(currentTextNode);
|
|
1394
|
-
}
|
|
1395
|
-
const emphasisContent = content.slice(index$1);
|
|
1396
|
-
currentTextNode = null;
|
|
1397
|
-
const { node } = parseEmphasisToken([
|
|
1398
|
-
{
|
|
1399
|
-
type: "em_open",
|
|
1400
|
-
tag: "em",
|
|
1401
|
-
content: "",
|
|
1402
|
-
markup: "*",
|
|
1403
|
-
info: "",
|
|
1404
|
-
meta: null
|
|
1405
|
-
},
|
|
1406
|
-
{
|
|
1407
|
-
type: "text",
|
|
1408
|
-
tag: "",
|
|
1409
|
-
content: emphasisContent.replace(/\*/g, ""),
|
|
1410
|
-
markup: "",
|
|
1411
|
-
info: "",
|
|
1412
|
-
meta: null
|
|
1413
|
-
},
|
|
1414
|
-
{
|
|
1415
|
-
type: "em_close",
|
|
1416
|
-
tag: "em",
|
|
1417
|
-
content: "",
|
|
1418
|
-
markup: "*",
|
|
1419
|
-
info: "",
|
|
1420
|
-
meta: null
|
|
1421
|
-
}
|
|
1422
|
-
], 0);
|
|
1423
|
-
result.push(node);
|
|
1424
|
-
i++;
|
|
1425
|
-
break;
|
|
1426
|
-
}
|
|
1427
|
-
const imageStart = content.indexOf(";
|
|
1451
|
-
if (linkEnd !== -1) {
|
|
1452
|
-
const textToken = tokens[i + 2];
|
|
1453
|
-
let text = content.slice(linkStart + 1, linkEnd);
|
|
1454
|
-
if (text.includes("[")) {
|
|
1455
|
-
const secondLinkStart = text.indexOf("[");
|
|
1456
|
-
linkStart = linkStart + secondLinkStart + 1;
|
|
1457
|
-
textNodeContent += content.slice(0, linkStart);
|
|
1458
|
-
text = content.slice(linkStart + 1, linkEnd);
|
|
1459
|
-
}
|
|
1460
|
-
if (content.endsWith("](") && nextToken?.type === "link_open" && textToken) {
|
|
1461
|
-
const last = tokens[i + 4];
|
|
1462
|
-
let index$1 = 4;
|
|
1463
|
-
let loading$1 = true;
|
|
1464
|
-
if (last?.type === "text" && last.content === ")") {
|
|
1465
|
-
index$1++;
|
|
1466
|
-
loading$1 = false;
|
|
1467
|
-
} else if (last?.type === "text" && last.content === ".") i++;
|
|
1468
|
-
if (textNodeContent) result.push({
|
|
1469
|
-
type: "text",
|
|
1470
|
-
content: textNodeContent,
|
|
1471
|
-
raw: textNodeContent
|
|
1472
|
-
});
|
|
1473
|
-
result.push({
|
|
1474
|
-
type: "link",
|
|
1475
|
-
href: textToken.content || "",
|
|
1476
|
-
text,
|
|
1477
|
-
children: [{
|
|
1478
|
-
type: "text",
|
|
1479
|
-
content: text,
|
|
1480
|
-
raw: text
|
|
1481
|
-
}],
|
|
1482
|
-
loading: loading$1
|
|
1483
|
-
});
|
|
1484
|
-
i += index$1;
|
|
1485
|
-
break;
|
|
1486
|
-
}
|
|
1487
|
-
const linkContentEnd = content.indexOf(")", linkEnd);
|
|
1488
|
-
const href = linkContentEnd !== -1 ? content.slice(linkEnd + 2, linkContentEnd) : "";
|
|
1489
|
-
const loading = linkContentEnd === -1;
|
|
1490
|
-
if (textNodeContent) result.push({
|
|
1491
|
-
type: "text",
|
|
1492
|
-
content: textNodeContent,
|
|
1493
|
-
raw: textNodeContent
|
|
1494
|
-
});
|
|
1495
|
-
result.push({
|
|
1496
|
-
type: "link",
|
|
1497
|
-
href,
|
|
1498
|
-
text,
|
|
1499
|
-
children: [{
|
|
1500
|
-
type: "text",
|
|
1501
|
-
content: text,
|
|
1502
|
-
raw: text
|
|
1503
|
-
}],
|
|
1504
|
-
loading
|
|
1505
|
-
});
|
|
1506
|
-
const afterText = linkContentEnd !== -1 ? content.slice(linkContentEnd + 1) : "";
|
|
1507
|
-
if (afterText) {
|
|
1508
|
-
handleToken({
|
|
1509
|
-
type: "text",
|
|
1510
|
-
content: afterText,
|
|
1511
|
-
raw: afterText
|
|
1512
|
-
});
|
|
1513
|
-
i--;
|
|
1514
|
-
}
|
|
1515
|
-
i++;
|
|
1516
|
-
break;
|
|
1517
|
-
}
|
|
1518
|
-
}
|
|
1519
|
-
const preToken = tokens[i - 1];
|
|
1520
|
-
if (currentTextNode) {
|
|
1521
|
-
currentTextNode.content += textNode.content.replace(/(\*+|\(|\\)$/, "");
|
|
1522
|
-
currentTextNode.raw += textNode.raw;
|
|
1523
|
-
} else {
|
|
1524
|
-
const maybeMath = preToken?.tag === "br" && tokens[i - 2]?.content === "[";
|
|
1525
|
-
if (!tokens[i + 1]) textNode.content = textNode.content.replace(/(\*+|\(|\\)$/, "");
|
|
1526
|
-
currentTextNode = textNode;
|
|
1527
|
-
currentTextNode.center = maybeMath;
|
|
1528
|
-
result.push(currentTextNode);
|
|
1529
|
-
}
|
|
1530
|
-
i++;
|
|
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
|
-
|
|
1542
|
-
result.push(parseInlineCodeToken(token));
|
|
1614
|
+
pushNode(parseInlineCodeToken(token));
|
|
1543
1615
|
i++;
|
|
1544
1616
|
break;
|
|
1545
|
-
case "link_open":
|
|
1546
|
-
|
|
1547
|
-
const href = token.attrs?.find((attr) => attr[0] === "href")?.[1];
|
|
1548
|
-
if (raw && tokens[i + 1].type === "text") {
|
|
1549
|
-
const text = tokens[i + 1]?.content || "";
|
|
1550
|
-
if (!(/* @__PURE__ */ new RegExp(`\\[${text}\\s*\\]`)).test(raw)) {
|
|
1551
|
-
result.push({
|
|
1552
|
-
type: "text",
|
|
1553
|
-
content: text,
|
|
1554
|
-
raw: text
|
|
1555
|
-
});
|
|
1556
|
-
i += 3;
|
|
1557
|
-
break;
|
|
1558
|
-
}
|
|
1559
|
-
}
|
|
1560
|
-
if (raw && href) {
|
|
1561
|
-
const loadingMath = /* @__PURE__ */ new RegExp(`\\(\\s*${href}\\s*\\)`);
|
|
1562
|
-
const pre = result.length > 0 ? result[result.length - 1] : null;
|
|
1563
|
-
const loading = !loadingMath.test(raw);
|
|
1564
|
-
if (loading && pre) {
|
|
1565
|
-
if ((/* @__PURE__ */ new RegExp(`\\[${pre.text}\\s*\\]\\(`)).test(raw)) {
|
|
1566
|
-
const text = pre?.text || pre?.content?.slice(1, -1) || "";
|
|
1567
|
-
result.splice(result.length - 1, 1, {
|
|
1568
|
-
type: "link",
|
|
1569
|
-
href: "",
|
|
1570
|
-
text,
|
|
1571
|
-
loading
|
|
1572
|
-
});
|
|
1573
|
-
i += 3;
|
|
1574
|
-
if (tokens[i]?.content === ".") i++;
|
|
1575
|
-
break;
|
|
1576
|
-
}
|
|
1577
|
-
}
|
|
1578
|
-
}
|
|
1579
|
-
const { node, nextIndex } = parseLinkToken(tokens, i);
|
|
1580
|
-
i = nextIndex;
|
|
1581
|
-
node.loading = false;
|
|
1582
|
-
result.push(node);
|
|
1617
|
+
case "link_open":
|
|
1618
|
+
handleLinkOpen(token);
|
|
1583
1619
|
break;
|
|
1584
|
-
}
|
|
1585
1620
|
case "image":
|
|
1586
|
-
|
|
1587
|
-
|
|
1621
|
+
resetCurrentTextNode();
|
|
1622
|
+
pushNode(parseImageToken(token));
|
|
1588
1623
|
i++;
|
|
1589
1624
|
break;
|
|
1590
1625
|
case "strong_open": {
|
|
1591
|
-
|
|
1626
|
+
resetCurrentTextNode();
|
|
1592
1627
|
const { node, nextIndex } = parseStrongToken(tokens, i, token.content);
|
|
1593
|
-
|
|
1628
|
+
pushNode(node);
|
|
1594
1629
|
i = nextIndex;
|
|
1595
1630
|
break;
|
|
1596
1631
|
}
|
|
1597
1632
|
case "em_open": {
|
|
1598
|
-
|
|
1633
|
+
resetCurrentTextNode();
|
|
1599
1634
|
const { node, nextIndex } = parseEmphasisToken(tokens, i);
|
|
1600
|
-
|
|
1635
|
+
pushNode(node);
|
|
1601
1636
|
i = nextIndex;
|
|
1602
1637
|
break;
|
|
1603
1638
|
}
|
|
1604
1639
|
case "s_open": {
|
|
1605
|
-
|
|
1640
|
+
resetCurrentTextNode();
|
|
1606
1641
|
const { node, nextIndex } = parseStrikethroughToken(tokens, i);
|
|
1607
|
-
|
|
1642
|
+
pushNode(node);
|
|
1608
1643
|
i = nextIndex;
|
|
1609
1644
|
break;
|
|
1610
1645
|
}
|
|
1611
1646
|
case "mark_open": {
|
|
1612
|
-
|
|
1647
|
+
resetCurrentTextNode();
|
|
1613
1648
|
const { node, nextIndex } = parseHighlightToken(tokens, i);
|
|
1614
|
-
|
|
1649
|
+
pushNode(node);
|
|
1615
1650
|
i = nextIndex;
|
|
1616
1651
|
break;
|
|
1617
1652
|
}
|
|
1618
1653
|
case "ins_open": {
|
|
1619
|
-
|
|
1654
|
+
resetCurrentTextNode();
|
|
1620
1655
|
const { node, nextIndex } = parseInsertToken(tokens, i);
|
|
1621
|
-
|
|
1656
|
+
pushNode(node);
|
|
1622
1657
|
i = nextIndex;
|
|
1623
1658
|
break;
|
|
1624
1659
|
}
|
|
1625
1660
|
case "sub_open": {
|
|
1626
|
-
|
|
1661
|
+
resetCurrentTextNode();
|
|
1627
1662
|
const { node, nextIndex } = parseSubscriptToken(tokens, i);
|
|
1628
|
-
|
|
1663
|
+
pushNode(node);
|
|
1629
1664
|
i = nextIndex;
|
|
1630
1665
|
break;
|
|
1631
1666
|
}
|
|
1632
1667
|
case "sup_open": {
|
|
1633
|
-
|
|
1668
|
+
resetCurrentTextNode();
|
|
1634
1669
|
const { node, nextIndex } = parseSuperscriptToken(tokens, i);
|
|
1635
|
-
|
|
1670
|
+
pushNode(node);
|
|
1636
1671
|
i = nextIndex;
|
|
1637
1672
|
break;
|
|
1638
1673
|
}
|
|
1639
1674
|
case "sub":
|
|
1640
|
-
|
|
1641
|
-
|
|
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
|
-
|
|
1654
|
-
|
|
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
|
-
|
|
1701
|
+
resetCurrentTextNode();
|
|
1667
1702
|
const preToken = tokens[i - 1];
|
|
1668
|
-
if (preToken?.type === "text" && /\|:-+/.test(preToken.content
|
|
1669
|
-
|
|
1670
|
-
content: "",
|
|
1671
|
-
raw: ""
|
|
1672
|
-
});
|
|
1673
|
-
else result.push(parseEmojiToken(token));
|
|
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
|
-
|
|
1679
|
-
|
|
1709
|
+
resetCurrentTextNode();
|
|
1710
|
+
pushNode(parseCheckboxToken(token));
|
|
1680
1711
|
i++;
|
|
1681
1712
|
break;
|
|
1682
1713
|
case "checkbox_input":
|
|
1683
|
-
|
|
1684
|
-
|
|
1714
|
+
resetCurrentTextNode();
|
|
1715
|
+
pushNode(parseCheckboxInputToken(token));
|
|
1685
1716
|
i++;
|
|
1686
1717
|
break;
|
|
1687
1718
|
case "footnote_ref":
|
|
1688
|
-
|
|
1689
|
-
|
|
1719
|
+
resetCurrentTextNode();
|
|
1720
|
+
pushNode(parseFootnoteRefToken(token));
|
|
1690
1721
|
i++;
|
|
1691
1722
|
break;
|
|
1692
1723
|
case "hardbreak":
|
|
1693
|
-
|
|
1694
|
-
|
|
1724
|
+
resetCurrentTextNode();
|
|
1725
|
+
pushNode(parseHardbreakToken());
|
|
1695
1726
|
i++;
|
|
1696
1727
|
break;
|
|
1697
1728
|
case "fence":
|
|
1698
|
-
|
|
1699
|
-
|
|
1729
|
+
resetCurrentTextNode();
|
|
1730
|
+
pushNode(parseFenceToken(tokens[i]));
|
|
1700
1731
|
i++;
|
|
1701
1732
|
break;
|
|
1702
1733
|
case "math_inline":
|
|
1703
|
-
|
|
1704
|
-
|
|
1734
|
+
resetCurrentTextNode();
|
|
1735
|
+
pushNode(parseMathInlineToken(token));
|
|
1705
1736
|
i++;
|
|
1706
1737
|
break;
|
|
1707
|
-
case "reference":
|
|
1708
|
-
|
|
1709
|
-
const nextToken = tokens[i + 1];
|
|
1710
|
-
const preToken = tokens[i - 1];
|
|
1711
|
-
const preResult = result[result.length - 1];
|
|
1712
|
-
if (nextToken?.type === "text" && !nextToken.content?.startsWith("(") || preToken.type === "text" && /\]$|^\s*$/.test(preToken.content || "")) result.push(parseReferenceToken(token));
|
|
1713
|
-
else if (nextToken && nextToken.type === "text") nextToken.content = token.markup + nextToken.content;
|
|
1714
|
-
else if (preResult.type === "text") {
|
|
1715
|
-
preResult.content = preResult.content + token.markup;
|
|
1716
|
-
preResult.raw = preResult.raw + token.markup;
|
|
1717
|
-
}
|
|
1718
|
-
i++;
|
|
1738
|
+
case "reference":
|
|
1739
|
+
handleReference(token);
|
|
1719
1740
|
break;
|
|
1720
|
-
}
|
|
1721
1741
|
default:
|
|
1722
|
-
|
|
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
|
|
1761
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
1937
|
-
|
|
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
|
|
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)
|
|
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
|
|
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)
|
|
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]
|
|
2073
|
-
const title = match[2]
|
|
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
|
|
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
|
|
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
|
|
2128
|
-
|
|
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
|
|
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")
|
|
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)
|
|
2297
|
-
|
|
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
|
|
2313
|
-
|
|
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
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
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
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
const
|
|
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 =
|
|
2622
|
+
const token = s.push("text", "", 0);
|
|
2341
2623
|
token.content = "~";
|
|
2342
2624
|
}
|
|
2343
|
-
|
|
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
|
|
2351
|
-
const info =
|
|
2352
|
-
const str =
|
|
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
|
|
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
|
-
|
|
2365
|
-
|
|
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 =
|
|
2652
|
+
const token = s.push("reference", "span", 0);
|
|
2370
2653
|
token.content = id;
|
|
2371
2654
|
token.markup = match[0];
|
|
2372
2655
|
}
|
|
2373
|
-
|
|
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
|
|
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;
|