stream-markdown-parser 1.0.7 → 1.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/README.md +1 -0
- package/README.zh-CN.md +1 -0
- package/dist/index.cjs +685 -133
- package/dist/index.d.cts +19 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +19 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +685 -133
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -10899,6 +10899,18 @@ function parseLooseInlineAttrs(input) {
|
|
|
10899
10899
|
}
|
|
10900
10900
|
return out;
|
|
10901
10901
|
}
|
|
10902
|
+
function offsetTokenMaps(tokens, lineOffset, maxEndLine) {
|
|
10903
|
+
for (const token of tokens) {
|
|
10904
|
+
const mappedToken = token;
|
|
10905
|
+
const map$1 = mappedToken.map;
|
|
10906
|
+
if (Array.isArray(map$1) && map$1.length >= 2) {
|
|
10907
|
+
const startLine = Number(map$1[0]);
|
|
10908
|
+
const endLine = Number(map$1[1]);
|
|
10909
|
+
if (Number.isFinite(startLine) && Number.isFinite(endLine)) mappedToken.map = [startLine + lineOffset, Math.min(endLine + lineOffset, maxEndLine)];
|
|
10910
|
+
}
|
|
10911
|
+
if (Array.isArray(mappedToken.children)) offsetTokenMaps(mappedToken.children, lineOffset, maxEndLine);
|
|
10912
|
+
}
|
|
10913
|
+
}
|
|
10902
10914
|
function applyContainers(md) {
|
|
10903
10915
|
[
|
|
10904
10916
|
"admonition",
|
|
@@ -10963,6 +10975,7 @@ function applyContainers(md) {
|
|
|
10963
10975
|
if (!found) nextLine = endLine;
|
|
10964
10976
|
const tokenOpen = s.push("vmr_container_open", "div", 1);
|
|
10965
10977
|
tokenOpen.attrSet("class", `vmr-container vmr-container-${name}`);
|
|
10978
|
+
tokenOpen.map = [startLine, found ? nextLine : endLine];
|
|
10966
10979
|
tokenOpen.meta = {
|
|
10967
10980
|
...tokenOpen.meta ?? {},
|
|
10968
10981
|
unclosed: !found && !envFinal
|
|
@@ -10996,6 +11009,7 @@ function applyContainers(md) {
|
|
|
10996
11009
|
if (prevToken) prevToken.raw = innerSrc;
|
|
10997
11010
|
const innerTokens = [];
|
|
10998
11011
|
s.md.block.parse(innerSrc, s.md, s.env, innerTokens);
|
|
11012
|
+
offsetTokenMaps(innerTokens, startLine + 1, startLine + 1 + contentLines.length);
|
|
10999
11013
|
s.tokens.push(...innerTokens);
|
|
11000
11014
|
}
|
|
11001
11015
|
if (found) s.push("vmr_container_close", "div", -1);
|
|
@@ -13508,6 +13522,7 @@ const SPAN_CURLY_RE = /span\{([^}]+)\}/;
|
|
|
13508
13522
|
const OPERATORNAME_SPAN_RE = /\\operatorname\{span\}\{((?:[^{}]|\{[^}]*\})+)\}/;
|
|
13509
13523
|
const SINGLE_BACKSLASH_NEWLINE_RE = /(^|[^\\])\\\r?\n/g;
|
|
13510
13524
|
const ENDING_SINGLE_BACKSLASH_RE = /(^|[^\\])\\$/g;
|
|
13525
|
+
const FACTORIAL_PRECEDING_RE = /[\p{L}\p{M}\p{N}\p{Pe}\p{Pf}'′″‴|‖]/u;
|
|
13511
13526
|
const DEFAULT_MATH_RE = new RegExp(`(${CONTROL_CHARS_CLASS})|(${ESCAPED_KATEX_COMMANDS})\\b`, "g");
|
|
13512
13527
|
const MATH_RE_CACHE = /* @__PURE__ */ new Map();
|
|
13513
13528
|
const BRACE_CMD_RE_CACHE = /* @__PURE__ */ new Map();
|
|
@@ -13547,6 +13562,13 @@ function countUnescapedStrong(s) {
|
|
|
13547
13562
|
while (re.exec(s) !== null) c++;
|
|
13548
13563
|
return c;
|
|
13549
13564
|
}
|
|
13565
|
+
function escapeStandaloneExclamation(value) {
|
|
13566
|
+
return value.replace(/(^|[^\\])!+/gu, (match, prefix) => {
|
|
13567
|
+
if (prefix && FACTORIAL_PRECEDING_RE.test(prefix)) return match;
|
|
13568
|
+
const marks = prefix ? match.slice(prefix.length) : match;
|
|
13569
|
+
return `${prefix}${"\\!".repeat(marks.length)}`;
|
|
13570
|
+
});
|
|
13571
|
+
}
|
|
13550
13572
|
function findLastUnescapedStrongMarker(s) {
|
|
13551
13573
|
const re = /(^|[^\\])(__|\*\*)/g;
|
|
13552
13574
|
let m;
|
|
@@ -13571,7 +13593,7 @@ function normalizeStandaloneBackslashT(s, opts) {
|
|
|
13571
13593
|
}
|
|
13572
13594
|
return m;
|
|
13573
13595
|
});
|
|
13574
|
-
if (escapeExclamation) out = out
|
|
13596
|
+
if (escapeExclamation) out = escapeStandaloneExclamation(out);
|
|
13575
13597
|
let result = out;
|
|
13576
13598
|
const braceCmdRe = getBraceCmdRegex(useDefault, useDefault ? void 0 : commands);
|
|
13577
13599
|
result = result.replace(braceCmdRe, (_m, p1, p2) => `${p1}\\${p2}{`);
|
|
@@ -16863,6 +16885,74 @@ function parseInlineTokens(tokens, raw, pPreToken, options) {
|
|
|
16863
16885
|
return result;
|
|
16864
16886
|
}
|
|
16865
16887
|
|
|
16888
|
+
//#endregion
|
|
16889
|
+
//#region src/parser/node-source-map.ts
|
|
16890
|
+
function mapSourceLineRange(startLine, endLine, options) {
|
|
16891
|
+
const mapper = options?.__sourceLineMapper;
|
|
16892
|
+
if (!mapper) return {
|
|
16893
|
+
startLine,
|
|
16894
|
+
endLine
|
|
16895
|
+
};
|
|
16896
|
+
const mappedStartRange = mapper(startLine);
|
|
16897
|
+
const mappedEndLine = endLine > startLine ? mapper(endLine - 1).endLine : mapper(endLine).startLine;
|
|
16898
|
+
return {
|
|
16899
|
+
startLine: mappedStartRange.startLine,
|
|
16900
|
+
endLine: Math.max(mappedStartRange.startLine, mappedEndLine)
|
|
16901
|
+
};
|
|
16902
|
+
}
|
|
16903
|
+
function lineAtOffset(source, offset) {
|
|
16904
|
+
const target = Math.max(0, Math.min(source.length, Math.trunc(offset)));
|
|
16905
|
+
let line = 0;
|
|
16906
|
+
for (let i = 0; i < target; i++) if (source[i] === "\n") line++;
|
|
16907
|
+
return line;
|
|
16908
|
+
}
|
|
16909
|
+
function sourceLineRangeFromOffsets(source, start, end) {
|
|
16910
|
+
const startIndex = Math.max(0, Math.min(source.length, Math.trunc(start)));
|
|
16911
|
+
const endIndex = Math.max(startIndex, Math.min(source.length, Math.trunc(end)));
|
|
16912
|
+
const startLine = lineAtOffset(source, startIndex);
|
|
16913
|
+
let endLine = lineAtOffset(source, endIndex);
|
|
16914
|
+
if (endIndex > startIndex && source[endIndex - 1] !== "\n") endLine++;
|
|
16915
|
+
return {
|
|
16916
|
+
startLine,
|
|
16917
|
+
endLine
|
|
16918
|
+
};
|
|
16919
|
+
}
|
|
16920
|
+
function createSourceMapFromOffsets(source, start, end, options) {
|
|
16921
|
+
const range = sourceLineRangeFromOffsets(source, start, end);
|
|
16922
|
+
return mapSourceLineRange(range.startLine, range.endLine, options);
|
|
16923
|
+
}
|
|
16924
|
+
function readSourceMap(token, options) {
|
|
16925
|
+
const map$1 = token?.map;
|
|
16926
|
+
if (!Array.isArray(map$1) || map$1.length < 2) return null;
|
|
16927
|
+
const startLine = Number(map$1[0]);
|
|
16928
|
+
const endLine = Number(map$1[1]);
|
|
16929
|
+
if (!Number.isFinite(startLine) || !Number.isFinite(endLine)) return null;
|
|
16930
|
+
return mapSourceLineRange(startLine, endLine, options);
|
|
16931
|
+
}
|
|
16932
|
+
function applyNodeSourceMap(node, token, options) {
|
|
16933
|
+
if (!options?.includeSourceMap) return node;
|
|
16934
|
+
const sourceMap = readSourceMap(token, options);
|
|
16935
|
+
if (!sourceMap) return node;
|
|
16936
|
+
node.sourceMap = sourceMap;
|
|
16937
|
+
if (node.type === "code_block") {
|
|
16938
|
+
const codeNode = node;
|
|
16939
|
+
codeNode.startLine = sourceMap.startLine;
|
|
16940
|
+
codeNode.endLine = sourceMap.endLine;
|
|
16941
|
+
}
|
|
16942
|
+
return node;
|
|
16943
|
+
}
|
|
16944
|
+
function applyNodeSourceMapRange(node, token, endLine, options) {
|
|
16945
|
+
if (!options?.includeSourceMap) return node;
|
|
16946
|
+
const map$1 = token?.map;
|
|
16947
|
+
if (!Array.isArray(map$1) || map$1.length < 2) return node;
|
|
16948
|
+
const startLine = Number(map$1[0]);
|
|
16949
|
+
const tokenEndLine = Number(map$1[1]);
|
|
16950
|
+
const rangeEndLine = Number(endLine);
|
|
16951
|
+
if (!Number.isFinite(startLine) || !Number.isFinite(tokenEndLine) || !Number.isFinite(rangeEndLine)) return node;
|
|
16952
|
+
node.sourceMap = mapSourceLineRange(startLine, Math.max(tokenEndLine, rangeEndLine), options);
|
|
16953
|
+
return node;
|
|
16954
|
+
}
|
|
16955
|
+
|
|
16866
16956
|
//#endregion
|
|
16867
16957
|
//#region src/parser/node-parsers/list-parser.ts
|
|
16868
16958
|
function trimInlineTokenTail(token) {
|
|
@@ -16947,11 +17037,13 @@ function parseList(tokens, index, options) {
|
|
|
16947
17037
|
trimInlineTokenTail(contentToken);
|
|
16948
17038
|
}
|
|
16949
17039
|
const paragraphRaw = String(contentToken.content ?? "");
|
|
16950
|
-
|
|
17040
|
+
const paragraphNode = {
|
|
16951
17041
|
type: "paragraph",
|
|
16952
17042
|
children: parseInlineTokens(contentToken.children || [], paragraphRaw, preToken, linkifyContext.options()),
|
|
16953
17043
|
raw: paragraphRaw
|
|
16954
|
-
}
|
|
17044
|
+
};
|
|
17045
|
+
if (options?.includeSourceMap) applyNodeSourceMap(paragraphNode, tokens[k], options);
|
|
17046
|
+
itemChildren.push(paragraphNode);
|
|
16955
17047
|
linkifyContext.remember(paragraphRaw);
|
|
16956
17048
|
k += 3;
|
|
16957
17049
|
} else if (tokens[k].type === "blockquote_open") {
|
|
@@ -16972,14 +17064,16 @@ function parseList(tokens, index, options) {
|
|
|
16972
17064
|
k = handled[1];
|
|
16973
17065
|
} else k += 1;
|
|
16974
17066
|
}
|
|
16975
|
-
|
|
17067
|
+
const listItemNode = {
|
|
16976
17068
|
type: "list_item",
|
|
16977
17069
|
children: itemChildren,
|
|
16978
17070
|
raw: itemChildren.map((child) => child.raw).join("")
|
|
16979
|
-
}
|
|
17071
|
+
};
|
|
17072
|
+
if (options?.includeSourceMap) applyNodeSourceMap(listItemNode, tokens[j], options);
|
|
17073
|
+
listItems.push(listItemNode);
|
|
16980
17074
|
j = k + 1;
|
|
16981
17075
|
} else j += 1;
|
|
16982
|
-
|
|
17076
|
+
const listNode = {
|
|
16983
17077
|
type: "list",
|
|
16984
17078
|
ordered: token.type === "ordered_list_open",
|
|
16985
17079
|
start: (() => {
|
|
@@ -16993,7 +17087,9 @@ function parseList(tokens, index, options) {
|
|
|
16993
17087
|
})(),
|
|
16994
17088
|
items: listItems,
|
|
16995
17089
|
raw: listItems.map((item) => item.raw).join("\n")
|
|
16996
|
-
}
|
|
17090
|
+
};
|
|
17091
|
+
if (options?.includeSourceMap) applyNodeSourceMap(listNode, token, options);
|
|
17092
|
+
return [listNode, j + 1];
|
|
16997
17093
|
}
|
|
16998
17094
|
|
|
16999
17095
|
//#endregion
|
|
@@ -17012,17 +17108,20 @@ function parseAdmonition(tokens, index, match, options) {
|
|
|
17012
17108
|
children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? ""), void 0, linkifyContext.options()),
|
|
17013
17109
|
raw: String(contentToken.content ?? "")
|
|
17014
17110
|
};
|
|
17111
|
+
if (options?.includeSourceMap) applyNodeSourceMap(paragraphNode, tokens[j], options);
|
|
17015
17112
|
admonitionChildren.push(paragraphNode);
|
|
17016
17113
|
linkifyContext.remember(paragraphNode.raw);
|
|
17017
17114
|
}
|
|
17018
17115
|
j += 3;
|
|
17019
17116
|
} else if (tokens[j].type === "bullet_list_open" || tokens[j].type === "ordered_list_open") {
|
|
17020
17117
|
const [listNode, newIndex] = parseList(tokens, j, linkifyContext.options());
|
|
17118
|
+
if (options?.includeSourceMap) applyNodeSourceMap(listNode, tokens[j], options);
|
|
17021
17119
|
admonitionChildren.push(listNode);
|
|
17022
17120
|
linkifyContext.remember(listNode.raw);
|
|
17023
17121
|
j = newIndex;
|
|
17024
17122
|
} else if (tokens[j].type === "blockquote_open") {
|
|
17025
17123
|
const [blockquoteNode, newIndex] = parseBlockquote(tokens, j, linkifyContext.options());
|
|
17124
|
+
if (options?.includeSourceMap) applyNodeSourceMap(blockquoteNode, tokens[j], options);
|
|
17026
17125
|
admonitionChildren.push(blockquoteNode);
|
|
17027
17126
|
linkifyContext.remember(blockquoteNode.raw);
|
|
17028
17127
|
j = newIndex;
|
|
@@ -17110,17 +17209,20 @@ function parseContainer(tokens, index, options) {
|
|
|
17110
17209
|
children: parseInlineTokens((i !== -1 ? childrenArr.slice(0, i) : childrenArr) || [], void 0, void 0, linkifyContext.options()),
|
|
17111
17210
|
raw: String(contentToken.content ?? "").replace(/\n:+$/, "").replace(/\n\s*:::\s*$/, "")
|
|
17112
17211
|
};
|
|
17212
|
+
if (options?.includeSourceMap) applyNodeSourceMap(paragraphNode, tokens[j], options);
|
|
17113
17213
|
children.push(paragraphNode);
|
|
17114
17214
|
linkifyContext.remember(paragraphNode.raw);
|
|
17115
17215
|
}
|
|
17116
17216
|
j += 3;
|
|
17117
17217
|
} else if (tokens[j].type === "bullet_list_open" || tokens[j].type === "ordered_list_open") {
|
|
17118
17218
|
const [listNode, newIndex] = parseList(tokens, j, linkifyContext.options());
|
|
17219
|
+
if (options?.includeSourceMap) applyNodeSourceMap(listNode, tokens[j], options);
|
|
17119
17220
|
children.push(listNode);
|
|
17120
17221
|
linkifyContext.remember(listNode.raw);
|
|
17121
17222
|
j = newIndex;
|
|
17122
17223
|
} else if (tokens[j].type === "blockquote_open") {
|
|
17123
17224
|
const [blockquoteNode, newIndex] = parseBlockquote(tokens, j, linkifyContext.options());
|
|
17225
|
+
if (options?.includeSourceMap) applyNodeSourceMap(blockquoteNode, tokens[j], options);
|
|
17124
17226
|
children.push(blockquoteNode);
|
|
17125
17227
|
linkifyContext.remember(blockquoteNode.raw);
|
|
17126
17228
|
j = newIndex;
|
|
@@ -17162,49 +17264,55 @@ function parseBlockquote(tokens, index, options) {
|
|
|
17162
17264
|
const blockquoteChildren = [];
|
|
17163
17265
|
const linkifyContext = createLinkifyDemotionContextTracker(options, true);
|
|
17164
17266
|
let j = index + 1;
|
|
17165
|
-
while (j < tokens.length && tokens[j].type !== "blockquote_close")
|
|
17166
|
-
|
|
17167
|
-
|
|
17168
|
-
|
|
17169
|
-
|
|
17170
|
-
|
|
17171
|
-
|
|
17172
|
-
|
|
17173
|
-
|
|
17174
|
-
|
|
17175
|
-
|
|
17176
|
-
|
|
17177
|
-
|
|
17178
|
-
|
|
17179
|
-
|
|
17180
|
-
|
|
17181
|
-
|
|
17182
|
-
|
|
17183
|
-
|
|
17184
|
-
|
|
17185
|
-
|
|
17186
|
-
|
|
17187
|
-
|
|
17188
|
-
|
|
17189
|
-
|
|
17190
|
-
|
|
17191
|
-
|
|
17192
|
-
|
|
17193
|
-
|
|
17194
|
-
|
|
17195
|
-
|
|
17196
|
-
|
|
17197
|
-
linkifyContext.
|
|
17198
|
-
|
|
17199
|
-
|
|
17200
|
-
|
|
17267
|
+
while (j < tokens.length && tokens[j].type !== "blockquote_close") {
|
|
17268
|
+
const token = tokens[j];
|
|
17269
|
+
switch (token.type) {
|
|
17270
|
+
case "paragraph_open": {
|
|
17271
|
+
const contentToken = tokens[j + 1];
|
|
17272
|
+
const paragraphNode = {
|
|
17273
|
+
type: "paragraph",
|
|
17274
|
+
children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? ""), void 0, linkifyContext.options()),
|
|
17275
|
+
raw: String(contentToken.content ?? "")
|
|
17276
|
+
};
|
|
17277
|
+
if (options?.includeSourceMap) applyNodeSourceMap(paragraphNode, token, options);
|
|
17278
|
+
blockquoteChildren.push(paragraphNode);
|
|
17279
|
+
linkifyContext.remember(paragraphNode.raw);
|
|
17280
|
+
j += 3;
|
|
17281
|
+
break;
|
|
17282
|
+
}
|
|
17283
|
+
case "bullet_list_open":
|
|
17284
|
+
case "ordered_list_open": {
|
|
17285
|
+
const [listNode, newIndex] = parseList(tokens, j, linkifyContext.options());
|
|
17286
|
+
blockquoteChildren.push(listNode);
|
|
17287
|
+
linkifyContext.remember(listNode.raw);
|
|
17288
|
+
j = newIndex;
|
|
17289
|
+
break;
|
|
17290
|
+
}
|
|
17291
|
+
case "blockquote_open": {
|
|
17292
|
+
const [nestedBlockquote, newIndex] = parseBlockquote(tokens, j, linkifyContext.options());
|
|
17293
|
+
blockquoteChildren.push(nestedBlockquote);
|
|
17294
|
+
linkifyContext.remember(nestedBlockquote.raw);
|
|
17295
|
+
j = newIndex;
|
|
17296
|
+
break;
|
|
17297
|
+
}
|
|
17298
|
+
default: {
|
|
17299
|
+
const handled = parseCommonBlockToken(tokens, j, linkifyContext.options(), containerTokenHandlers);
|
|
17300
|
+
if (handled) {
|
|
17301
|
+
blockquoteChildren.push(handled[0]);
|
|
17302
|
+
linkifyContext.remember(handled[0].raw);
|
|
17303
|
+
j = handled[1];
|
|
17304
|
+
} else j++;
|
|
17305
|
+
break;
|
|
17306
|
+
}
|
|
17201
17307
|
}
|
|
17202
17308
|
}
|
|
17203
|
-
|
|
17309
|
+
const blockquoteNode = {
|
|
17204
17310
|
type: "blockquote",
|
|
17205
17311
|
children: blockquoteChildren,
|
|
17206
17312
|
raw: blockquoteChildren.map((child) => child.raw).join("\n")
|
|
17207
|
-
}
|
|
17313
|
+
};
|
|
17314
|
+
if (options?.includeSourceMap) applyNodeSourceMap(blockquoteNode, tokens[index], options);
|
|
17315
|
+
return [blockquoteNode, j + 1];
|
|
17208
17316
|
}
|
|
17209
17317
|
|
|
17210
17318
|
//#endregion
|
|
@@ -17562,17 +17670,20 @@ function parseVmrContainer(tokens, index, options) {
|
|
|
17562
17670
|
children: parseInlineTokens(contentToken.children || [], void 0, void 0, linkifyContext.options()),
|
|
17563
17671
|
raw: String(contentToken.content ?? "")
|
|
17564
17672
|
};
|
|
17673
|
+
if (options?.includeSourceMap) applyNodeSourceMap(paragraphNode, tokens[j], options);
|
|
17565
17674
|
children.push(paragraphNode);
|
|
17566
17675
|
linkifyContext.remember(paragraphNode.raw);
|
|
17567
17676
|
}
|
|
17568
17677
|
j += 3;
|
|
17569
17678
|
} else if (tokens[j].type === "bullet_list_open" || tokens[j].type === "ordered_list_open") {
|
|
17570
17679
|
const [listNode, newIndex] = parseList(tokens, j, linkifyContext.options());
|
|
17680
|
+
if (options?.includeSourceMap) applyNodeSourceMap(listNode, tokens[j], options);
|
|
17571
17681
|
children.push(listNode);
|
|
17572
17682
|
linkifyContext.remember(listNode.raw);
|
|
17573
17683
|
j = newIndex;
|
|
17574
17684
|
} else if (tokens[j].type === "blockquote_open") {
|
|
17575
17685
|
const [blockquoteNode, newIndex] = parseBlockquote(tokens, j, linkifyContext.options());
|
|
17686
|
+
if (options?.includeSourceMap) applyNodeSourceMap(blockquoteNode, tokens[j], options);
|
|
17576
17687
|
children.push(blockquoteNode);
|
|
17577
17688
|
linkifyContext.remember(blockquoteNode.raw);
|
|
17578
17689
|
j = newIndex;
|
|
@@ -17603,6 +17714,14 @@ function parseVmrContainer(tokens, index, options) {
|
|
|
17603
17714
|
raw
|
|
17604
17715
|
}, hasCloseToken ? j + 1 : j];
|
|
17605
17716
|
}
|
|
17717
|
+
function applyPairedBlockSourceMap(node, openToken, closeToken, options) {
|
|
17718
|
+
if (closeToken?.type.endsWith("_close")) {
|
|
17719
|
+
let endLine = Array.isArray(closeToken.map) ? Number(closeToken.map[1]) : NaN;
|
|
17720
|
+
if (!Number.isFinite(endLine)) endLine = Array.isArray(openToken.map) ? Number(openToken.map[1]) + 1 : NaN;
|
|
17721
|
+
return applyNodeSourceMapRange(node, openToken, endLine, options);
|
|
17722
|
+
}
|
|
17723
|
+
return applyNodeSourceMap(node, openToken, options);
|
|
17724
|
+
}
|
|
17606
17725
|
function stripWrapperNewlines(s) {
|
|
17607
17726
|
return s.replace(/^\r?\n/, "").replace(/\r?\n$/, "");
|
|
17608
17727
|
}
|
|
@@ -17661,6 +17780,7 @@ function findNextCustomHtmlBlockFromSource(source, tag, startIndex) {
|
|
|
17661
17780
|
const end = openEnd + 1;
|
|
17662
17781
|
return {
|
|
17663
17782
|
raw: source.slice(openStart, end),
|
|
17783
|
+
start: openStart,
|
|
17664
17784
|
end
|
|
17665
17785
|
};
|
|
17666
17786
|
}
|
|
@@ -17678,6 +17798,7 @@ function findNextCustomHtmlBlockFromSource(source, tag, startIndex) {
|
|
|
17678
17798
|
const lt = source.indexOf("<", i);
|
|
17679
17799
|
if (lt === -1) return {
|
|
17680
17800
|
raw: source.slice(openStart),
|
|
17801
|
+
start: openStart,
|
|
17681
17802
|
end: source.length
|
|
17682
17803
|
};
|
|
17683
17804
|
if (isCloseAt(lt)) {
|
|
@@ -17688,6 +17809,7 @@ function findNextCustomHtmlBlockFromSource(source, tag, startIndex) {
|
|
|
17688
17809
|
const end = gt + 1;
|
|
17689
17810
|
return {
|
|
17690
17811
|
raw: source.slice(openStart, end),
|
|
17812
|
+
start: openStart,
|
|
17691
17813
|
end
|
|
17692
17814
|
};
|
|
17693
17815
|
}
|
|
@@ -17705,6 +17827,7 @@ function findNextCustomHtmlBlockFromSource(source, tag, startIndex) {
|
|
|
17705
17827
|
}
|
|
17706
17828
|
return {
|
|
17707
17829
|
raw: source.slice(openStart),
|
|
17830
|
+
start: openStart,
|
|
17708
17831
|
end: source.length
|
|
17709
17832
|
};
|
|
17710
17833
|
}
|
|
@@ -17723,17 +17846,34 @@ function lineToIndex(source, line) {
|
|
|
17723
17846
|
}
|
|
17724
17847
|
function parseBasicBlockToken(tokens, index, options) {
|
|
17725
17848
|
const token = tokens[index];
|
|
17849
|
+
const includeSourceMap = options?.includeSourceMap === true;
|
|
17726
17850
|
switch (token.type) {
|
|
17727
|
-
case "heading_open":
|
|
17728
|
-
|
|
17729
|
-
|
|
17730
|
-
|
|
17851
|
+
case "heading_open": {
|
|
17852
|
+
const node = parseHeading(tokens, index, options);
|
|
17853
|
+
if (includeSourceMap) applyNodeSourceMap(node, token, options);
|
|
17854
|
+
return [node, index + 3];
|
|
17855
|
+
}
|
|
17856
|
+
case "code_block": {
|
|
17857
|
+
const node = parseCodeBlock(token);
|
|
17858
|
+
if (includeSourceMap) applyNodeSourceMap(node, token, options);
|
|
17859
|
+
return [node, index + 1];
|
|
17860
|
+
}
|
|
17861
|
+
case "fence": {
|
|
17862
|
+
const node = parseFenceToken(token);
|
|
17863
|
+
if (includeSourceMap) applyNodeSourceMap(node, token, options);
|
|
17864
|
+
return [node, index + 1];
|
|
17865
|
+
}
|
|
17866
|
+
case "math_block": {
|
|
17867
|
+
const node = parseMathBlock(token);
|
|
17868
|
+
if (includeSourceMap) applyNodeSourceMap(node, token, options);
|
|
17869
|
+
return [node, index + 1];
|
|
17870
|
+
}
|
|
17731
17871
|
case "html_block": {
|
|
17732
17872
|
const htmlBlockNode = parseHtmlBlock(token);
|
|
17733
17873
|
const tagSets = htmlBlockNode.tag ? getHtmlTagSets(options?.customHtmlTags) : null;
|
|
17734
17874
|
if (htmlBlockNode.tag && htmlBlockNode.loading && tagSets && !tagSets.allowedTagSet.has(htmlBlockNode.tag)) {
|
|
17735
17875
|
const content = String(token.content ?? "").replace(/\n+$/, "");
|
|
17736
|
-
|
|
17876
|
+
const paragraphNode = {
|
|
17737
17877
|
type: "paragraph",
|
|
17738
17878
|
children: content ? [{
|
|
17739
17879
|
type: "text",
|
|
@@ -17741,7 +17881,9 @@ function parseBasicBlockToken(tokens, index, options) {
|
|
|
17741
17881
|
raw: content
|
|
17742
17882
|
}] : [],
|
|
17743
17883
|
raw: content
|
|
17744
|
-
}
|
|
17884
|
+
};
|
|
17885
|
+
if (includeSourceMap) applyNodeSourceMap(paragraphNode, token, options);
|
|
17886
|
+
return [paragraphNode, index + 1];
|
|
17745
17887
|
}
|
|
17746
17888
|
if (htmlBlockNode.tag && tagSets?.customTagSet?.has(htmlBlockNode.tag)) {
|
|
17747
17889
|
const tag = htmlBlockNode.tag;
|
|
@@ -17770,30 +17912,41 @@ function parseBasicBlockToken(tokens, index, options) {
|
|
|
17770
17912
|
attrs.push([name, value]);
|
|
17771
17913
|
}
|
|
17772
17914
|
const loading = !options?.final && !selfClosing && closeRange == null;
|
|
17773
|
-
|
|
17915
|
+
const customNode = {
|
|
17774
17916
|
type: tag,
|
|
17775
17917
|
tag,
|
|
17776
17918
|
content: stripWrapperNewlines(inner),
|
|
17777
17919
|
raw: String(fromSource?.raw ?? htmlBlockNode.raw ?? rawHtml),
|
|
17778
17920
|
loading,
|
|
17779
17921
|
attrs: attrs.length ? attrs : void 0
|
|
17780
|
-
}
|
|
17922
|
+
};
|
|
17923
|
+
if (includeSourceMap) if (fromSource) customNode.sourceMap = createSourceMapFromOffsets(source, fromSource.start, fromSource.end, options);
|
|
17924
|
+
else applyNodeSourceMap(customNode, token, options);
|
|
17925
|
+
return [customNode, index + 1];
|
|
17781
17926
|
}
|
|
17927
|
+
if (includeSourceMap) applyNodeSourceMap(htmlBlockNode, token, options);
|
|
17782
17928
|
return [htmlBlockNode, index + 1];
|
|
17783
17929
|
}
|
|
17784
17930
|
case "table_open": {
|
|
17785
17931
|
const [tableNode, newIndex] = parseTable(tokens, index, options);
|
|
17932
|
+
if (includeSourceMap) applyNodeSourceMap(tableNode, token, options);
|
|
17786
17933
|
return [tableNode, newIndex];
|
|
17787
17934
|
}
|
|
17788
17935
|
case "dl_open": {
|
|
17789
17936
|
const [definitionListNode, newIndex] = parseDefinitionList(tokens, index, options);
|
|
17937
|
+
if (includeSourceMap) applyNodeSourceMap(definitionListNode, token, options);
|
|
17790
17938
|
return [definitionListNode, newIndex];
|
|
17791
17939
|
}
|
|
17792
17940
|
case "footnote_open": {
|
|
17793
17941
|
const [footnoteNode, newIndex] = parseFootnote(tokens, index, options);
|
|
17942
|
+
if (includeSourceMap) applyNodeSourceMap(footnoteNode, token, options);
|
|
17794
17943
|
return [footnoteNode, newIndex];
|
|
17795
17944
|
}
|
|
17796
|
-
case "hr":
|
|
17945
|
+
case "hr": {
|
|
17946
|
+
const node = parseThematicBreak();
|
|
17947
|
+
if (includeSourceMap) applyNodeSourceMap(node, token, options);
|
|
17948
|
+
return [node, index + 1];
|
|
17949
|
+
}
|
|
17797
17950
|
default: break;
|
|
17798
17951
|
}
|
|
17799
17952
|
return null;
|
|
@@ -17801,7 +17954,9 @@ function parseBasicBlockToken(tokens, index, options) {
|
|
|
17801
17954
|
function parseCommonBlockToken(tokens, index, options, handlers) {
|
|
17802
17955
|
const basicResult = parseBasicBlockToken(tokens, index, options);
|
|
17803
17956
|
if (basicResult) return basicResult;
|
|
17804
|
-
|
|
17957
|
+
const token = tokens[index];
|
|
17958
|
+
const includeSourceMap = options?.includeSourceMap === true;
|
|
17959
|
+
switch (token.type) {
|
|
17805
17960
|
case "container_warning_open":
|
|
17806
17961
|
case "container_info_open":
|
|
17807
17962
|
case "container_note_open":
|
|
@@ -17809,15 +17964,26 @@ function parseCommonBlockToken(tokens, index, options, handlers) {
|
|
|
17809
17964
|
case "container_danger_open":
|
|
17810
17965
|
case "container_caution_open":
|
|
17811
17966
|
case "container_error_open":
|
|
17812
|
-
if (handlers?.parseContainer)
|
|
17967
|
+
if (handlers?.parseContainer) {
|
|
17968
|
+
const result = handlers.parseContainer(tokens, index, options);
|
|
17969
|
+
if (includeSourceMap) applyPairedBlockSourceMap(result[0], token, tokens[result[1] - 1], options);
|
|
17970
|
+
return result;
|
|
17971
|
+
}
|
|
17813
17972
|
break;
|
|
17814
17973
|
case "container_open":
|
|
17815
17974
|
if (handlers?.matchAdmonition) {
|
|
17816
17975
|
const result = handlers.matchAdmonition(tokens, index, options);
|
|
17817
|
-
if (result)
|
|
17976
|
+
if (result) {
|
|
17977
|
+
if (includeSourceMap) applyPairedBlockSourceMap(result[0], token, tokens[result[1] - 1], options);
|
|
17978
|
+
return result;
|
|
17979
|
+
}
|
|
17818
17980
|
}
|
|
17819
17981
|
break;
|
|
17820
|
-
case "vmr_container_open":
|
|
17982
|
+
case "vmr_container_open": {
|
|
17983
|
+
const result = parseVmrContainer(tokens, index, options);
|
|
17984
|
+
if (includeSourceMap) applyPairedBlockSourceMap(result[0], token, tokens[result[1] - 1], options);
|
|
17985
|
+
return result;
|
|
17986
|
+
}
|
|
17821
17987
|
default: break;
|
|
17822
17988
|
}
|
|
17823
17989
|
return null;
|
|
@@ -17866,6 +18032,15 @@ function finishTimedParse(result, timing, startedAt) {
|
|
|
17866
18032
|
if (timing) addTiming(timing, "parseMarkdownToStructureTotalMs", getParserNow() - startedAt);
|
|
17867
18033
|
return result;
|
|
17868
18034
|
}
|
|
18035
|
+
function applyPostTransformNodes(nodes, options) {
|
|
18036
|
+
const transform = options.postTransformNodes;
|
|
18037
|
+
if (typeof transform !== "function") return nodes;
|
|
18038
|
+
const transformed = transform(nodes);
|
|
18039
|
+
return Array.isArray(transformed) ? transformed : nodes;
|
|
18040
|
+
}
|
|
18041
|
+
function finishParsedNodes(result, options, timing, startedAt) {
|
|
18042
|
+
return finishTimedParse(applyPostTransformNodes(result, options), timing, startedAt);
|
|
18043
|
+
}
|
|
17869
18044
|
function processTokensWithTiming(tokens, options, timing) {
|
|
17870
18045
|
if (!timing) return processTokens(tokens, options);
|
|
17871
18046
|
const startedAt = getParserNow();
|
|
@@ -18031,8 +18206,24 @@ function shouldResetTopLevelStreamCacheForFinalAutoParse(md, options) {
|
|
|
18031
18206
|
function clearTolerantMathBoundaryStreamCache(md) {
|
|
18032
18207
|
tolerantMathBoundaryStreamCache.delete(md);
|
|
18033
18208
|
}
|
|
18034
|
-
function
|
|
18209
|
+
function createExplicitBracketMathContext() {
|
|
18210
|
+
return {
|
|
18211
|
+
fenceChar: "",
|
|
18212
|
+
fenceInBlockquote: false,
|
|
18213
|
+
fenceInList: false,
|
|
18214
|
+
fenceLen: 0,
|
|
18215
|
+
fenceListIndent: 0,
|
|
18216
|
+
inFence: false,
|
|
18217
|
+
inMath: false,
|
|
18218
|
+
listContentIndent: null
|
|
18219
|
+
};
|
|
18220
|
+
}
|
|
18221
|
+
function cloneExplicitBracketMathContext(context) {
|
|
18222
|
+
return { ...context };
|
|
18223
|
+
}
|
|
18224
|
+
function setTolerantMathBoundaryStreamCache(md, source, key, explicitBracketMath = scanExplicitBracketMathStreamState(source).state) {
|
|
18035
18225
|
tolerantMathBoundaryStreamCache.set(md, {
|
|
18226
|
+
explicitBracketMath,
|
|
18036
18227
|
source,
|
|
18037
18228
|
key,
|
|
18038
18229
|
pendingCandidate: key === null && mayContainTolerantMathBlockBoundaryOpener(source)
|
|
@@ -18048,12 +18239,235 @@ function sourceEndsWithCompleteTolerantBoundaryOpener(source) {
|
|
|
18048
18239
|
}
|
|
18049
18240
|
function appendedChunkMayAffectTolerantMathBoundary(previousSource, appended) {
|
|
18050
18241
|
if (!appended) return false;
|
|
18051
|
-
if (appended.includes("$$") || appended.includes("\\[")
|
|
18242
|
+
if (appended.includes("$$") || appended.includes("\\[")) return true;
|
|
18052
18243
|
if (previousSource.endsWith("$") && appended[0] === "$") return true;
|
|
18053
|
-
if (previousSource.endsWith("\\") &&
|
|
18244
|
+
if (previousSource.endsWith("\\") && appended[0] === "[") return true;
|
|
18054
18245
|
if (sourceEndsWithCompleteTolerantBoundaryOpener(previousSource) && /[\r\n]/.test(appended)) return true;
|
|
18055
18246
|
return false;
|
|
18056
18247
|
}
|
|
18248
|
+
function isEscapedDelimiterAt(source, index) {
|
|
18249
|
+
let cursor = index - 1;
|
|
18250
|
+
let backslashes = 0;
|
|
18251
|
+
while (cursor >= 0 && source[cursor] === "\\") {
|
|
18252
|
+
backslashes++;
|
|
18253
|
+
cursor--;
|
|
18254
|
+
}
|
|
18255
|
+
return backslashes % 2 === 1;
|
|
18256
|
+
}
|
|
18257
|
+
function isIndentWhitespace(ch) {
|
|
18258
|
+
return ch === " " || ch === " ";
|
|
18259
|
+
}
|
|
18260
|
+
function advanceMarkdownIndentColumn(column, ch) {
|
|
18261
|
+
return ch === " " ? column + 1 : column + 4 - column % 4;
|
|
18262
|
+
}
|
|
18263
|
+
function getMarkdownIndent(line) {
|
|
18264
|
+
let index = 0;
|
|
18265
|
+
let column = 0;
|
|
18266
|
+
while (index < line.length && isIndentWhitespace(line[index])) {
|
|
18267
|
+
column = advanceMarkdownIndentColumn(column, line[index]);
|
|
18268
|
+
index++;
|
|
18269
|
+
}
|
|
18270
|
+
return {
|
|
18271
|
+
index,
|
|
18272
|
+
column
|
|
18273
|
+
};
|
|
18274
|
+
}
|
|
18275
|
+
function consumeMarkdownIndent(line) {
|
|
18276
|
+
const indent = getMarkdownIndent(line);
|
|
18277
|
+
return indent.column > 3 ? null : indent;
|
|
18278
|
+
}
|
|
18279
|
+
function parseMarkdownFenceMarker(line) {
|
|
18280
|
+
const indent = consumeMarkdownIndent(line);
|
|
18281
|
+
if (!indent) return null;
|
|
18282
|
+
const index = indent.index;
|
|
18283
|
+
const markerChar = line[index];
|
|
18284
|
+
if (markerChar !== "`" && markerChar !== "~") return null;
|
|
18285
|
+
let markerEnd = index;
|
|
18286
|
+
while (markerEnd < line.length && line[markerEnd] === markerChar) markerEnd++;
|
|
18287
|
+
const markerLen = markerEnd - index;
|
|
18288
|
+
if (markerLen < 3) return null;
|
|
18289
|
+
const rest = line.slice(markerEnd);
|
|
18290
|
+
if (markerChar === "`" && rest.includes("`")) return null;
|
|
18291
|
+
return {
|
|
18292
|
+
markerChar,
|
|
18293
|
+
markerLen,
|
|
18294
|
+
rest
|
|
18295
|
+
};
|
|
18296
|
+
}
|
|
18297
|
+
function stripMarkdownListPrefix(line) {
|
|
18298
|
+
const indent = consumeMarkdownIndent(line);
|
|
18299
|
+
if (!indent) return null;
|
|
18300
|
+
const rest = line.slice(indent.index);
|
|
18301
|
+
const marker = /^(?:[-+*]|\d{1,9}[.)])(?=[\t ]|$)/.exec(rest)?.[0];
|
|
18302
|
+
if (!marker) return null;
|
|
18303
|
+
let index = indent.index + marker.length;
|
|
18304
|
+
let column = indent.column + marker.length;
|
|
18305
|
+
if (!isIndentWhitespace(line[index])) return null;
|
|
18306
|
+
while (index < line.length && isIndentWhitespace(line[index])) {
|
|
18307
|
+
column = advanceMarkdownIndentColumn(column, line[index]);
|
|
18308
|
+
index++;
|
|
18309
|
+
}
|
|
18310
|
+
return {
|
|
18311
|
+
content: line.slice(index),
|
|
18312
|
+
contentIndent: column
|
|
18313
|
+
};
|
|
18314
|
+
}
|
|
18315
|
+
function stripMarkdownBlockquotePrefix(line) {
|
|
18316
|
+
let rest = line;
|
|
18317
|
+
let saw = false;
|
|
18318
|
+
while (true) {
|
|
18319
|
+
const indent = consumeMarkdownIndent(rest);
|
|
18320
|
+
if (!indent) return saw ? rest : null;
|
|
18321
|
+
let index = indent.index;
|
|
18322
|
+
if (rest[index] !== ">") return saw ? rest : null;
|
|
18323
|
+
saw = true;
|
|
18324
|
+
index++;
|
|
18325
|
+
if (rest[index] === " " || rest[index] === " ") index++;
|
|
18326
|
+
rest = rest.slice(index);
|
|
18327
|
+
}
|
|
18328
|
+
}
|
|
18329
|
+
function matchMarkdownFenceMarker(line) {
|
|
18330
|
+
const direct = parseMarkdownFenceMarker(line);
|
|
18331
|
+
if (direct) return {
|
|
18332
|
+
...direct,
|
|
18333
|
+
inBlockquote: false,
|
|
18334
|
+
inList: false,
|
|
18335
|
+
listIndent: 0
|
|
18336
|
+
};
|
|
18337
|
+
const quoted = stripMarkdownBlockquotePrefix(line);
|
|
18338
|
+
const quotedMarker = quoted == null ? null : parseMarkdownFenceMarker(quoted);
|
|
18339
|
+
if (quotedMarker) return {
|
|
18340
|
+
...quotedMarker,
|
|
18341
|
+
inBlockquote: true,
|
|
18342
|
+
inList: false,
|
|
18343
|
+
listIndent: 0
|
|
18344
|
+
};
|
|
18345
|
+
const listed = stripMarkdownListPrefix(line);
|
|
18346
|
+
if (!listed) return null;
|
|
18347
|
+
const listedMarker = parseMarkdownFenceMarker(listed.content);
|
|
18348
|
+
return listedMarker == null ? null : {
|
|
18349
|
+
...listedMarker,
|
|
18350
|
+
inBlockquote: false,
|
|
18351
|
+
inList: true,
|
|
18352
|
+
listIndent: listed.contentIndent
|
|
18353
|
+
};
|
|
18354
|
+
}
|
|
18355
|
+
function countRepeatedChar(source, index, ch) {
|
|
18356
|
+
let end = index;
|
|
18357
|
+
while (end < source.length && source[end] === ch) end++;
|
|
18358
|
+
return end - index;
|
|
18359
|
+
}
|
|
18360
|
+
function findCodeSpanCloseIndex(line, start, markerLen) {
|
|
18361
|
+
let index = start;
|
|
18362
|
+
while (index < line.length) {
|
|
18363
|
+
const next = line.indexOf("`", index);
|
|
18364
|
+
if (next === -1) return -1;
|
|
18365
|
+
const runLen = countRepeatedChar(line, next, "`");
|
|
18366
|
+
if (runLen === markerLen) return next;
|
|
18367
|
+
index = next + runLen;
|
|
18368
|
+
}
|
|
18369
|
+
return -1;
|
|
18370
|
+
}
|
|
18371
|
+
function resetExplicitBracketFenceContext(context) {
|
|
18372
|
+
context.inFence = false;
|
|
18373
|
+
context.fenceChar = "";
|
|
18374
|
+
context.fenceLen = 0;
|
|
18375
|
+
context.fenceInBlockquote = false;
|
|
18376
|
+
context.fenceInList = false;
|
|
18377
|
+
context.fenceListIndent = 0;
|
|
18378
|
+
}
|
|
18379
|
+
function scanLineForExplicitBracketMathState(line, context, lineStart, appendStart, openAtAppendStart) {
|
|
18380
|
+
let index = 0;
|
|
18381
|
+
let closedOpenMath = false;
|
|
18382
|
+
while (index < line.length) {
|
|
18383
|
+
const sourceIndex = index;
|
|
18384
|
+
if (context.inMath) {
|
|
18385
|
+
if (line.startsWith("\\]", index) && !isEscapedDelimiterAt(line, sourceIndex)) {
|
|
18386
|
+
if (appendStart != null && openAtAppendStart && lineStart + index + 2 > appendStart) closedOpenMath = true;
|
|
18387
|
+
context.inMath = false;
|
|
18388
|
+
index += 2;
|
|
18389
|
+
continue;
|
|
18390
|
+
}
|
|
18391
|
+
index++;
|
|
18392
|
+
continue;
|
|
18393
|
+
}
|
|
18394
|
+
if (line[index] === "`" && !isEscapedDelimiterAt(line, sourceIndex)) {
|
|
18395
|
+
const markerLen = countRepeatedChar(line, index, "`");
|
|
18396
|
+
const closeIndex = findCodeSpanCloseIndex(line, index + markerLen, markerLen);
|
|
18397
|
+
if (closeIndex === -1) break;
|
|
18398
|
+
index = closeIndex + markerLen;
|
|
18399
|
+
continue;
|
|
18400
|
+
}
|
|
18401
|
+
if (line.startsWith("\\[", index) && !isEscapedDelimiterAt(line, sourceIndex)) {
|
|
18402
|
+
context.inMath = true;
|
|
18403
|
+
index += 2;
|
|
18404
|
+
continue;
|
|
18405
|
+
}
|
|
18406
|
+
index++;
|
|
18407
|
+
}
|
|
18408
|
+
return closedOpenMath;
|
|
18409
|
+
}
|
|
18410
|
+
function scanExplicitBracketMathLine(line, context, lineStart, appendStart, openAtAppendStart) {
|
|
18411
|
+
const lineIndent = getMarkdownIndent(line);
|
|
18412
|
+
const listPrefix = stripMarkdownListPrefix(line);
|
|
18413
|
+
if (context.inFence && context.fenceInBlockquote && line.trim() && stripMarkdownBlockquotePrefix(line) == null) resetExplicitBracketFenceContext(context);
|
|
18414
|
+
if (context.inFence && context.fenceInList && line.trim() && lineIndent.column < context.fenceListIndent && !listPrefix) resetExplicitBracketFenceContext(context);
|
|
18415
|
+
if (listPrefix) context.listContentIndent = listPrefix.contentIndent;
|
|
18416
|
+
else if (line.trim() && context.listContentIndent != null && lineIndent.column < context.listContentIndent && !context.inFence) context.listContentIndent = null;
|
|
18417
|
+
if (!context.inMath) {
|
|
18418
|
+
const fenceMatch = matchMarkdownFenceMarker(line);
|
|
18419
|
+
if (fenceMatch) if (context.inFence) {
|
|
18420
|
+
if (fenceMatch.markerChar === context.fenceChar && fenceMatch.markerLen >= context.fenceLen && /^\s*$/.test(fenceMatch.rest)) resetExplicitBracketFenceContext(context);
|
|
18421
|
+
} else {
|
|
18422
|
+
context.inFence = true;
|
|
18423
|
+
context.fenceChar = fenceMatch.markerChar;
|
|
18424
|
+
context.fenceLen = fenceMatch.markerLen;
|
|
18425
|
+
context.fenceInBlockquote = fenceMatch.inBlockquote;
|
|
18426
|
+
context.fenceInList = fenceMatch.inList || context.listContentIndent != null && !fenceMatch.inBlockquote && lineIndent.column >= context.listContentIndent;
|
|
18427
|
+
context.fenceListIndent = fenceMatch.listIndent || context.listContentIndent || 0;
|
|
18428
|
+
}
|
|
18429
|
+
else if (!context.inFence) return scanLineForExplicitBracketMathState(line, context, lineStart, appendStart, openAtAppendStart);
|
|
18430
|
+
} else return scanLineForExplicitBracketMathState(line, context, lineStart, appendStart, openAtAppendStart);
|
|
18431
|
+
return false;
|
|
18432
|
+
}
|
|
18433
|
+
function scanExplicitBracketMathStreamState(source, initialContext = createExplicitBracketMathContext(), appendStart = null, openAtAppendStart = false) {
|
|
18434
|
+
const context = cloneExplicitBracketMathContext(initialContext);
|
|
18435
|
+
let committedContext = cloneExplicitBracketMathContext(initialContext);
|
|
18436
|
+
let lineBuffer = "";
|
|
18437
|
+
let closedOpenMath = false;
|
|
18438
|
+
let index = 0;
|
|
18439
|
+
while (index < source.length) {
|
|
18440
|
+
const newlineIndex = source.indexOf("\n", index);
|
|
18441
|
+
const hasNewline = newlineIndex !== -1;
|
|
18442
|
+
const lineEnd$2 = hasNewline && newlineIndex > index && source[newlineIndex - 1] === "\r" ? newlineIndex - 1 : hasNewline ? newlineIndex : source.length;
|
|
18443
|
+
const line = source.slice(index, lineEnd$2);
|
|
18444
|
+
if (scanExplicitBracketMathLine(line, context, index, appendStart, openAtAppendStart)) closedOpenMath = true;
|
|
18445
|
+
if (hasNewline) {
|
|
18446
|
+
committedContext = cloneExplicitBracketMathContext(context);
|
|
18447
|
+
lineBuffer = "";
|
|
18448
|
+
} else lineBuffer = line;
|
|
18449
|
+
index = hasNewline ? newlineIndex + 1 : source.length;
|
|
18450
|
+
}
|
|
18451
|
+
return {
|
|
18452
|
+
closedOpenMath,
|
|
18453
|
+
state: {
|
|
18454
|
+
committedContext,
|
|
18455
|
+
context,
|
|
18456
|
+
lineBuffer
|
|
18457
|
+
}
|
|
18458
|
+
};
|
|
18459
|
+
}
|
|
18460
|
+
function updateExplicitBracketMathStreamState(previous, appended) {
|
|
18461
|
+
if (appended && !previous.context.inMath && !previous.context.inFence && !previous.committedContext.inFence && !/[\\`~\r\n]/.test(appended) && !(previous.lineBuffer.endsWith("\\") && (appended[0] === "[" || appended[0] === "]"))) return {
|
|
18462
|
+
closedOpenMath: false,
|
|
18463
|
+
state: {
|
|
18464
|
+
committedContext: cloneExplicitBracketMathContext(previous.committedContext),
|
|
18465
|
+
context: cloneExplicitBracketMathContext(previous.context),
|
|
18466
|
+
lineBuffer: previous.lineBuffer + appended
|
|
18467
|
+
}
|
|
18468
|
+
};
|
|
18469
|
+
return scanExplicitBracketMathStreamState(previous.lineBuffer + appended, previous.committedContext, previous.lineBuffer.length, previous.context.inMath);
|
|
18470
|
+
}
|
|
18057
18471
|
function syncTolerantMathBoundaryStreamCache(md, source) {
|
|
18058
18472
|
if (!hasMarkstreamMathPlugin(md)) return;
|
|
18059
18473
|
const stream = md.stream;
|
|
@@ -18061,18 +18475,22 @@ function syncTolerantMathBoundaryStreamCache(md, source) {
|
|
|
18061
18475
|
const owner = md;
|
|
18062
18476
|
const previous = tolerantMathBoundaryStreamCache.get(owner);
|
|
18063
18477
|
if (previous?.source === source) return;
|
|
18064
|
-
|
|
18065
|
-
|
|
18066
|
-
|
|
18478
|
+
const sourceExtendsPrevious = previous ? source.startsWith(previous.source) : false;
|
|
18479
|
+
const appended = sourceExtendsPrevious && previous ? source.slice(previous.source.length) : "";
|
|
18480
|
+
const explicitBracketMathUpdate = sourceExtendsPrevious && previous ? updateExplicitBracketMathStreamState(previous.explicitBracketMath, appended) : scanExplicitBracketMathStreamState(source);
|
|
18481
|
+
const nextExplicitBracketMath = explicitBracketMathUpdate.state;
|
|
18482
|
+
const completesExplicitBracketMathClose = sourceExtendsPrevious && previous ? explicitBracketMathUpdate.closedOpenMath : false;
|
|
18483
|
+
if (previous && sourceExtendsPrevious) {
|
|
18484
|
+
if (previous.key === null && previous.pendingCandidate === false && !completesExplicitBracketMathClose && !appendedChunkMayAffectTolerantMathBoundary(previous.source, appended) && !sourceEndsWithSplitTolerantBoundaryPrefix(source)) {
|
|
18067
18485
|
previous.source = source;
|
|
18486
|
+
previous.explicitBracketMath = nextExplicitBracketMath;
|
|
18068
18487
|
return;
|
|
18069
18488
|
}
|
|
18070
18489
|
}
|
|
18071
18490
|
const nextKey = getTolerantMathBlockBoundaryStreamKey(source);
|
|
18072
|
-
|
|
18073
|
-
if (previous && (sourceWasReplaced || previous.key !== nextKey)) stream.reset();
|
|
18491
|
+
if (previous && ((previous ? !sourceExtendsPrevious : false) || previous.key !== nextKey || completesExplicitBracketMathClose)) stream.reset();
|
|
18074
18492
|
else if (!previous && nextKey) stream.reset();
|
|
18075
|
-
setTolerantMathBoundaryStreamCache(md, source, nextKey);
|
|
18493
|
+
setTolerantMathBoundaryStreamCache(md, source, nextKey, nextExplicitBracketMath);
|
|
18076
18494
|
}
|
|
18077
18495
|
function shouldCloneTopLevelStreamTokens(options) {
|
|
18078
18496
|
return typeof options.preTransformTokens === "function" || typeof options.postTransformTokens === "function";
|
|
@@ -18141,6 +18559,10 @@ function buildParagraphFromInlineChildren(children) {
|
|
|
18141
18559
|
raw: children.map(stringifyInlineNodeRaw).join("")
|
|
18142
18560
|
};
|
|
18143
18561
|
}
|
|
18562
|
+
function inheritSourceMap(nodes, sourceNode) {
|
|
18563
|
+
if (!sourceNode.sourceMap) return;
|
|
18564
|
+
for (const node of nodes) if (!node.sourceMap) node.sourceMap = sourceNode.sourceMap;
|
|
18565
|
+
}
|
|
18144
18566
|
function maybePromoteCustomNodeFromParagraph(node, options) {
|
|
18145
18567
|
if (node.type !== "paragraph") return null;
|
|
18146
18568
|
const nodeChildren = getNodeFields(node).children;
|
|
@@ -18480,7 +18902,7 @@ function combineStructuredDetailsHtmlBlocks(nodes, source, md, options, final, s
|
|
|
18480
18902
|
const renderedCloseRaw = explicitClose ? source.slice(closeStart, closeSliceEnd) : closeRaw;
|
|
18481
18903
|
const mergedRaw = explicitClose ? source.slice(openStart, closeSliceEnd) : source.slice(openStart);
|
|
18482
18904
|
const contentPrefix = selfContained && openTagEndIndex !== -1 ? openRaw.slice(0, openTagEndIndex + 1) : openRaw;
|
|
18483
|
-
|
|
18905
|
+
const detailsNode = {
|
|
18484
18906
|
...node,
|
|
18485
18907
|
tag: "details",
|
|
18486
18908
|
attrs: parseTagAttrs(openRaw.slice(0, openTagEndIndex + 1)),
|
|
@@ -18488,14 +18910,16 @@ function combineStructuredDetailsHtmlBlocks(nodes, source, md, options, final, s
|
|
|
18488
18910
|
content: `${contentPrefix}${renderedMiddle}${renderedCloseRaw}`,
|
|
18489
18911
|
children: [...prefixChildren, ...children],
|
|
18490
18912
|
loading: !final && !explicitClose
|
|
18491
|
-
}
|
|
18913
|
+
};
|
|
18914
|
+
if (options.includeSourceMap) detailsNode.sourceMap = createSourceMapFromOffsets(source, openStart, explicitClose ? closeSliceEnd : source.length, options);
|
|
18915
|
+
merged.push(detailsNode);
|
|
18492
18916
|
cursor = explicitClose ? closeSliceEnd : source.length;
|
|
18493
18917
|
if (closeIndex === -1 && !selfContained) break;
|
|
18494
18918
|
if (closeIndex !== -1) i = closeIndex;
|
|
18495
18919
|
}
|
|
18496
18920
|
return [merged, cursor];
|
|
18497
18921
|
}
|
|
18498
|
-
function mergeSplitTopLevelHtmlBlocks(nodes, final, source) {
|
|
18922
|
+
function mergeSplitTopLevelHtmlBlocks(nodes, final, source, options) {
|
|
18499
18923
|
if (!source) return nodes;
|
|
18500
18924
|
const merged = nodes.slice();
|
|
18501
18925
|
let sourceHtmlCursor = 0;
|
|
@@ -18528,6 +18952,7 @@ function mergeSplitTopLevelHtmlBlocks(nodes, final, source) {
|
|
|
18528
18952
|
node.raw = exact.raw;
|
|
18529
18953
|
node.loading = desiredLoading;
|
|
18530
18954
|
node.attrs = exactAttrs.length ? exactAttrs : void 0;
|
|
18955
|
+
if (options?.includeSourceMap) node.sourceMap = createSourceMapFromOffsets(source, exact.start, exact.end, options);
|
|
18531
18956
|
if (!needsExpansion) continue;
|
|
18532
18957
|
let tailCursor = findApproximateConsumedPrefixEnd(exact.raw, currentRaw);
|
|
18533
18958
|
if (tailCursor === -1) tailCursor = 0;
|
|
@@ -18694,6 +19119,106 @@ function stripDanglingHtmlLikeTail(markdown) {
|
|
|
18694
19119
|
if (!isLikelyHtmlTagPrefix(tail)) return s;
|
|
18695
19120
|
return s.slice(0, lastLt);
|
|
18696
19121
|
}
|
|
19122
|
+
function createSourceLineMapper(source, parsedSource) {
|
|
19123
|
+
if (source === parsedSource) return void 0;
|
|
19124
|
+
const sourceLines = source.split(/\r?\n/);
|
|
19125
|
+
const parsedLines = parsedSource.split(/\r?\n/);
|
|
19126
|
+
const mappedLines = [];
|
|
19127
|
+
let sourceCursor = 0;
|
|
19128
|
+
for (let parsedLine = 0; parsedLine < parsedLines.length; parsedLine++) {
|
|
19129
|
+
const line = parsedLines[parsedLine] ?? "";
|
|
19130
|
+
if (sourceLines[sourceCursor] === line) {
|
|
19131
|
+
mappedLines[parsedLine] = {
|
|
19132
|
+
startLine: sourceCursor,
|
|
19133
|
+
endLine: sourceCursor + 1
|
|
19134
|
+
};
|
|
19135
|
+
sourceCursor++;
|
|
19136
|
+
continue;
|
|
19137
|
+
}
|
|
19138
|
+
const sourceLine = sourceLines[sourceCursor] ?? "";
|
|
19139
|
+
if (line !== "" && sourceLine !== line && sourceLine.startsWith(line)) {
|
|
19140
|
+
let joinedLine = line;
|
|
19141
|
+
let splitEnd = -1;
|
|
19142
|
+
for (let nextParsedLine = parsedLine + 1; nextParsedLine < parsedLines.length; nextParsedLine++) {
|
|
19143
|
+
joinedLine += parsedLines[nextParsedLine] ?? "";
|
|
19144
|
+
if (joinedLine === sourceLine) {
|
|
19145
|
+
splitEnd = nextParsedLine;
|
|
19146
|
+
break;
|
|
19147
|
+
}
|
|
19148
|
+
if (!sourceLine.startsWith(joinedLine)) break;
|
|
19149
|
+
}
|
|
19150
|
+
if (splitEnd !== -1) {
|
|
19151
|
+
for (let mappedLine = parsedLine; mappedLine <= splitEnd; mappedLine++) mappedLines[mappedLine] = {
|
|
19152
|
+
startLine: sourceCursor,
|
|
19153
|
+
endLine: sourceCursor + 1
|
|
19154
|
+
};
|
|
19155
|
+
sourceCursor++;
|
|
19156
|
+
parsedLine = splitEnd;
|
|
19157
|
+
continue;
|
|
19158
|
+
}
|
|
19159
|
+
mappedLines[parsedLine] = {
|
|
19160
|
+
startLine: sourceCursor,
|
|
19161
|
+
endLine: sourceCursor + 1
|
|
19162
|
+
};
|
|
19163
|
+
continue;
|
|
19164
|
+
}
|
|
19165
|
+
let collapsedLine = sourceLines[sourceCursor] ?? "";
|
|
19166
|
+
let collapsedEnd = -1;
|
|
19167
|
+
for (let sourceLine$1 = sourceCursor + 1; sourceLine$1 < sourceLines.length; sourceLine$1++) {
|
|
19168
|
+
collapsedLine += `\\n${sourceLines[sourceLine$1] ?? ""}`;
|
|
19169
|
+
if (collapsedLine === line) {
|
|
19170
|
+
collapsedEnd = sourceLine$1 + 1;
|
|
19171
|
+
break;
|
|
19172
|
+
}
|
|
19173
|
+
if (!line.startsWith(collapsedLine)) break;
|
|
19174
|
+
}
|
|
19175
|
+
if (collapsedEnd !== -1) {
|
|
19176
|
+
mappedLines[parsedLine] = {
|
|
19177
|
+
startLine: sourceCursor,
|
|
19178
|
+
endLine: collapsedEnd
|
|
19179
|
+
};
|
|
19180
|
+
sourceCursor = collapsedEnd;
|
|
19181
|
+
continue;
|
|
19182
|
+
}
|
|
19183
|
+
let found = -1;
|
|
19184
|
+
if (line !== "") {
|
|
19185
|
+
const searchEnd = Math.min(sourceLines.length, sourceCursor + 80);
|
|
19186
|
+
for (let sourceLine$1 = sourceCursor; sourceLine$1 < searchEnd; sourceLine$1++) if (sourceLines[sourceLine$1] === line) {
|
|
19187
|
+
found = sourceLine$1;
|
|
19188
|
+
break;
|
|
19189
|
+
}
|
|
19190
|
+
}
|
|
19191
|
+
if (found !== -1) {
|
|
19192
|
+
mappedLines[parsedLine] = {
|
|
19193
|
+
startLine: found,
|
|
19194
|
+
endLine: found + 1
|
|
19195
|
+
};
|
|
19196
|
+
sourceCursor = found + 1;
|
|
19197
|
+
continue;
|
|
19198
|
+
}
|
|
19199
|
+
const fallbackLine = Math.min(Math.max(0, sourceLines.length - 1), Math.max(0, sourceCursor - 1));
|
|
19200
|
+
mappedLines[parsedLine] = {
|
|
19201
|
+
startLine: fallbackLine,
|
|
19202
|
+
endLine: fallbackLine + 1
|
|
19203
|
+
};
|
|
19204
|
+
}
|
|
19205
|
+
return (line) => {
|
|
19206
|
+
const index = Number.isFinite(line) ? Math.max(0, Math.trunc(line)) : 0;
|
|
19207
|
+
if (index < mappedLines.length) return mappedLines[index] ?? {
|
|
19208
|
+
startLine: 0,
|
|
19209
|
+
endLine: 0
|
|
19210
|
+
};
|
|
19211
|
+
const lastMapped = mappedLines[mappedLines.length - 1] ?? {
|
|
19212
|
+
startLine: Math.max(0, sourceLines.length - 1),
|
|
19213
|
+
endLine: sourceLines.length
|
|
19214
|
+
};
|
|
19215
|
+
const startLine = Math.min(sourceLines.length, lastMapped.endLine + index - mappedLines.length);
|
|
19216
|
+
return {
|
|
19217
|
+
startLine,
|
|
19218
|
+
endLine: Math.min(sourceLines.length, startLine + 1)
|
|
19219
|
+
};
|
|
19220
|
+
};
|
|
19221
|
+
}
|
|
18697
19222
|
function ensureBlankLineBeforeInlineMultilineCustomHtmlBlocks(markdown, tags) {
|
|
18698
19223
|
if (!markdown || !tags.length) return markdown;
|
|
18699
19224
|
const tagSet = new Set(tags.map((t) => String(t ?? "").toLowerCase()).filter(Boolean));
|
|
@@ -19315,7 +19840,8 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
|
|
|
19315
19840
|
const timing = getParseTiming(options);
|
|
19316
19841
|
const parseStartedAt = timing ? getParserNow() : 0;
|
|
19317
19842
|
const isFinal = !!options.final;
|
|
19318
|
-
|
|
19843
|
+
const sourceMarkdown = (markdown ?? "").toString();
|
|
19844
|
+
let safeMarkdown = sourceMarkdown.replace(/([^\\])\r(ight|ho)/g, "$1\\r$2").replace(/([^\\])\r?\n(abla|eq|ot|exists)/g, "$1\\n$2");
|
|
19319
19845
|
if (shouldResetTopLevelStreamCacheForFinalAutoParse(md, options)) {
|
|
19320
19846
|
md.stream.reset();
|
|
19321
19847
|
clearTolerantMathBoundaryStreamCache(md);
|
|
@@ -19358,6 +19884,13 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
|
|
|
19358
19884
|
if (!isFinal) safeMarkdown = stripDanglingHtmlLikeTail(safeMarkdown);
|
|
19359
19885
|
const standaloneHtmlDocument = parseStandaloneHtmlDocument(safeMarkdown);
|
|
19360
19886
|
if (standaloneHtmlDocument) {
|
|
19887
|
+
if (options.includeSourceMap) {
|
|
19888
|
+
const sourceMapOptions = {
|
|
19889
|
+
...options,
|
|
19890
|
+
__sourceLineMapper: createSourceLineMapper(sourceMarkdown, safeMarkdown)
|
|
19891
|
+
};
|
|
19892
|
+
standaloneHtmlDocument[0].sourceMap = createSourceMapFromOffsets(safeMarkdown, 0, safeMarkdown.length, sourceMapOptions);
|
|
19893
|
+
}
|
|
19361
19894
|
const preHook = options.preTransformTokens;
|
|
19362
19895
|
const postHook = options.postTransformTokens;
|
|
19363
19896
|
if (shouldUseTopLevelStreamParse(md, options) || typeof preHook === "function" || typeof postHook === "function") {
|
|
@@ -19365,10 +19898,10 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
|
|
|
19365
19898
|
const hookedTokens = typeof preHook === "function" ? preHook(rawTokens) || rawTokens : rawTokens;
|
|
19366
19899
|
if (typeof postHook === "function") postHook(hookedTokens);
|
|
19367
19900
|
}
|
|
19368
|
-
return
|
|
19901
|
+
return finishParsedNodes(standaloneHtmlDocument, options, timing, parseStartedAt);
|
|
19369
19902
|
}
|
|
19370
19903
|
const tokens = parseTopLevelTokens(md, safeMarkdown, { __markstreamFinal: isFinal }, options);
|
|
19371
|
-
if (!tokens || !Array.isArray(tokens)) return
|
|
19904
|
+
if (!tokens || !Array.isArray(tokens)) return finishParsedNodes([], options, timing, parseStartedAt);
|
|
19372
19905
|
const pre = options.preTransformTokens;
|
|
19373
19906
|
const post = options.postTransformTokens;
|
|
19374
19907
|
let transformedTokens = tokens;
|
|
@@ -19379,6 +19912,7 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
|
|
|
19379
19912
|
...options,
|
|
19380
19913
|
validateLink: validateLink$1,
|
|
19381
19914
|
__markdownIt: md,
|
|
19915
|
+
__sourceLineMapper: options.includeSourceMap === true ? createSourceLineMapper(sourceMarkdown, safeMarkdown) : void 0,
|
|
19382
19916
|
__sourceMarkdown: safeMarkdown,
|
|
19383
19917
|
__customHtmlBlockCursor: 0
|
|
19384
19918
|
};
|
|
@@ -19388,13 +19922,16 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
|
|
|
19388
19922
|
if (Array.isArray(postResult)) {
|
|
19389
19923
|
const first = postResult[0];
|
|
19390
19924
|
const firstType = first?.type;
|
|
19391
|
-
if (first && typeof firstType === "string") result = processTokensWithTiming(postResult,
|
|
19925
|
+
if (first && typeof firstType === "string") result = processTokensWithTiming(postResult, {
|
|
19926
|
+
...internalOptions,
|
|
19927
|
+
__customHtmlBlockCursor: 0
|
|
19928
|
+
}, timing);
|
|
19392
19929
|
else result = postResult;
|
|
19393
19930
|
}
|
|
19394
19931
|
}
|
|
19395
|
-
result = mergeSplitTopLevelHtmlBlocks(result, isFinal, safeMarkdown);
|
|
19396
|
-
result = combineStructuredDetailsHtmlBlocks(result, safeMarkdown, md,
|
|
19397
|
-
result = structureGenericHtmlBlockChildren(result, md,
|
|
19932
|
+
result = mergeSplitTopLevelHtmlBlocks(result, isFinal, safeMarkdown, internalOptions);
|
|
19933
|
+
result = combineStructuredDetailsHtmlBlocks(result, safeMarkdown, md, internalOptions, isFinal)[0];
|
|
19934
|
+
result = structureGenericHtmlBlockChildren(result, md, internalOptions, isFinal);
|
|
19398
19935
|
if (isFinal) {
|
|
19399
19936
|
const seen = /* @__PURE__ */ new WeakSet();
|
|
19400
19937
|
const finalizeHtmlBlockLoading = (value) => {
|
|
@@ -19411,6 +19948,7 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
|
|
|
19411
19948
|
};
|
|
19412
19949
|
finalizeHtmlBlockLoading(result);
|
|
19413
19950
|
}
|
|
19951
|
+
result = applyPostTransformNodes(result, options);
|
|
19414
19952
|
if (options.debug) console.log("Parsed Markdown Tree Structure:", result);
|
|
19415
19953
|
return finishTimedParse(result, timing, parseStartedAt);
|
|
19416
19954
|
}
|
|
@@ -19418,6 +19956,7 @@ function processTokens(tokens, options) {
|
|
|
19418
19956
|
if (!tokens || !Array.isArray(tokens)) return [];
|
|
19419
19957
|
const result = [];
|
|
19420
19958
|
const linkifyContext = createLinkifyDemotionContextTracker(options);
|
|
19959
|
+
const includeSourceMap = options?.includeSourceMap === true;
|
|
19421
19960
|
let i = 0;
|
|
19422
19961
|
while (i < tokens.length) {
|
|
19423
19962
|
const handled = parseCommonBlockToken(tokens, i, linkifyContext.options(), containerTokenHandlers);
|
|
@@ -19432,9 +19971,12 @@ function processTokens(tokens, options) {
|
|
|
19432
19971
|
case "paragraph_open": {
|
|
19433
19972
|
const paragraphRaw = String(tokens[i + 1]?.content ?? "");
|
|
19434
19973
|
const paragraphNode = parseParagraph(tokens, i, linkifyContext.options(paragraphRaw));
|
|
19974
|
+
if (includeSourceMap) applyNodeSourceMap(paragraphNode, token, options);
|
|
19435
19975
|
const promoted = maybePromoteCustomNodeFromParagraph(paragraphNode, options);
|
|
19436
|
-
if (promoted)
|
|
19437
|
-
|
|
19976
|
+
if (promoted) {
|
|
19977
|
+
if (includeSourceMap) inheritSourceMap(promoted, paragraphNode);
|
|
19978
|
+
result.push(...promoted);
|
|
19979
|
+
} else result.push(paragraphNode);
|
|
19438
19980
|
linkifyContext.remember(paragraphNode.raw);
|
|
19439
19981
|
i += 3;
|
|
19440
19982
|
break;
|
|
@@ -19442,6 +19984,7 @@ function processTokens(tokens, options) {
|
|
|
19442
19984
|
case "bullet_list_open":
|
|
19443
19985
|
case "ordered_list_open": {
|
|
19444
19986
|
const [listNode, newIndex] = parseList(tokens, i, linkifyContext.options());
|
|
19987
|
+
if (includeSourceMap) applyNodeSourceMap(listNode, token, options);
|
|
19445
19988
|
result.push(listNode);
|
|
19446
19989
|
linkifyContext.remember(listNode.raw);
|
|
19447
19990
|
i = newIndex;
|
|
@@ -19449,6 +19992,7 @@ function processTokens(tokens, options) {
|
|
|
19449
19992
|
}
|
|
19450
19993
|
case "blockquote_open": {
|
|
19451
19994
|
const [blockquoteNode, newIndex] = parseBlockquote(tokens, i, linkifyContext.options());
|
|
19995
|
+
if (includeSourceMap) applyNodeSourceMap(blockquoteNode, token, options);
|
|
19452
19996
|
result.push(blockquoteNode);
|
|
19453
19997
|
linkifyContext.remember(blockquoteNode.raw);
|
|
19454
19998
|
i = newIndex;
|
|
@@ -19456,12 +20000,13 @@ function processTokens(tokens, options) {
|
|
|
19456
20000
|
}
|
|
19457
20001
|
case "footnote_anchor": {
|
|
19458
20002
|
const meta = token.meta ?? {};
|
|
19459
|
-
const
|
|
19460
|
-
result.push({
|
|
20003
|
+
const footnoteAnchorNode = {
|
|
19461
20004
|
type: "footnote_anchor",
|
|
19462
|
-
id,
|
|
20005
|
+
id: String(meta.label ?? token.content ?? ""),
|
|
19463
20006
|
raw: String(token.content ?? "")
|
|
19464
|
-
}
|
|
20007
|
+
};
|
|
20008
|
+
if (includeSourceMap) applyNodeSourceMap(footnoteAnchorNode, token, options);
|
|
20009
|
+
result.push(footnoteAnchorNode);
|
|
19465
20010
|
linkifyContext.remember(String(token.content ?? ""));
|
|
19466
20011
|
i++;
|
|
19467
20012
|
break;
|
|
@@ -19473,7 +20018,7 @@ function processTokens(tokens, options) {
|
|
|
19473
20018
|
break;
|
|
19474
20019
|
case "text": {
|
|
19475
20020
|
const content = String(token.content ?? "");
|
|
19476
|
-
|
|
20021
|
+
const paragraphNode = {
|
|
19477
20022
|
type: "paragraph",
|
|
19478
20023
|
raw: content,
|
|
19479
20024
|
children: content ? [{
|
|
@@ -19481,7 +20026,9 @@ function processTokens(tokens, options) {
|
|
|
19481
20026
|
content,
|
|
19482
20027
|
raw: content
|
|
19483
20028
|
}] : []
|
|
19484
|
-
}
|
|
20029
|
+
};
|
|
20030
|
+
if (includeSourceMap) applyNodeSourceMap(paragraphNode, token, options);
|
|
20031
|
+
result.push(paragraphNode);
|
|
19485
20032
|
linkifyContext.remember(content);
|
|
19486
20033
|
i++;
|
|
19487
20034
|
break;
|
|
@@ -19490,16 +20037,21 @@ function processTokens(tokens, options) {
|
|
|
19490
20037
|
{
|
|
19491
20038
|
const raw = String(token.content ?? "");
|
|
19492
20039
|
const parsed = parseInlineTokens(token.children || [], raw, void 0, linkifyContext.options(raw));
|
|
19493
|
-
if (parsed.length === 0) {} else if (parsed.every((n) => n.type === "html_block"))
|
|
19494
|
-
|
|
20040
|
+
if (parsed.length === 0) {} else if (parsed.every((n) => n.type === "html_block")) {
|
|
20041
|
+
if (includeSourceMap) for (const node of parsed) applyNodeSourceMap(node, token, options);
|
|
20042
|
+
result.push(...parsed);
|
|
20043
|
+
} else {
|
|
19495
20044
|
const paragraphNode = {
|
|
19496
20045
|
type: "paragraph",
|
|
19497
20046
|
raw,
|
|
19498
20047
|
children: parsed
|
|
19499
20048
|
};
|
|
20049
|
+
if (includeSourceMap) applyNodeSourceMap(paragraphNode, token, options);
|
|
19500
20050
|
const promoted = maybePromoteCustomNodeFromParagraph(paragraphNode, options);
|
|
19501
|
-
if (promoted)
|
|
19502
|
-
|
|
20051
|
+
if (promoted) {
|
|
20052
|
+
if (includeSourceMap) inheritSourceMap(promoted, paragraphNode);
|
|
20053
|
+
result.push(...promoted);
|
|
20054
|
+
} else result.push(paragraphNode);
|
|
19503
20055
|
}
|
|
19504
20056
|
linkifyContext.remember(raw);
|
|
19505
20057
|
}
|
|
@@ -19515,6 +20067,7 @@ function processTokens(tokens, options) {
|
|
|
19515
20067
|
|
|
19516
20068
|
//#endregion
|
|
19517
20069
|
//#region src/htmlRenderUtils.ts
|
|
20070
|
+
const HTML_TOKEN_TAG_NAME_RE = /^([a-z][\w-]*)(?=[\t\n\f\r />]|$)/i;
|
|
19518
20071
|
const SAFE_BLOCKED_HTML_TAGS = new Set([
|
|
19519
20072
|
...BLOCKED_HTML_TAGS,
|
|
19520
20073
|
"base",
|
|
@@ -19588,7 +20141,6 @@ const SAFE_ALLOWED_HTML_TAGS = new Set([
|
|
|
19588
20141
|
"tr",
|
|
19589
20142
|
"ul"
|
|
19590
20143
|
]);
|
|
19591
|
-
const CUSTOM_TAG_REGEX = /<([a-z][a-z0-9-]*)\b[^>]*>/gi;
|
|
19592
20144
|
function hasOwn(obj, key) {
|
|
19593
20145
|
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
19594
20146
|
}
|
|
@@ -19626,6 +20178,18 @@ function serializeAttrs(attrs) {
|
|
|
19626
20178
|
if (pairs.length === 0) return "";
|
|
19627
20179
|
return pairs.map(([name, value]) => value === "" ? ` ${name}` : ` ${name}="${escapeAttr(value)}"`).join("");
|
|
19628
20180
|
}
|
|
20181
|
+
function parseHtmlTokenTag(rawContent) {
|
|
20182
|
+
const isClosing = rawContent.startsWith("/");
|
|
20183
|
+
const source = isClosing ? rawContent.slice(1) : rawContent;
|
|
20184
|
+
const match = source.match(HTML_TOKEN_TAG_NAME_RE);
|
|
20185
|
+
if (!match) return null;
|
|
20186
|
+
return {
|
|
20187
|
+
attrsStr: isClosing ? "" : source.slice(match[0].length).trimStart(),
|
|
20188
|
+
isClosing,
|
|
20189
|
+
isSelfClosing: !isClosing && rawContent.trimEnd().endsWith("/"),
|
|
20190
|
+
tagName: match[1]
|
|
20191
|
+
};
|
|
20192
|
+
}
|
|
19629
20193
|
function isUnsafeSrcset(value, tagName) {
|
|
19630
20194
|
const candidates = value.split(",").map((candidate) => candidate.trim()).filter(Boolean);
|
|
19631
20195
|
if (candidates.length === 0) return false;
|
|
@@ -19798,37 +20362,34 @@ function tokenizeHtml(html) {
|
|
|
19798
20362
|
}
|
|
19799
20363
|
const tagEnd = html.indexOf(">", tagStart);
|
|
19800
20364
|
if (tagEnd === -1) break;
|
|
19801
|
-
const
|
|
19802
|
-
|
|
19803
|
-
|
|
19804
|
-
|
|
19805
|
-
|
|
19806
|
-
|
|
19807
|
-
type: "tag_close",
|
|
19808
|
-
tagName
|
|
20365
|
+
const parsedTag = parseHtmlTokenTag(html.slice(tagStart + 1, tagEnd));
|
|
20366
|
+
if (!parsedTag) {
|
|
20367
|
+
const rawTag = html.slice(tagStart, tagEnd + 1);
|
|
20368
|
+
if (isMeaningfulText(rawTag)) tokens.push({
|
|
20369
|
+
type: "text",
|
|
20370
|
+
content: rawTag
|
|
19809
20371
|
});
|
|
19810
|
-
|
|
19811
|
-
|
|
19812
|
-
|
|
19813
|
-
|
|
19814
|
-
|
|
19815
|
-
|
|
19816
|
-
|
|
19817
|
-
|
|
19818
|
-
}
|
|
20372
|
+
pos = tagEnd + 1;
|
|
20373
|
+
continue;
|
|
20374
|
+
}
|
|
20375
|
+
if (parsedTag.isClosing) tokens.push({
|
|
20376
|
+
type: "tag_close",
|
|
20377
|
+
tagName: parsedTag.tagName
|
|
20378
|
+
});
|
|
20379
|
+
else {
|
|
19819
20380
|
const attrs = {};
|
|
19820
|
-
if (attrsStr) {
|
|
20381
|
+
if (parsedTag.attrsStr) {
|
|
19821
20382
|
const attrRegex = /([^\s=]+)(?:=(?:"([^"]*)"|'([^']*)'|(\S*)))?/g;
|
|
19822
20383
|
let attrMatch;
|
|
19823
|
-
while ((attrMatch = attrRegex.exec(attrsStr)) !== null) {
|
|
20384
|
+
while ((attrMatch = attrRegex.exec(parsedTag.attrsStr)) !== null) {
|
|
19824
20385
|
const name = attrMatch[1];
|
|
19825
20386
|
const value = attrMatch[2] ?? attrMatch[3] ?? attrMatch[4] ?? "";
|
|
19826
20387
|
if (name && !name.endsWith("/")) attrs[name] = value;
|
|
19827
20388
|
}
|
|
19828
20389
|
}
|
|
19829
20390
|
tokens.push({
|
|
19830
|
-
type: isSelfClosing
|
|
19831
|
-
tagName,
|
|
20391
|
+
type: parsedTag.isSelfClosing || VOID_HTML_TAGS.has(parsedTag.tagName.toLowerCase()) ? "self_closing" : "tag_open",
|
|
20392
|
+
tagName: parsedTag.tagName,
|
|
19832
20393
|
attrs
|
|
19833
20394
|
});
|
|
19834
20395
|
}
|
|
@@ -19882,43 +20443,36 @@ function tokenizeHtmlPreservingText(html) {
|
|
|
19882
20443
|
}
|
|
19883
20444
|
const tagEnd = html.indexOf(">", tagStart);
|
|
19884
20445
|
if (tagEnd === -1) break;
|
|
19885
|
-
const
|
|
19886
|
-
if (!
|
|
20446
|
+
const parsedTag = parseHtmlTokenTag(html.slice(tagStart + 1, tagEnd));
|
|
20447
|
+
if (!parsedTag) {
|
|
20448
|
+
tokens.push({
|
|
20449
|
+
type: "text",
|
|
20450
|
+
content: html.slice(tagStart, tagEnd + 1)
|
|
20451
|
+
});
|
|
19887
20452
|
pos = tagEnd + 1;
|
|
19888
20453
|
continue;
|
|
19889
20454
|
}
|
|
19890
|
-
|
|
19891
|
-
const isSelfClosing$1 = tagContent.endsWith("/");
|
|
19892
|
-
if (isClosingTag$1) {
|
|
19893
|
-
const tagName$1 = tagContent.slice(1).trim();
|
|
20455
|
+
if (parsedTag.isClosing) {
|
|
19894
20456
|
tokens.push({
|
|
19895
20457
|
type: "tag_close",
|
|
19896
|
-
tagName: tagName
|
|
20458
|
+
tagName: parsedTag.tagName
|
|
19897
20459
|
});
|
|
19898
20460
|
pos = tagEnd + 1;
|
|
19899
20461
|
continue;
|
|
19900
20462
|
}
|
|
19901
|
-
const spaceIndex = tagContent.indexOf(" ");
|
|
19902
|
-
let tagName = "";
|
|
19903
|
-
let attrsStr = "";
|
|
19904
|
-
if (spaceIndex === -1) tagName = isSelfClosing$1 ? tagContent.slice(0, -1).trim() : tagContent.trim();
|
|
19905
|
-
else {
|
|
19906
|
-
tagName = tagContent.slice(0, spaceIndex).trim();
|
|
19907
|
-
attrsStr = tagContent.slice(spaceIndex + 1);
|
|
19908
|
-
}
|
|
19909
20463
|
const attrs = {};
|
|
19910
|
-
if (attrsStr) {
|
|
20464
|
+
if (parsedTag.attrsStr) {
|
|
19911
20465
|
const attrRegex = /([^\s=]+)(?:=(?:"([^"]*)"|'([^']*)'|(\S*)))?/g;
|
|
19912
20466
|
let attrMatch;
|
|
19913
|
-
while ((attrMatch = attrRegex.exec(attrsStr)) !== null) {
|
|
20467
|
+
while ((attrMatch = attrRegex.exec(parsedTag.attrsStr)) !== null) {
|
|
19914
20468
|
const name = attrMatch[1];
|
|
19915
20469
|
const value = attrMatch[2] ?? attrMatch[3] ?? attrMatch[4] ?? "";
|
|
19916
20470
|
if (name && !name.endsWith("/")) attrs[name] = value;
|
|
19917
20471
|
}
|
|
19918
20472
|
}
|
|
19919
20473
|
tokens.push({
|
|
19920
|
-
type: isSelfClosing
|
|
19921
|
-
tagName,
|
|
20474
|
+
type: parsedTag.isSelfClosing || VOID_HTML_TAGS.has(parsedTag.tagName.toLowerCase()) ? "self_closing" : "tag_open",
|
|
20475
|
+
tagName: parsedTag.tagName,
|
|
19922
20476
|
attrs
|
|
19923
20477
|
});
|
|
19924
20478
|
pos = tagEnd + 1;
|
|
@@ -19935,9 +20489,7 @@ function serializeLiteralHtmlTag(token) {
|
|
|
19935
20489
|
function hasCustomHtmlComponents(content, customComponents) {
|
|
19936
20490
|
if (!content || !content.includes("<")) return false;
|
|
19937
20491
|
if (!customComponents || Object.keys(customComponents).length === 0) return false;
|
|
19938
|
-
|
|
19939
|
-
let match;
|
|
19940
|
-
while ((match = CUSTOM_TAG_REGEX.exec(content)) !== null) if (isCustomHtmlComponentTag(match[1], customComponents)) return true;
|
|
20492
|
+
for (const token of tokenizeHtml(content)) if ((token.type === "tag_open" || token.type === "self_closing") && isCustomHtmlComponentTag(token.tagName ?? "", customComponents)) return true;
|
|
19941
20493
|
return false;
|
|
19942
20494
|
}
|
|
19943
20495
|
function sanitizeHtmlContent(content, policy = "safe") {
|