stream-markdown-parser 0.0.47 → 0.0.49
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 +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +300 -271
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6752,7 +6752,7 @@ function applyContainers(md) {
|
|
|
6752
6752
|
const startPos = s.bMarks[startLine] + s.tShift[startLine];
|
|
6753
6753
|
const lineMax = s.eMarks[startLine];
|
|
6754
6754
|
const line = s.src.slice(startPos, lineMax);
|
|
6755
|
-
const nameMatch = line.match(
|
|
6755
|
+
const nameMatch = line.match(/^:::\s*(\S+)/);
|
|
6756
6756
|
if (!nameMatch) return false;
|
|
6757
6757
|
const name = nameMatch[1];
|
|
6758
6758
|
if (!name.trim()) return false;
|
|
@@ -6800,13 +6800,12 @@ function applyContainers(md) {
|
|
|
6800
6800
|
contentLines.push(s.src.slice(sPos, ePos));
|
|
6801
6801
|
}
|
|
6802
6802
|
if (contentLines.some((line$1) => line$1.trim().length > 0)) {
|
|
6803
|
-
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
s.
|
|
6809
|
-
s.push("paragraph_close", "p", -1);
|
|
6803
|
+
let innerSrc = contentLines.join("\n");
|
|
6804
|
+
if (!innerSrc.endsWith("\n")) innerSrc += "\n";
|
|
6805
|
+
if (!innerSrc.endsWith("\n\n")) innerSrc += "\n";
|
|
6806
|
+
const innerTokens = [];
|
|
6807
|
+
s.md.block.parse(innerSrc, s.md, s.env, innerTokens);
|
|
6808
|
+
s.tokens.push(...innerTokens);
|
|
6810
6809
|
}
|
|
6811
6810
|
s.push("vmr_container_close", "div", -1);
|
|
6812
6811
|
s.line = nextLine + 1;
|
|
@@ -8499,6 +8498,7 @@ function applyMath(md, mathOpts) {
|
|
|
8499
8498
|
const mathInline = (state, silent) => {
|
|
8500
8499
|
const s = state;
|
|
8501
8500
|
const strict = !!mathOpts?.strictDelimiters;
|
|
8501
|
+
const allowLoading = !s?.env?.__markstreamFinal;
|
|
8502
8502
|
if (/^\*[^*]+/.test(s.src)) return false;
|
|
8503
8503
|
const delimiters = [["$", "$"], ["\\(", "\\)"]];
|
|
8504
8504
|
let searchPos = 0;
|
|
@@ -8544,7 +8544,7 @@ function applyMath(md, mathOpts) {
|
|
|
8544
8544
|
continue;
|
|
8545
8545
|
}
|
|
8546
8546
|
if (endIdx === -1) {
|
|
8547
|
-
if (!strict && isMathLike(content$1) && !content$1.includes("`")) {
|
|
8547
|
+
if (allowLoading && !strict && isMathLike(content$1) && !content$1.includes("`")) {
|
|
8548
8548
|
searchPos = index + open.length;
|
|
8549
8549
|
foundAny = true;
|
|
8550
8550
|
if (!silent) {
|
|
@@ -8585,7 +8585,8 @@ function applyMath(md, mathOpts) {
|
|
|
8585
8585
|
}
|
|
8586
8586
|
const content = src.slice(index + open.length, endIdx);
|
|
8587
8587
|
const hasBacktick = content.includes("`");
|
|
8588
|
-
|
|
8588
|
+
const isEmpty = !content || !content.trim();
|
|
8589
|
+
if (strict ? hasBacktick || isEmpty : hasBacktick || isEmpty || !(open === "$") && !isMathLike(content)) {
|
|
8589
8590
|
searchPos = endIdx + close.length;
|
|
8590
8591
|
const text$1 = src.slice(s.pos, searchPos);
|
|
8591
8592
|
if (!s.pending) pushText(text$1);
|
|
@@ -8654,6 +8655,7 @@ function applyMath(md, mathOpts) {
|
|
|
8654
8655
|
};
|
|
8655
8656
|
const mathBlock = (state, startLine, endLine, silent) => {
|
|
8656
8657
|
const s = state;
|
|
8658
|
+
const allowLoading = !s?.env?.__markstreamFinal;
|
|
8657
8659
|
const strict = mathOpts?.strictDelimiters;
|
|
8658
8660
|
const delimiters = strict ? [["\\[", "\\]"], ["$$", "$$"]] : [
|
|
8659
8661
|
["\\[", "\\]"],
|
|
@@ -8761,7 +8763,7 @@ function applyMath(md, mathOpts) {
|
|
|
8761
8763
|
content += (content ? "\n" : "") + currentLine;
|
|
8762
8764
|
}
|
|
8763
8765
|
}
|
|
8764
|
-
if (strict && !found) return false;
|
|
8766
|
+
if ((!allowLoading || strict) && !found) return false;
|
|
8765
8767
|
if (!(openDelim === "[" ? isPlainBracketMathLike(content) : isMathLike(content))) return false;
|
|
8766
8768
|
const token = s.push("math_block", "math", 0);
|
|
8767
8769
|
token.content = normalizeStandaloneBackslashT(content);
|
|
@@ -10273,6 +10275,249 @@ function normalizeSingleLinkResult(raw, nodes) {
|
|
|
10273
10275
|
return nodes;
|
|
10274
10276
|
}
|
|
10275
10277
|
|
|
10278
|
+
//#endregion
|
|
10279
|
+
//#region src/parser/node-parsers/list-parser.ts
|
|
10280
|
+
function parseList(tokens, index, options) {
|
|
10281
|
+
const token = tokens[index];
|
|
10282
|
+
const listItems = [];
|
|
10283
|
+
let j = index + 1;
|
|
10284
|
+
while (j < tokens.length && tokens[j].type !== "bullet_list_close" && tokens[j].type !== "ordered_list_close") if (tokens[j].type === "list_item_open") {
|
|
10285
|
+
const itemChildren = [];
|
|
10286
|
+
let k = j + 1;
|
|
10287
|
+
while (k < tokens.length && tokens[k].type !== "list_item_close") if (tokens[k].type === "paragraph_open") {
|
|
10288
|
+
const contentToken = tokens[k + 1];
|
|
10289
|
+
const preToken = tokens[k - 1];
|
|
10290
|
+
const contentStr = String(contentToken.content ?? "");
|
|
10291
|
+
if (/\n\d+$/.test(contentStr)) {
|
|
10292
|
+
contentToken.content = contentStr.replace(/\n\d+$/, "");
|
|
10293
|
+
contentToken.children?.splice(-1, 1);
|
|
10294
|
+
}
|
|
10295
|
+
itemChildren.push({
|
|
10296
|
+
type: "paragraph",
|
|
10297
|
+
children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? ""), preToken, {
|
|
10298
|
+
requireClosingStrong: options?.requireClosingStrong,
|
|
10299
|
+
customHtmlTags: options?.customHtmlTags
|
|
10300
|
+
}),
|
|
10301
|
+
raw: String(contentToken.content ?? "")
|
|
10302
|
+
});
|
|
10303
|
+
k += 3;
|
|
10304
|
+
} else if (tokens[k].type === "blockquote_open") {
|
|
10305
|
+
const [blockquoteNode, newIndex] = parseBlockquote(tokens, k, options);
|
|
10306
|
+
itemChildren.push(blockquoteNode);
|
|
10307
|
+
k = newIndex;
|
|
10308
|
+
} else if (tokens[k].type === "bullet_list_open" || tokens[k].type === "ordered_list_open") {
|
|
10309
|
+
const [nestedListNode, newIndex] = parseList(tokens, k, options);
|
|
10310
|
+
itemChildren.push(nestedListNode);
|
|
10311
|
+
k = newIndex;
|
|
10312
|
+
} else {
|
|
10313
|
+
const handled = parseCommonBlockToken(tokens, k, options, containerTokenHandlers);
|
|
10314
|
+
if (handled) {
|
|
10315
|
+
itemChildren.push(handled[0]);
|
|
10316
|
+
k = handled[1];
|
|
10317
|
+
} else k += 1;
|
|
10318
|
+
}
|
|
10319
|
+
listItems.push({
|
|
10320
|
+
type: "list_item",
|
|
10321
|
+
children: itemChildren,
|
|
10322
|
+
raw: itemChildren.map((child) => child.raw).join("")
|
|
10323
|
+
});
|
|
10324
|
+
j = k + 1;
|
|
10325
|
+
} else j += 1;
|
|
10326
|
+
return [{
|
|
10327
|
+
type: "list",
|
|
10328
|
+
ordered: token.type === "ordered_list_open",
|
|
10329
|
+
start: (() => {
|
|
10330
|
+
if (token.attrs && token.attrs.length) {
|
|
10331
|
+
const found = token.attrs.find((a) => a[0] === "start");
|
|
10332
|
+
if (found) {
|
|
10333
|
+
const parsed = Number(found[1]);
|
|
10334
|
+
return Number.isFinite(parsed) && parsed !== 0 ? parsed : 1;
|
|
10335
|
+
}
|
|
10336
|
+
}
|
|
10337
|
+
})(),
|
|
10338
|
+
items: listItems,
|
|
10339
|
+
raw: listItems.map((item) => item.raw).join("\n")
|
|
10340
|
+
}, j + 1];
|
|
10341
|
+
}
|
|
10342
|
+
|
|
10343
|
+
//#endregion
|
|
10344
|
+
//#region src/parser/node-parsers/admonition-parser.ts
|
|
10345
|
+
function parseAdmonition(tokens, index, match, options) {
|
|
10346
|
+
const kind = String(match[1] ?? "note");
|
|
10347
|
+
const title = String(match[2] ?? kind.charAt(0).toUpperCase() + kind.slice(1));
|
|
10348
|
+
const admonitionChildren = [];
|
|
10349
|
+
let j = index + 1;
|
|
10350
|
+
while (j < tokens.length && tokens[j].type !== "container_close") if (tokens[j].type === "paragraph_open") {
|
|
10351
|
+
const contentToken = tokens[j + 1];
|
|
10352
|
+
if (contentToken) admonitionChildren.push({
|
|
10353
|
+
type: "paragraph",
|
|
10354
|
+
children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? ""), void 0, {
|
|
10355
|
+
requireClosingStrong: options?.requireClosingStrong,
|
|
10356
|
+
customHtmlTags: options?.customHtmlTags
|
|
10357
|
+
}),
|
|
10358
|
+
raw: String(contentToken.content ?? "")
|
|
10359
|
+
});
|
|
10360
|
+
j += 3;
|
|
10361
|
+
} else if (tokens[j].type === "bullet_list_open" || tokens[j].type === "ordered_list_open") {
|
|
10362
|
+
const [listNode, newIndex] = parseList(tokens, j, options);
|
|
10363
|
+
admonitionChildren.push(listNode);
|
|
10364
|
+
j = newIndex;
|
|
10365
|
+
} else if (tokens[j].type === "blockquote_open") {
|
|
10366
|
+
const [blockquoteNode, newIndex] = parseBlockquote(tokens, j, options);
|
|
10367
|
+
admonitionChildren.push(blockquoteNode);
|
|
10368
|
+
j = newIndex;
|
|
10369
|
+
} else {
|
|
10370
|
+
const handled = parseBasicBlockToken(tokens, j, options);
|
|
10371
|
+
if (handled) {
|
|
10372
|
+
admonitionChildren.push(handled[0]);
|
|
10373
|
+
j = handled[1];
|
|
10374
|
+
} else j++;
|
|
10375
|
+
}
|
|
10376
|
+
return [{
|
|
10377
|
+
type: "admonition",
|
|
10378
|
+
kind,
|
|
10379
|
+
title,
|
|
10380
|
+
children: admonitionChildren,
|
|
10381
|
+
raw: `:::${kind} ${title}\n${admonitionChildren.map((child) => child.raw).join("\n")}\n:::`
|
|
10382
|
+
}, j + 1];
|
|
10383
|
+
}
|
|
10384
|
+
|
|
10385
|
+
//#endregion
|
|
10386
|
+
//#region src/parser/node-parsers/container-parser.ts
|
|
10387
|
+
function parseContainer(tokens, index, options) {
|
|
10388
|
+
const openToken = tokens[index];
|
|
10389
|
+
let kind = "note";
|
|
10390
|
+
let title = "";
|
|
10391
|
+
const typeMatch = openToken.type.match(/^container_(\w+)_open$/);
|
|
10392
|
+
if (typeMatch) {
|
|
10393
|
+
kind = typeMatch[1];
|
|
10394
|
+
const info = String(openToken.info ?? "").trim();
|
|
10395
|
+
if (info && !info.startsWith(":::")) {
|
|
10396
|
+
const maybe = info.replace(/* @__PURE__ */ new RegExp(`^${kind}`), "").trim();
|
|
10397
|
+
if (maybe) title = maybe;
|
|
10398
|
+
}
|
|
10399
|
+
} else {
|
|
10400
|
+
const info = String(openToken.info ?? "").trim();
|
|
10401
|
+
const match = /^:{1,3}\s*(warning|info|note|tip|danger|caution)\s*(.*)$/i.exec(info);
|
|
10402
|
+
if (match) {
|
|
10403
|
+
kind = match[1];
|
|
10404
|
+
title = String(match[2] ?? "");
|
|
10405
|
+
}
|
|
10406
|
+
}
|
|
10407
|
+
if (!title) title = kind.charAt(0).toUpperCase() + kind.slice(1);
|
|
10408
|
+
const children = [];
|
|
10409
|
+
let j = index + 1;
|
|
10410
|
+
const closeType = /* @__PURE__ */ new RegExp(`^container_${kind}_close$`);
|
|
10411
|
+
while (j < tokens.length && tokens[j].type !== "container_close" && !closeType.test(tokens[j].type)) if (tokens[j].type === "paragraph_open") {
|
|
10412
|
+
const contentToken = tokens[j + 1];
|
|
10413
|
+
if (contentToken) {
|
|
10414
|
+
const childrenArr = contentToken.children || [];
|
|
10415
|
+
let i = -1;
|
|
10416
|
+
for (let k = childrenArr.length - 1; k >= 0; k--) {
|
|
10417
|
+
const t = childrenArr[k];
|
|
10418
|
+
if (t.type === "text" && /:+/.test(t.content)) {
|
|
10419
|
+
i = k;
|
|
10420
|
+
break;
|
|
10421
|
+
}
|
|
10422
|
+
}
|
|
10423
|
+
const _children = i !== -1 ? childrenArr.slice(0, i) : childrenArr;
|
|
10424
|
+
children.push({
|
|
10425
|
+
type: "paragraph",
|
|
10426
|
+
children: parseInlineTokens(_children || [], void 0, void 0, {
|
|
10427
|
+
requireClosingStrong: options?.requireClosingStrong,
|
|
10428
|
+
customHtmlTags: options?.customHtmlTags
|
|
10429
|
+
}),
|
|
10430
|
+
raw: String(contentToken.content ?? "").replace(/\n:+$/, "").replace(/\n\s*:::\s*$/, "")
|
|
10431
|
+
});
|
|
10432
|
+
}
|
|
10433
|
+
j += 3;
|
|
10434
|
+
} else if (tokens[j].type === "bullet_list_open" || tokens[j].type === "ordered_list_open") {
|
|
10435
|
+
const [listNode, newIndex] = parseList(tokens, j, options);
|
|
10436
|
+
children.push(listNode);
|
|
10437
|
+
j = newIndex;
|
|
10438
|
+
} else if (tokens[j].type === "blockquote_open") {
|
|
10439
|
+
const [blockquoteNode, newIndex] = parseBlockquote(tokens, j, options);
|
|
10440
|
+
children.push(blockquoteNode);
|
|
10441
|
+
j = newIndex;
|
|
10442
|
+
} else {
|
|
10443
|
+
const handled = parseBasicBlockToken(tokens, j, options);
|
|
10444
|
+
if (handled) {
|
|
10445
|
+
children.push(handled[0]);
|
|
10446
|
+
j = handled[1];
|
|
10447
|
+
} else j++;
|
|
10448
|
+
}
|
|
10449
|
+
return [{
|
|
10450
|
+
type: "admonition",
|
|
10451
|
+
kind,
|
|
10452
|
+
title,
|
|
10453
|
+
children,
|
|
10454
|
+
raw: `:::${kind} ${title}\n${children.map((c) => c.raw).join("\n")}\n:::`
|
|
10455
|
+
}, j + 1];
|
|
10456
|
+
}
|
|
10457
|
+
|
|
10458
|
+
//#endregion
|
|
10459
|
+
//#region src/parser/node-parsers/container-token-handlers.ts
|
|
10460
|
+
const CONTAINER_REGEX = /^::: ?(warning|info|note|tip|danger|caution|error) ?(.*)$/;
|
|
10461
|
+
function handleContainerOpen(tokens, index, options) {
|
|
10462
|
+
const token = tokens[index];
|
|
10463
|
+
if (token.type !== "container_open") return null;
|
|
10464
|
+
const match = CONTAINER_REGEX.exec(String(token.info ?? ""));
|
|
10465
|
+
if (!match) return null;
|
|
10466
|
+
return parseAdmonition(tokens, index, match, options);
|
|
10467
|
+
}
|
|
10468
|
+
const containerTokenHandlers = {
|
|
10469
|
+
parseContainer: (tokens, index, options) => parseContainer(tokens, index, options),
|
|
10470
|
+
matchAdmonition: handleContainerOpen
|
|
10471
|
+
};
|
|
10472
|
+
|
|
10473
|
+
//#endregion
|
|
10474
|
+
//#region src/parser/node-parsers/blockquote-parser.ts
|
|
10475
|
+
function parseBlockquote(tokens, index, options) {
|
|
10476
|
+
const blockquoteChildren = [];
|
|
10477
|
+
let j = index + 1;
|
|
10478
|
+
while (j < tokens.length && tokens[j].type !== "blockquote_close") switch (tokens[j].type) {
|
|
10479
|
+
case "paragraph_open": {
|
|
10480
|
+
const contentToken = tokens[j + 1];
|
|
10481
|
+
blockquoteChildren.push({
|
|
10482
|
+
type: "paragraph",
|
|
10483
|
+
children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? ""), void 0, {
|
|
10484
|
+
requireClosingStrong: options?.requireClosingStrong,
|
|
10485
|
+
customHtmlTags: options?.customHtmlTags
|
|
10486
|
+
}),
|
|
10487
|
+
raw: String(contentToken.content ?? "")
|
|
10488
|
+
});
|
|
10489
|
+
j += 3;
|
|
10490
|
+
break;
|
|
10491
|
+
}
|
|
10492
|
+
case "bullet_list_open":
|
|
10493
|
+
case "ordered_list_open": {
|
|
10494
|
+
const [listNode, newIndex] = parseList(tokens, j, options);
|
|
10495
|
+
blockquoteChildren.push(listNode);
|
|
10496
|
+
j = newIndex;
|
|
10497
|
+
break;
|
|
10498
|
+
}
|
|
10499
|
+
case "blockquote_open": {
|
|
10500
|
+
const [nestedBlockquote, newIndex] = parseBlockquote(tokens, j, options);
|
|
10501
|
+
blockquoteChildren.push(nestedBlockquote);
|
|
10502
|
+
j = newIndex;
|
|
10503
|
+
break;
|
|
10504
|
+
}
|
|
10505
|
+
default: {
|
|
10506
|
+
const handled = parseCommonBlockToken(tokens, j, options, containerTokenHandlers);
|
|
10507
|
+
if (handled) {
|
|
10508
|
+
blockquoteChildren.push(handled[0]);
|
|
10509
|
+
j = handled[1];
|
|
10510
|
+
} else j++;
|
|
10511
|
+
break;
|
|
10512
|
+
}
|
|
10513
|
+
}
|
|
10514
|
+
return [{
|
|
10515
|
+
type: "blockquote",
|
|
10516
|
+
children: blockquoteChildren,
|
|
10517
|
+
raw: blockquoteChildren.map((child) => child.raw).join("\n")
|
|
10518
|
+
}, j + 1];
|
|
10519
|
+
}
|
|
10520
|
+
|
|
10276
10521
|
//#endregion
|
|
10277
10522
|
//#region src/parser/node-parsers/code-block-parser.ts
|
|
10278
10523
|
function parseCodeBlock(token) {
|
|
@@ -10550,7 +10795,29 @@ function parseVmrContainer(tokens, index, options) {
|
|
|
10550
10795
|
}
|
|
10551
10796
|
const children = [];
|
|
10552
10797
|
let j = index + 1;
|
|
10553
|
-
while (j < tokens.length && tokens[j].type !== "vmr_container_close") {
|
|
10798
|
+
while (j < tokens.length && tokens[j].type !== "vmr_container_close") if (tokens[j].type === "paragraph_open") {
|
|
10799
|
+
const contentToken = tokens[j + 1];
|
|
10800
|
+
if (contentToken) {
|
|
10801
|
+
const childrenArr = contentToken.children || [];
|
|
10802
|
+
children.push({
|
|
10803
|
+
type: "paragraph",
|
|
10804
|
+
children: parseInlineTokens(childrenArr || [], void 0, void 0, {
|
|
10805
|
+
requireClosingStrong: options?.requireClosingStrong,
|
|
10806
|
+
customHtmlTags: options?.customHtmlTags
|
|
10807
|
+
}),
|
|
10808
|
+
raw: String(contentToken.content ?? "")
|
|
10809
|
+
});
|
|
10810
|
+
}
|
|
10811
|
+
j += 3;
|
|
10812
|
+
} else if (tokens[j].type === "bullet_list_open" || tokens[j].type === "ordered_list_open") {
|
|
10813
|
+
const [listNode, newIndex] = parseList(tokens, j, options);
|
|
10814
|
+
children.push(listNode);
|
|
10815
|
+
j = newIndex;
|
|
10816
|
+
} else if (tokens[j].type === "blockquote_open") {
|
|
10817
|
+
const [blockquoteNode, newIndex] = parseBlockquote(tokens, j, options);
|
|
10818
|
+
children.push(blockquoteNode);
|
|
10819
|
+
j = newIndex;
|
|
10820
|
+
} else {
|
|
10554
10821
|
const handled = parseBasicBlockToken(tokens, j, options);
|
|
10555
10822
|
if (handled) {
|
|
10556
10823
|
children.push(handled[0]);
|
|
@@ -10754,249 +11021,6 @@ function parseCommonBlockToken(tokens, index, options, handlers) {
|
|
|
10754
11021
|
return null;
|
|
10755
11022
|
}
|
|
10756
11023
|
|
|
10757
|
-
//#endregion
|
|
10758
|
-
//#region src/parser/node-parsers/list-parser.ts
|
|
10759
|
-
function parseList(tokens, index, options) {
|
|
10760
|
-
const token = tokens[index];
|
|
10761
|
-
const listItems = [];
|
|
10762
|
-
let j = index + 1;
|
|
10763
|
-
while (j < tokens.length && tokens[j].type !== "bullet_list_close" && tokens[j].type !== "ordered_list_close") if (tokens[j].type === "list_item_open") {
|
|
10764
|
-
const itemChildren = [];
|
|
10765
|
-
let k = j + 1;
|
|
10766
|
-
while (k < tokens.length && tokens[k].type !== "list_item_close") if (tokens[k].type === "paragraph_open") {
|
|
10767
|
-
const contentToken = tokens[k + 1];
|
|
10768
|
-
const preToken = tokens[k - 1];
|
|
10769
|
-
const contentStr = String(contentToken.content ?? "");
|
|
10770
|
-
if (/\n\d+$/.test(contentStr)) {
|
|
10771
|
-
contentToken.content = contentStr.replace(/\n\d+$/, "");
|
|
10772
|
-
contentToken.children?.splice(-1, 1);
|
|
10773
|
-
}
|
|
10774
|
-
itemChildren.push({
|
|
10775
|
-
type: "paragraph",
|
|
10776
|
-
children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? ""), preToken, {
|
|
10777
|
-
requireClosingStrong: options?.requireClosingStrong,
|
|
10778
|
-
customHtmlTags: options?.customHtmlTags
|
|
10779
|
-
}),
|
|
10780
|
-
raw: String(contentToken.content ?? "")
|
|
10781
|
-
});
|
|
10782
|
-
k += 3;
|
|
10783
|
-
} else if (tokens[k].type === "blockquote_open") {
|
|
10784
|
-
const [blockquoteNode, newIndex] = parseBlockquote(tokens, k, options);
|
|
10785
|
-
itemChildren.push(blockquoteNode);
|
|
10786
|
-
k = newIndex;
|
|
10787
|
-
} else if (tokens[k].type === "bullet_list_open" || tokens[k].type === "ordered_list_open") {
|
|
10788
|
-
const [nestedListNode, newIndex] = parseList(tokens, k, options);
|
|
10789
|
-
itemChildren.push(nestedListNode);
|
|
10790
|
-
k = newIndex;
|
|
10791
|
-
} else {
|
|
10792
|
-
const handled = parseCommonBlockToken(tokens, k, options, containerTokenHandlers);
|
|
10793
|
-
if (handled) {
|
|
10794
|
-
itemChildren.push(handled[0]);
|
|
10795
|
-
k = handled[1];
|
|
10796
|
-
} else k += 1;
|
|
10797
|
-
}
|
|
10798
|
-
listItems.push({
|
|
10799
|
-
type: "list_item",
|
|
10800
|
-
children: itemChildren,
|
|
10801
|
-
raw: itemChildren.map((child) => child.raw).join("")
|
|
10802
|
-
});
|
|
10803
|
-
j = k + 1;
|
|
10804
|
-
} else j += 1;
|
|
10805
|
-
return [{
|
|
10806
|
-
type: "list",
|
|
10807
|
-
ordered: token.type === "ordered_list_open",
|
|
10808
|
-
start: (() => {
|
|
10809
|
-
if (token.attrs && token.attrs.length) {
|
|
10810
|
-
const found = token.attrs.find((a) => a[0] === "start");
|
|
10811
|
-
if (found) {
|
|
10812
|
-
const parsed = Number(found[1]);
|
|
10813
|
-
return Number.isFinite(parsed) && parsed !== 0 ? parsed : 1;
|
|
10814
|
-
}
|
|
10815
|
-
}
|
|
10816
|
-
})(),
|
|
10817
|
-
items: listItems,
|
|
10818
|
-
raw: listItems.map((item) => item.raw).join("\n")
|
|
10819
|
-
}, j + 1];
|
|
10820
|
-
}
|
|
10821
|
-
|
|
10822
|
-
//#endregion
|
|
10823
|
-
//#region src/parser/node-parsers/admonition-parser.ts
|
|
10824
|
-
function parseAdmonition(tokens, index, match, options) {
|
|
10825
|
-
const kind = String(match[1] ?? "note");
|
|
10826
|
-
const title = String(match[2] ?? kind.charAt(0).toUpperCase() + kind.slice(1));
|
|
10827
|
-
const admonitionChildren = [];
|
|
10828
|
-
let j = index + 1;
|
|
10829
|
-
while (j < tokens.length && tokens[j].type !== "container_close") if (tokens[j].type === "paragraph_open") {
|
|
10830
|
-
const contentToken = tokens[j + 1];
|
|
10831
|
-
if (contentToken) admonitionChildren.push({
|
|
10832
|
-
type: "paragraph",
|
|
10833
|
-
children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? ""), void 0, {
|
|
10834
|
-
requireClosingStrong: options?.requireClosingStrong,
|
|
10835
|
-
customHtmlTags: options?.customHtmlTags
|
|
10836
|
-
}),
|
|
10837
|
-
raw: String(contentToken.content ?? "")
|
|
10838
|
-
});
|
|
10839
|
-
j += 3;
|
|
10840
|
-
} else if (tokens[j].type === "bullet_list_open" || tokens[j].type === "ordered_list_open") {
|
|
10841
|
-
const [listNode, newIndex] = parseList(tokens, j, options);
|
|
10842
|
-
admonitionChildren.push(listNode);
|
|
10843
|
-
j = newIndex;
|
|
10844
|
-
} else if (tokens[j].type === "blockquote_open") {
|
|
10845
|
-
const [blockquoteNode, newIndex] = parseBlockquote(tokens, j, options);
|
|
10846
|
-
admonitionChildren.push(blockquoteNode);
|
|
10847
|
-
j = newIndex;
|
|
10848
|
-
} else {
|
|
10849
|
-
const handled = parseBasicBlockToken(tokens, j, options);
|
|
10850
|
-
if (handled) {
|
|
10851
|
-
admonitionChildren.push(handled[0]);
|
|
10852
|
-
j = handled[1];
|
|
10853
|
-
} else j++;
|
|
10854
|
-
}
|
|
10855
|
-
return [{
|
|
10856
|
-
type: "admonition",
|
|
10857
|
-
kind,
|
|
10858
|
-
title,
|
|
10859
|
-
children: admonitionChildren,
|
|
10860
|
-
raw: `:::${kind} ${title}\n${admonitionChildren.map((child) => child.raw).join("\n")}\n:::`
|
|
10861
|
-
}, j + 1];
|
|
10862
|
-
}
|
|
10863
|
-
|
|
10864
|
-
//#endregion
|
|
10865
|
-
//#region src/parser/node-parsers/container-parser.ts
|
|
10866
|
-
function parseContainer(tokens, index, options) {
|
|
10867
|
-
const openToken = tokens[index];
|
|
10868
|
-
let kind = "note";
|
|
10869
|
-
let title = "";
|
|
10870
|
-
const typeMatch = openToken.type.match(/^container_(\w+)_open$/);
|
|
10871
|
-
if (typeMatch) {
|
|
10872
|
-
kind = typeMatch[1];
|
|
10873
|
-
const info = String(openToken.info ?? "").trim();
|
|
10874
|
-
if (info && !info.startsWith(":::")) {
|
|
10875
|
-
const maybe = info.replace(/* @__PURE__ */ new RegExp(`^${kind}`), "").trim();
|
|
10876
|
-
if (maybe) title = maybe;
|
|
10877
|
-
}
|
|
10878
|
-
} else {
|
|
10879
|
-
const info = String(openToken.info ?? "").trim();
|
|
10880
|
-
const match = /^:{1,3}\s*(warning|info|note|tip|danger|caution)\s*(.*)$/i.exec(info);
|
|
10881
|
-
if (match) {
|
|
10882
|
-
kind = match[1];
|
|
10883
|
-
title = String(match[2] ?? "");
|
|
10884
|
-
}
|
|
10885
|
-
}
|
|
10886
|
-
if (!title) title = kind.charAt(0).toUpperCase() + kind.slice(1);
|
|
10887
|
-
const children = [];
|
|
10888
|
-
let j = index + 1;
|
|
10889
|
-
const closeType = /* @__PURE__ */ new RegExp(`^container_${kind}_close$`);
|
|
10890
|
-
while (j < tokens.length && tokens[j].type !== "container_close" && !closeType.test(tokens[j].type)) if (tokens[j].type === "paragraph_open") {
|
|
10891
|
-
const contentToken = tokens[j + 1];
|
|
10892
|
-
if (contentToken) {
|
|
10893
|
-
const childrenArr = contentToken.children || [];
|
|
10894
|
-
let i = -1;
|
|
10895
|
-
for (let k = childrenArr.length - 1; k >= 0; k--) {
|
|
10896
|
-
const t = childrenArr[k];
|
|
10897
|
-
if (t.type === "text" && /:+/.test(t.content)) {
|
|
10898
|
-
i = k;
|
|
10899
|
-
break;
|
|
10900
|
-
}
|
|
10901
|
-
}
|
|
10902
|
-
const _children = i !== -1 ? childrenArr.slice(0, i) : childrenArr;
|
|
10903
|
-
children.push({
|
|
10904
|
-
type: "paragraph",
|
|
10905
|
-
children: parseInlineTokens(_children || [], void 0, void 0, {
|
|
10906
|
-
requireClosingStrong: options?.requireClosingStrong,
|
|
10907
|
-
customHtmlTags: options?.customHtmlTags
|
|
10908
|
-
}),
|
|
10909
|
-
raw: String(contentToken.content ?? "").replace(/\n:+$/, "").replace(/\n\s*:::\s*$/, "")
|
|
10910
|
-
});
|
|
10911
|
-
}
|
|
10912
|
-
j += 3;
|
|
10913
|
-
} else if (tokens[j].type === "bullet_list_open" || tokens[j].type === "ordered_list_open") {
|
|
10914
|
-
const [listNode, newIndex] = parseList(tokens, j, options);
|
|
10915
|
-
children.push(listNode);
|
|
10916
|
-
j = newIndex;
|
|
10917
|
-
} else if (tokens[j].type === "blockquote_open") {
|
|
10918
|
-
const [blockquoteNode, newIndex] = parseBlockquote(tokens, j, options);
|
|
10919
|
-
children.push(blockquoteNode);
|
|
10920
|
-
j = newIndex;
|
|
10921
|
-
} else {
|
|
10922
|
-
const handled = parseBasicBlockToken(tokens, j, options);
|
|
10923
|
-
if (handled) {
|
|
10924
|
-
children.push(handled[0]);
|
|
10925
|
-
j = handled[1];
|
|
10926
|
-
} else j++;
|
|
10927
|
-
}
|
|
10928
|
-
return [{
|
|
10929
|
-
type: "admonition",
|
|
10930
|
-
kind,
|
|
10931
|
-
title,
|
|
10932
|
-
children,
|
|
10933
|
-
raw: `:::${kind} ${title}\n${children.map((c) => c.raw).join("\n")}\n:::`
|
|
10934
|
-
}, j + 1];
|
|
10935
|
-
}
|
|
10936
|
-
|
|
10937
|
-
//#endregion
|
|
10938
|
-
//#region src/parser/node-parsers/container-token-handlers.ts
|
|
10939
|
-
const CONTAINER_REGEX = /^::: ?(warning|info|note|tip|danger|caution|error) ?(.*)$/;
|
|
10940
|
-
function handleContainerOpen(tokens, index, options) {
|
|
10941
|
-
const token = tokens[index];
|
|
10942
|
-
if (token.type !== "container_open") return null;
|
|
10943
|
-
const match = CONTAINER_REGEX.exec(String(token.info ?? ""));
|
|
10944
|
-
if (!match) return null;
|
|
10945
|
-
return parseAdmonition(tokens, index, match, options);
|
|
10946
|
-
}
|
|
10947
|
-
const containerTokenHandlers = {
|
|
10948
|
-
parseContainer: (tokens, index, options) => parseContainer(tokens, index, options),
|
|
10949
|
-
matchAdmonition: handleContainerOpen
|
|
10950
|
-
};
|
|
10951
|
-
|
|
10952
|
-
//#endregion
|
|
10953
|
-
//#region src/parser/node-parsers/blockquote-parser.ts
|
|
10954
|
-
function parseBlockquote(tokens, index, options) {
|
|
10955
|
-
const blockquoteChildren = [];
|
|
10956
|
-
let j = index + 1;
|
|
10957
|
-
while (j < tokens.length && tokens[j].type !== "blockquote_close") switch (tokens[j].type) {
|
|
10958
|
-
case "paragraph_open": {
|
|
10959
|
-
const contentToken = tokens[j + 1];
|
|
10960
|
-
blockquoteChildren.push({
|
|
10961
|
-
type: "paragraph",
|
|
10962
|
-
children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? ""), void 0, {
|
|
10963
|
-
requireClosingStrong: options?.requireClosingStrong,
|
|
10964
|
-
customHtmlTags: options?.customHtmlTags
|
|
10965
|
-
}),
|
|
10966
|
-
raw: String(contentToken.content ?? "")
|
|
10967
|
-
});
|
|
10968
|
-
j += 3;
|
|
10969
|
-
break;
|
|
10970
|
-
}
|
|
10971
|
-
case "bullet_list_open":
|
|
10972
|
-
case "ordered_list_open": {
|
|
10973
|
-
const [listNode, newIndex] = parseList(tokens, j, options);
|
|
10974
|
-
blockquoteChildren.push(listNode);
|
|
10975
|
-
j = newIndex;
|
|
10976
|
-
break;
|
|
10977
|
-
}
|
|
10978
|
-
case "blockquote_open": {
|
|
10979
|
-
const [nestedBlockquote, newIndex] = parseBlockquote(tokens, j, options);
|
|
10980
|
-
blockquoteChildren.push(nestedBlockquote);
|
|
10981
|
-
j = newIndex;
|
|
10982
|
-
break;
|
|
10983
|
-
}
|
|
10984
|
-
default: {
|
|
10985
|
-
const handled = parseCommonBlockToken(tokens, j, options, containerTokenHandlers);
|
|
10986
|
-
if (handled) {
|
|
10987
|
-
blockquoteChildren.push(handled[0]);
|
|
10988
|
-
j = handled[1];
|
|
10989
|
-
} else j++;
|
|
10990
|
-
break;
|
|
10991
|
-
}
|
|
10992
|
-
}
|
|
10993
|
-
return [{
|
|
10994
|
-
type: "blockquote",
|
|
10995
|
-
children: blockquoteChildren,
|
|
10996
|
-
raw: blockquoteChildren.map((child) => child.raw).join("\n")
|
|
10997
|
-
}, j + 1];
|
|
10998
|
-
}
|
|
10999
|
-
|
|
11000
11024
|
//#endregion
|
|
11001
11025
|
//#region src/parser/node-parsers/hardbreak-parser.ts
|
|
11002
11026
|
function parseHardBreak() {
|
|
@@ -11101,19 +11125,22 @@ function stripDanglingHtmlLikeTail(markdown) {
|
|
|
11101
11125
|
return s.slice(0, lastLt);
|
|
11102
11126
|
}
|
|
11103
11127
|
function parseMarkdownToStructure(markdown, md, options = {}) {
|
|
11128
|
+
const isFinal = !!options.final;
|
|
11104
11129
|
let safeMarkdown = (markdown ?? "").toString().replace(/([^\\])\r(ight|ho)/g, "$1\\r$2").replace(/([^\\])\n(abla|eq|ot|exists)/g, "$1\\n$2");
|
|
11105
|
-
if (
|
|
11106
|
-
|
|
11107
|
-
|
|
11108
|
-
|
|
11109
|
-
|
|
11110
|
-
|
|
11111
|
-
|
|
11112
|
-
|
|
11113
|
-
|
|
11114
|
-
|
|
11115
|
-
|
|
11116
|
-
|
|
11130
|
+
if (!isFinal) {
|
|
11131
|
+
if (safeMarkdown.endsWith("- *")) safeMarkdown = safeMarkdown.replace(/- \*$/, "- \\*");
|
|
11132
|
+
if (/(?:^|\n)\s*-\s*$/.test(safeMarkdown)) safeMarkdown = safeMarkdown.replace(/(?:^|\n)\s*-\s*$/, (m) => {
|
|
11133
|
+
return m.startsWith("\n") ? "\n" : "";
|
|
11134
|
+
});
|
|
11135
|
+
else if (/(?:^|\n)\s*--\s*$/.test(safeMarkdown)) safeMarkdown = safeMarkdown.replace(/(?:^|\n)\s*--\s*$/, (m) => {
|
|
11136
|
+
return m.startsWith("\n") ? "\n" : "";
|
|
11137
|
+
});
|
|
11138
|
+
else if (/(?:^|\n)\s*>\s*$/.test(safeMarkdown)) safeMarkdown = safeMarkdown.replace(/(?:^|\n)\s*>\s*$/, (m) => {
|
|
11139
|
+
return m.startsWith("\n") ? "\n" : "";
|
|
11140
|
+
});
|
|
11141
|
+
else if (/\n\s*[*+]\s*$/.test(safeMarkdown)) safeMarkdown = safeMarkdown.replace(/\n\s*[*+]\s*$/, "\n");
|
|
11142
|
+
else if (/\n[[(]\n*$/.test(safeMarkdown)) safeMarkdown = safeMarkdown.replace(/(\n\[|\n\()+\n*$/g, "\n");
|
|
11143
|
+
}
|
|
11117
11144
|
if (options.customHtmlTags?.length) {
|
|
11118
11145
|
const tags = options.customHtmlTags.map((t) => String(t ?? "").trim()).filter(Boolean).map((t) => {
|
|
11119
11146
|
return (t.match(/^[<\s/]*([A-Z][\w-]*)/i)?.[1] ?? "").toLowerCase();
|
|
@@ -11123,8 +11150,8 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
|
|
|
11123
11150
|
safeMarkdown = safeMarkdown.replace(re, "$1$2$2");
|
|
11124
11151
|
}
|
|
11125
11152
|
}
|
|
11126
|
-
safeMarkdown = stripDanglingHtmlLikeTail(safeMarkdown);
|
|
11127
|
-
const tokens = md.parse(safeMarkdown, {});
|
|
11153
|
+
if (!isFinal) safeMarkdown = stripDanglingHtmlLikeTail(safeMarkdown);
|
|
11154
|
+
const tokens = md.parse(safeMarkdown, { __markstreamFinal: isFinal });
|
|
11128
11155
|
if (!tokens || !Array.isArray(tokens)) return [];
|
|
11129
11156
|
const pre = options.preTransformTokens;
|
|
11130
11157
|
const post = options.postTransformTokens;
|
|
@@ -11269,7 +11296,9 @@ function getMarkdown(msgId = `editor-${Date.now()}`, options = {}) {
|
|
|
11269
11296
|
md.use(footnote_plugin);
|
|
11270
11297
|
md.core.ruler.after("block", "mark_fence_closed", (state) => {
|
|
11271
11298
|
const s = state;
|
|
11272
|
-
const
|
|
11299
|
+
const src = s.src;
|
|
11300
|
+
const envFinal = !!s.env?.__markstreamFinal;
|
|
11301
|
+
const lines = src.split(/\r?\n/);
|
|
11273
11302
|
for (const token of s.tokens) {
|
|
11274
11303
|
if (token.type !== "fence" || !token.map || !token.markup) continue;
|
|
11275
11304
|
const openLine = token.map[0];
|
|
@@ -11284,7 +11313,7 @@ function getMarkdown(msgId = `editor-${Date.now()}`, options = {}) {
|
|
|
11284
11313
|
while (i + count < line.length && line[i + count] === marker) count++;
|
|
11285
11314
|
let j = i + count;
|
|
11286
11315
|
while (j < line.length && (line[j] === " " || line[j] === " ")) j++;
|
|
11287
|
-
const closed = endLine > openLine + 1 && count >= minLen && j === line.length;
|
|
11316
|
+
const closed = envFinal ? true : endLine > openLine + 1 && count >= minLen && j === line.length;
|
|
11288
11317
|
const tokenShape = token;
|
|
11289
11318
|
tokenShape.meta = tokenShape.meta ?? {};
|
|
11290
11319
|
tokenShape.meta.unclosed = !closed;
|