stream-markdown-parser 0.0.58-beta.8 → 0.0.58
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 +333 -45
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,11 @@ interface FactoryOptions extends Record<string, unknown> {
|
|
|
14
14
|
* suppression and be emitted as custom nodes (e.g. ['thinking']).
|
|
15
15
|
*/
|
|
16
16
|
customHtmlTags?: readonly string[];
|
|
17
|
+
/**
|
|
18
|
+
* Whether to enable the fix for indented code blocks that should be paragraphs.
|
|
19
|
+
* Default: true
|
|
20
|
+
*/
|
|
21
|
+
enableFixIndentedCodeBlock?: boolean;
|
|
17
22
|
}
|
|
18
23
|
//#endregion
|
|
19
24
|
//#region src/types.d.ts
|
|
@@ -39,6 +44,7 @@ interface HeadingNode extends BaseNode {
|
|
|
39
44
|
type: 'heading';
|
|
40
45
|
level: number;
|
|
41
46
|
text: string;
|
|
47
|
+
attrs?: Record<string, string | boolean>;
|
|
42
48
|
children: ParsedNode[];
|
|
43
49
|
}
|
|
44
50
|
interface ParagraphNode extends BaseNode {
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/factory.ts","../src/types.ts","../src/parser/inline-parsers/index.ts","../src/parser/index.ts","../src/config.ts","../src/findMatchingClose.ts","../src/parser/inline-parsers/fence-parser.ts","../src/plugins/containers.ts","../src/plugins/isMathLike.ts","../src/plugins/math.ts","../src/index.ts"],"sourcesContent":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/factory.ts","../src/types.ts","../src/parser/inline-parsers/index.ts","../src/parser/index.ts","../src/config.ts","../src/findMatchingClose.ts","../src/parser/inline-parsers/fence-parser.ts","../src/plugins/containers.ts","../src/plugins/isMathLike.ts","../src/plugins/math.ts","../src/index.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -7484,18 +7484,33 @@ function applyFixHtmlInlineTokens(md, options = {}) {
|
|
|
7484
7484
|
const t = toks[i];
|
|
7485
7485
|
if (t.type === "html_block") {
|
|
7486
7486
|
const tag = (t.content?.match(/<([^\s>/]+)/)?.[1] ?? "").toLowerCase();
|
|
7487
|
+
if (tag.startsWith("!") || tag.startsWith("?")) {
|
|
7488
|
+
t.loading = false;
|
|
7489
|
+
continue;
|
|
7490
|
+
}
|
|
7487
7491
|
if (customTagSet.has(tag)) {
|
|
7488
|
-
const raw$
|
|
7492
|
+
const raw$2 = String(t.content ?? "");
|
|
7489
7493
|
const closeRe = new RegExp(`<\\/\\s*${tag}\\s*>`, "i");
|
|
7490
|
-
t.loading = closeRe.test(raw$
|
|
7491
|
-
const closeMatch = closeRe.exec(raw$
|
|
7492
|
-
const endTagIndex = closeMatch ? closeMatch.index : -1;
|
|
7493
|
-
const closeLen = closeMatch ? closeMatch[0].length : 0;
|
|
7494
|
-
if (endTagIndex !== -1) {
|
|
7495
|
-
const rawForNode = raw$
|
|
7494
|
+
t.loading = closeRe.test(raw$2) ? false : t.loading !== void 0 ? t.loading : true;
|
|
7495
|
+
const closeMatch$1 = closeRe.exec(raw$2);
|
|
7496
|
+
const endTagIndex$1 = closeMatch$1 ? closeMatch$1.index : -1;
|
|
7497
|
+
const closeLen$1 = closeMatch$1 ? closeMatch$1[0].length : 0;
|
|
7498
|
+
if (endTagIndex$1 !== -1) {
|
|
7499
|
+
const rawForNode = raw$2.slice(0, endTagIndex$1 + closeLen$1);
|
|
7500
|
+
let inner = "";
|
|
7501
|
+
const openEnd = findTagCloseIndexOutsideQuotes$1(raw$2);
|
|
7502
|
+
if (openEnd !== -1 && openEnd < endTagIndex$1) inner = raw$2.slice(openEnd + 1, endTagIndex$1);
|
|
7503
|
+
t.children = [{
|
|
7504
|
+
type: tag,
|
|
7505
|
+
content: inner,
|
|
7506
|
+
raw: rawForNode,
|
|
7507
|
+
attrs: [],
|
|
7508
|
+
tag,
|
|
7509
|
+
loading: false
|
|
7510
|
+
}];
|
|
7496
7511
|
t.content = rawForNode;
|
|
7497
7512
|
t.raw = rawForNode;
|
|
7498
|
-
const afterTrimmed = (raw$
|
|
7513
|
+
const afterTrimmed = (raw$2.slice(endTagIndex$1 + closeLen$1) || "").replace(/^\s+/, "");
|
|
7499
7514
|
if (afterTrimmed) toks.splice(i + 1, 0, afterTrimmed.startsWith("<") ? {
|
|
7500
7515
|
type: "html_block",
|
|
7501
7516
|
content: afterTrimmed
|
|
@@ -7504,11 +7519,14 @@ function applyFixHtmlInlineTokens(md, options = {}) {
|
|
|
7504
7519
|
content: afterTrimmed,
|
|
7505
7520
|
raw: afterTrimmed
|
|
7506
7521
|
});
|
|
7507
|
-
}
|
|
7508
|
-
|
|
7509
|
-
|
|
7510
|
-
|
|
7511
|
-
|
|
7522
|
+
} else t.children = [{
|
|
7523
|
+
type: tag,
|
|
7524
|
+
content: "",
|
|
7525
|
+
raw: raw$2,
|
|
7526
|
+
attrs: [],
|
|
7527
|
+
tag,
|
|
7528
|
+
loading: true
|
|
7529
|
+
}];
|
|
7512
7530
|
continue;
|
|
7513
7531
|
}
|
|
7514
7532
|
if ([
|
|
@@ -7524,7 +7542,6 @@ function applyFixHtmlInlineTokens(md, options = {}) {
|
|
|
7524
7542
|
"li"
|
|
7525
7543
|
].includes(tag)) continue;
|
|
7526
7544
|
t.type = "inline";
|
|
7527
|
-
const loading = new RegExp(`<\\/\\s*${tag}\\s*>`, "i").test(String(t.content ?? "")) ? false : t.loading !== void 0 ? t.loading : true;
|
|
7528
7545
|
const attrs = [];
|
|
7529
7546
|
const attrRegex = /\s([\w:-]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+)))?/g;
|
|
7530
7547
|
let match;
|
|
@@ -7533,44 +7550,34 @@ function applyFixHtmlInlineTokens(md, options = {}) {
|
|
|
7533
7550
|
const attrValue = match[2] || match[3] || match[4] || "";
|
|
7534
7551
|
attrs.push([attrName, attrValue]);
|
|
7535
7552
|
}
|
|
7536
|
-
|
|
7537
|
-
|
|
7538
|
-
|
|
7539
|
-
|
|
7540
|
-
|
|
7541
|
-
const rawForNode =
|
|
7542
|
-
|
|
7543
|
-
const openEnd = findTagCloseIndexOutsideQuotes$1(raw$1);
|
|
7544
|
-
if (openEnd !== -1) {
|
|
7545
|
-
if (endTagIndex !== -1 && openEnd < endTagIndex) inner = raw$1.slice(openEnd + 1, endTagIndex);
|
|
7546
|
-
else if (endTagIndex === -1) inner = raw$1.slice(openEnd + 1).replace(/<.*$/, "");
|
|
7547
|
-
}
|
|
7553
|
+
const raw$1 = String(t.content ?? "");
|
|
7554
|
+
const closeMatch = new RegExp(`<\\/\\s*${tag}\\s*>`, "i").exec(raw$1);
|
|
7555
|
+
const endTagIndex = closeMatch ? closeMatch.index : -1;
|
|
7556
|
+
const closeLen = closeMatch ? closeMatch[0].length : 0;
|
|
7557
|
+
if (endTagIndex !== -1) {
|
|
7558
|
+
const rawForNode = raw$1.slice(0, endTagIndex + closeLen);
|
|
7559
|
+
const afterTrimmed = (raw$1.slice(endTagIndex + closeLen) || "").replace(/^\s+/, "");
|
|
7548
7560
|
t.children = [{
|
|
7549
|
-
type:
|
|
7550
|
-
content:
|
|
7551
|
-
raw: rawForNode,
|
|
7552
|
-
attrs,
|
|
7561
|
+
type: "html_block",
|
|
7562
|
+
content: rawForNode,
|
|
7553
7563
|
tag,
|
|
7554
|
-
loading
|
|
7564
|
+
loading: false
|
|
7555
7565
|
}];
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
7562
|
-
|
|
7563
|
-
|
|
7564
|
-
|
|
7565
|
-
|
|
7566
|
-
raw: afterTrimmed
|
|
7567
|
-
});
|
|
7568
|
-
}
|
|
7566
|
+
t.content = rawForNode;
|
|
7567
|
+
t.raw = rawForNode;
|
|
7568
|
+
if (afterTrimmed) toks.splice(i + 1, 0, afterTrimmed.startsWith("<") ? {
|
|
7569
|
+
type: "html_block",
|
|
7570
|
+
content: afterTrimmed
|
|
7571
|
+
} : {
|
|
7572
|
+
type: "text",
|
|
7573
|
+
content: afterTrimmed,
|
|
7574
|
+
raw: afterTrimmed
|
|
7575
|
+
});
|
|
7569
7576
|
} else t.children = [{
|
|
7570
7577
|
type: "html_block",
|
|
7571
7578
|
content: t.content,
|
|
7572
7579
|
tag,
|
|
7573
|
-
loading
|
|
7580
|
+
loading: true
|
|
7574
7581
|
}];
|
|
7575
7582
|
continue;
|
|
7576
7583
|
}
|
|
@@ -7622,6 +7629,81 @@ function applyFixHtmlInlineTokens(md, options = {}) {
|
|
|
7622
7629
|
});
|
|
7623
7630
|
}
|
|
7624
7631
|
|
|
7632
|
+
//#endregion
|
|
7633
|
+
//#region src/plugins/fixIndentedCodeBlock.ts
|
|
7634
|
+
/**
|
|
7635
|
+
* Check if a line looks like code (vs plain text or HTML entities).
|
|
7636
|
+
* Returns true if the line appears to be code.
|
|
7637
|
+
*/
|
|
7638
|
+
function looksLikeCode(line) {
|
|
7639
|
+
const trimmed = line.trim();
|
|
7640
|
+
if (!trimmed) return false;
|
|
7641
|
+
if (/^&[a-z0-9#]+;/i.test(trimmed)) return false;
|
|
7642
|
+
if (/^(?:const|let|var|function|class|import|export|if|for|while|return|await|async|yield|try|catch|throw|new|typeof|instanceof|switch|case|break|continue|def|ruby|perl|print|echo|true|false|null|undefined|NaN|Infinity|this)\b/.test(trimmed)) return true;
|
|
7643
|
+
if (/[a-z_$][\w$]*(?:\.[a-z_$][\w$]*|\['[^']*'\]|\["[^"]*"\]|\[\d+\])*\s*\(/i.test(trimmed)) return true;
|
|
7644
|
+
if (/[a-z_$][\w$]*(?:\.[a-z_$][\w$]*|\['[^']*'\]|\["[^"]*"\]|\[[\d+\]])+/i.test(trimmed)) return true;
|
|
7645
|
+
if (/\w+\s*(?:===?|!==?|<=?|>=?|\+\+|--|&&|\|\||\?\.)/.test(trimmed)) return true;
|
|
7646
|
+
if (/^(?:!!|\+\+|--)\s*\w/.test(trimmed)) return true;
|
|
7647
|
+
if (/[\w$]+\s*(?:\+=|-=|\*=|\/=|%=|\*\*=|=)/.test(trimmed)) return true;
|
|
7648
|
+
if (/^(?:https?:\/\/|ftp:\/\/|file:\/\/|\/\/|www\.)/i.test(trimmed)) return true;
|
|
7649
|
+
if (/`[^`]*\$\{[^}]*\}[^`]*`/.test(trimmed)) return true;
|
|
7650
|
+
if (/<\/?[A-Z][a-zA-Z0-9]*/.test(trimmed)) return true;
|
|
7651
|
+
if (/<[a-z][a-z0-9]*\s[^>]+>/.test(trimmed)) return true;
|
|
7652
|
+
if (/^(["'`]).*\1\s*[;,]?$/.test(trimmed)) return true;
|
|
7653
|
+
if (/^\[[\s\S]*\]$/.test(trimmed) || /^\{[\s\S]*\}$/.test(trimmed) || /^\(\s*\)$/.test(trimmed)) return true;
|
|
7654
|
+
if (/[\w$]+(?:\s*[+\-*/%<>=!&|^~:]+\s*[\w$]+|\s*\.\s*[\w$]+)/.test(trimmed)) return true;
|
|
7655
|
+
if (/=>|->|::/.test(trimmed)) return true;
|
|
7656
|
+
if (/^@[\w.$]+$/.test(trimmed)) return true;
|
|
7657
|
+
if (/^(?:0x[0-9a-fA-F]+|0b[01]+|0o[0-7]+|\d+(?:\.\d*)?(?:px|em|rem|%|vh|vw|deg|s|ms)?)$/.test(trimmed)) return true;
|
|
7658
|
+
if (/^\$[\w$]+\s*[=:]/.test(trimmed)) return true;
|
|
7659
|
+
if (/\|\s*\w+|\w+\s*\|/.test(trimmed)) return true;
|
|
7660
|
+
if (/^(?:git|npm|yarn|pnpm|bun|pip|cargo|go|rust|python|node|java|mvn|gradle|docker|kubectl)\s+/.test(trimmed)) return true;
|
|
7661
|
+
if (/(?:console|window|document|Math|JSON|Date|Array|Object|String|Number|Boolean)\.[a-zA-Z]/.test(trimmed)) return true;
|
|
7662
|
+
if (/^(?:\/\/|#|\/\*|\*\/|<!--|-->)/.test(trimmed)) return true;
|
|
7663
|
+
if (/^(?:<<<|<<\s*['"]?\w+['"]?)/.test(trimmed)) return true;
|
|
7664
|
+
return false;
|
|
7665
|
+
}
|
|
7666
|
+
function applyFixIndentedCodeBlock(md, options = {}) {
|
|
7667
|
+
if (options.enabled === false) return;
|
|
7668
|
+
md.core.ruler.after("inline", "fix_indented_code_block", (state) => {
|
|
7669
|
+
const tokens = state.tokens;
|
|
7670
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
7671
|
+
const token = tokens[i];
|
|
7672
|
+
if (token.type !== "code_block") continue;
|
|
7673
|
+
const content = String(token.content ?? "").trim();
|
|
7674
|
+
if (!content) continue;
|
|
7675
|
+
const lines = content.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
7676
|
+
if (lines.length === 1 && !looksLikeCode(lines[0] ?? "")) {
|
|
7677
|
+
const textContent = lines[0] ?? "";
|
|
7678
|
+
tokens.splice(i, 1, {
|
|
7679
|
+
type: "paragraph_open",
|
|
7680
|
+
tag: "p",
|
|
7681
|
+
nesting: 1,
|
|
7682
|
+
level: token.level
|
|
7683
|
+
}, {
|
|
7684
|
+
type: "inline",
|
|
7685
|
+
tag: "",
|
|
7686
|
+
nesting: 0,
|
|
7687
|
+
level: token.level,
|
|
7688
|
+
content: textContent,
|
|
7689
|
+
children: [{
|
|
7690
|
+
type: "text",
|
|
7691
|
+
content: textContent,
|
|
7692
|
+
level: token.level + 1
|
|
7693
|
+
}],
|
|
7694
|
+
block: true
|
|
7695
|
+
}, {
|
|
7696
|
+
type: "paragraph_close",
|
|
7697
|
+
tag: "p",
|
|
7698
|
+
nesting: -1,
|
|
7699
|
+
level: token.level
|
|
7700
|
+
});
|
|
7701
|
+
i += 2;
|
|
7702
|
+
}
|
|
7703
|
+
}
|
|
7704
|
+
});
|
|
7705
|
+
}
|
|
7706
|
+
|
|
7625
7707
|
//#endregion
|
|
7626
7708
|
//#region src/plugins/fixLinkTokens.ts
|
|
7627
7709
|
function textToken(content) {
|
|
@@ -8989,6 +9071,7 @@ function factory(opts = {}) {
|
|
|
8989
9071
|
...opts.mathOptions ?? {}
|
|
8990
9072
|
});
|
|
8991
9073
|
if (opts.enableContainers ?? true) applyContainers(md);
|
|
9074
|
+
if (opts.enableFixIndentedCodeBlock !== false) applyFixIndentedCodeBlock(md);
|
|
8992
9075
|
applyFixLinkTokens(md);
|
|
8993
9076
|
applyFixStrongTokens(md);
|
|
8994
9077
|
applyFixListItem(md);
|
|
@@ -10711,6 +10794,8 @@ function parseFootnote(tokens, index, options) {
|
|
|
10711
10794
|
//#region src/parser/node-parsers/heading-parser.ts
|
|
10712
10795
|
function parseHeading(tokens, index, options) {
|
|
10713
10796
|
const token = tokens[index];
|
|
10797
|
+
const attrs = token?.attrs;
|
|
10798
|
+
const attrsRecord = Array.isArray(attrs) && attrs.length ? Object.fromEntries(attrs.filter((pair) => Array.isArray(pair) && pair.length >= 1 && pair[0]).map(([name, value]) => [String(name), value == null || value === "" ? true : String(value)])) : void 0;
|
|
10714
10799
|
const levelStr = String(token.tag?.substring(1) ?? "1");
|
|
10715
10800
|
const headingLevel = Number.parseInt(levelStr, 10);
|
|
10716
10801
|
const headingContentToken = tokens[index + 1];
|
|
@@ -10719,6 +10804,7 @@ function parseHeading(tokens, index, options) {
|
|
|
10719
10804
|
type: "heading",
|
|
10720
10805
|
level: headingLevel,
|
|
10721
10806
|
text: headingContent,
|
|
10807
|
+
...attrsRecord ? { attrs: attrsRecord } : {},
|
|
10722
10808
|
children: parseInlineTokens(headingContentToken.children || [], headingContent, void 0, {
|
|
10723
10809
|
requireClosingStrong: options?.requireClosingStrong,
|
|
10724
10810
|
customHtmlTags: options?.customHtmlTags
|
|
@@ -11398,6 +11484,207 @@ function normalizeCustomHtmlOpeningTagSameLine(markdown, tags) {
|
|
|
11398
11484
|
}
|
|
11399
11485
|
return out;
|
|
11400
11486
|
}
|
|
11487
|
+
function ensureBlankLineBeforeCustomHtmlBlocks(markdown, tags) {
|
|
11488
|
+
if (!markdown || !tags.length) return markdown;
|
|
11489
|
+
const tagSet = new Set(tags.map((t) => String(t ?? "").toLowerCase()));
|
|
11490
|
+
if (!tagSet.size) return markdown;
|
|
11491
|
+
const isIndentWs = (ch) => ch === " " || ch === " ";
|
|
11492
|
+
const isIndentedCodeLine = (line) => {
|
|
11493
|
+
if (!line) return false;
|
|
11494
|
+
if (line[0] === " ") return true;
|
|
11495
|
+
let spaces = 0;
|
|
11496
|
+
for (let i = 0; i < line.length; i++) {
|
|
11497
|
+
const ch = line[i];
|
|
11498
|
+
if (ch === " ") {
|
|
11499
|
+
spaces++;
|
|
11500
|
+
if (spaces >= 4) return true;
|
|
11501
|
+
continue;
|
|
11502
|
+
}
|
|
11503
|
+
if (ch === " ") return true;
|
|
11504
|
+
break;
|
|
11505
|
+
}
|
|
11506
|
+
return false;
|
|
11507
|
+
};
|
|
11508
|
+
const isNameChar = (ch) => {
|
|
11509
|
+
const c = ch.charCodeAt(0);
|
|
11510
|
+
return c >= 65 && c <= 90 || c >= 97 && c <= 122 || c >= 48 && c <= 57 || ch === "_" || ch === "-" || ch === ":";
|
|
11511
|
+
};
|
|
11512
|
+
const trimStartIndentWs = (s) => {
|
|
11513
|
+
let i = 0;
|
|
11514
|
+
while (i < s.length && isIndentWs(s[i])) i++;
|
|
11515
|
+
return s.slice(i);
|
|
11516
|
+
};
|
|
11517
|
+
const parseBlockquotePrefix = (rawLine) => {
|
|
11518
|
+
let i = 0;
|
|
11519
|
+
let saw = false;
|
|
11520
|
+
let prefixEnd = 0;
|
|
11521
|
+
while (i < rawLine.length) {
|
|
11522
|
+
while (i < rawLine.length && isIndentWs(rawLine[i])) i++;
|
|
11523
|
+
if (i >= rawLine.length || rawLine[i] !== ">") break;
|
|
11524
|
+
saw = true;
|
|
11525
|
+
i++;
|
|
11526
|
+
while (i < rawLine.length && isIndentWs(rawLine[i])) i++;
|
|
11527
|
+
prefixEnd = i;
|
|
11528
|
+
}
|
|
11529
|
+
if (!saw) return null;
|
|
11530
|
+
const prefix = rawLine.slice(0, prefixEnd);
|
|
11531
|
+
return {
|
|
11532
|
+
prefix,
|
|
11533
|
+
key: prefix.replace(/[ \t]+$/, ""),
|
|
11534
|
+
content: rawLine.slice(prefixEnd)
|
|
11535
|
+
};
|
|
11536
|
+
};
|
|
11537
|
+
const previousLineLooksHtmlish = (line) => {
|
|
11538
|
+
return trimStartIndentWs(line).startsWith("<");
|
|
11539
|
+
};
|
|
11540
|
+
const lineIsBlank = (line) => {
|
|
11541
|
+
for (let i = 0; i < line.length; i++) {
|
|
11542
|
+
const ch = line[i];
|
|
11543
|
+
if (ch !== " " && ch !== " ") return false;
|
|
11544
|
+
}
|
|
11545
|
+
return true;
|
|
11546
|
+
};
|
|
11547
|
+
const parseOpeningCustomTagName = (line) => {
|
|
11548
|
+
if (isIndentedCodeLine(line)) return "";
|
|
11549
|
+
const trimmed = trimStartIndentWs(line);
|
|
11550
|
+
if (!trimmed.startsWith("<")) return "";
|
|
11551
|
+
let i = 1;
|
|
11552
|
+
while (i < trimmed.length && isIndentWs(trimmed[i])) i++;
|
|
11553
|
+
if (i >= trimmed.length) return "";
|
|
11554
|
+
if (trimmed[i] === "/" || trimmed[i] === "!" || trimmed[i] === "?") return "";
|
|
11555
|
+
const nameStart = i;
|
|
11556
|
+
while (i < trimmed.length && isNameChar(trimmed[i])) i++;
|
|
11557
|
+
if (i === nameStart) return "";
|
|
11558
|
+
const name = trimmed.slice(nameStart, i).toLowerCase();
|
|
11559
|
+
if (!tagSet.has(name)) return "";
|
|
11560
|
+
const next = trimmed[i];
|
|
11561
|
+
if (next && next !== " " && next !== " " && next !== ">" && next !== "/") return "";
|
|
11562
|
+
return name;
|
|
11563
|
+
};
|
|
11564
|
+
const parseLineStartCustomTag = (line) => {
|
|
11565
|
+
if (isIndentedCodeLine(line)) return null;
|
|
11566
|
+
const trimmed = trimStartIndentWs(line);
|
|
11567
|
+
if (!trimmed.startsWith("<")) return null;
|
|
11568
|
+
let i = 1;
|
|
11569
|
+
while (i < trimmed.length && isIndentWs(trimmed[i])) i++;
|
|
11570
|
+
if (i >= trimmed.length) return null;
|
|
11571
|
+
const isClose = trimmed[i] === "/";
|
|
11572
|
+
if (isClose) {
|
|
11573
|
+
i++;
|
|
11574
|
+
while (i < trimmed.length && isIndentWs(trimmed[i])) i++;
|
|
11575
|
+
}
|
|
11576
|
+
const next = trimmed[i];
|
|
11577
|
+
if (!next || next === "!" || next === "?") return null;
|
|
11578
|
+
const nameStart = i;
|
|
11579
|
+
while (i < trimmed.length && isNameChar(trimmed[i])) i++;
|
|
11580
|
+
if (i === nameStart) return null;
|
|
11581
|
+
const name = trimmed.slice(nameStart, i).toLowerCase();
|
|
11582
|
+
if (!tagSet.has(name)) return null;
|
|
11583
|
+
const boundary = trimmed[i];
|
|
11584
|
+
if (boundary && boundary !== " " && boundary !== " " && boundary !== ">" && boundary !== "/") return null;
|
|
11585
|
+
if (isClose) return {
|
|
11586
|
+
type: "close",
|
|
11587
|
+
name
|
|
11588
|
+
};
|
|
11589
|
+
if (/\/\s*>\s*$/.test(trimmed)) return {
|
|
11590
|
+
type: "open",
|
|
11591
|
+
name,
|
|
11592
|
+
complete: true
|
|
11593
|
+
};
|
|
11594
|
+
const gt = trimmed.indexOf(">", i);
|
|
11595
|
+
if (gt !== -1) {
|
|
11596
|
+
const after = trimmed.slice(gt + 1);
|
|
11597
|
+
if (new RegExp(`<\\s*\\/\\s*${name}\\s*>`, "i").test(after)) return {
|
|
11598
|
+
type: "open",
|
|
11599
|
+
name,
|
|
11600
|
+
complete: true
|
|
11601
|
+
};
|
|
11602
|
+
}
|
|
11603
|
+
return {
|
|
11604
|
+
type: "open",
|
|
11605
|
+
name,
|
|
11606
|
+
complete: false
|
|
11607
|
+
};
|
|
11608
|
+
};
|
|
11609
|
+
let inFence = false;
|
|
11610
|
+
let fenceChar = "";
|
|
11611
|
+
let fenceLen = 0;
|
|
11612
|
+
const parseFenceMarker = (line) => {
|
|
11613
|
+
let i = 0;
|
|
11614
|
+
while (i < line.length && isIndentWs(line[i])) i++;
|
|
11615
|
+
const ch = line[i];
|
|
11616
|
+
if (ch !== "`" && ch !== "~") return null;
|
|
11617
|
+
let j = i;
|
|
11618
|
+
while (j < line.length && line[j] === ch) j++;
|
|
11619
|
+
const len = j - i;
|
|
11620
|
+
if (len < 3) return null;
|
|
11621
|
+
return {
|
|
11622
|
+
markerChar: ch,
|
|
11623
|
+
markerLen: len,
|
|
11624
|
+
rest: line.slice(j)
|
|
11625
|
+
};
|
|
11626
|
+
};
|
|
11627
|
+
const fenceMatchLine = (rawLine) => parseFenceMarker(rawLine);
|
|
11628
|
+
let out = "";
|
|
11629
|
+
let idx = 0;
|
|
11630
|
+
let prevLineBlank = true;
|
|
11631
|
+
let prevLineHtmlish = false;
|
|
11632
|
+
let lastNewline = "\n";
|
|
11633
|
+
const customBlockStack = [];
|
|
11634
|
+
let prevQuoteKey = "";
|
|
11635
|
+
while (idx < markdown.length) {
|
|
11636
|
+
const nl = markdown.indexOf("\n", idx);
|
|
11637
|
+
const hasNl = nl !== -1;
|
|
11638
|
+
const isCrlf = hasNl && nl > idx && markdown[nl - 1] === "\r";
|
|
11639
|
+
const lineEnd = hasNl ? isCrlf ? nl - 1 : nl : markdown.length;
|
|
11640
|
+
const line = markdown.slice(idx, lineEnd);
|
|
11641
|
+
const newline$1 = hasNl ? isCrlf ? "\r\n" : "\n" : "";
|
|
11642
|
+
const blockquote$1 = parseBlockquotePrefix(line);
|
|
11643
|
+
const quoteKey = blockquote$1?.key ?? "";
|
|
11644
|
+
const contentLine = blockquote$1?.content ?? line;
|
|
11645
|
+
const fenceMatch = fenceMatchLine(contentLine);
|
|
11646
|
+
if (fenceMatch) if (inFence) {
|
|
11647
|
+
if (fenceMatch.markerChar === fenceChar && fenceMatch.markerLen >= fenceLen) {
|
|
11648
|
+
if (/^\s*$/.test(fenceMatch.rest)) {
|
|
11649
|
+
inFence = false;
|
|
11650
|
+
fenceChar = "";
|
|
11651
|
+
fenceLen = 0;
|
|
11652
|
+
}
|
|
11653
|
+
}
|
|
11654
|
+
} else {
|
|
11655
|
+
inFence = true;
|
|
11656
|
+
fenceChar = fenceMatch.markerChar;
|
|
11657
|
+
fenceLen = fenceMatch.markerLen;
|
|
11658
|
+
}
|
|
11659
|
+
const insideCustomBlock = customBlockStack.length > 0;
|
|
11660
|
+
if (!inFence && !insideCustomBlock) {
|
|
11661
|
+
if (parseOpeningCustomTagName(contentLine) && !prevLineBlank && !prevLineHtmlish) {
|
|
11662
|
+
if (quoteKey && prevQuoteKey && quoteKey === prevQuoteKey) out += `${quoteKey}${lastNewline}`;
|
|
11663
|
+
else if (!quoteKey) out += lastNewline;
|
|
11664
|
+
}
|
|
11665
|
+
}
|
|
11666
|
+
out += line;
|
|
11667
|
+
out += newline$1;
|
|
11668
|
+
if (newline$1) lastNewline = newline$1;
|
|
11669
|
+
if (!inFence) {
|
|
11670
|
+
const tag = parseLineStartCustomTag(contentLine);
|
|
11671
|
+
if (tag) {
|
|
11672
|
+
if (tag.type === "open") {
|
|
11673
|
+
if (!tag.complete) customBlockStack.push(tag.name);
|
|
11674
|
+
} else for (let j = customBlockStack.length - 1; j >= 0; j--) if (customBlockStack[j] === tag.name) {
|
|
11675
|
+
customBlockStack.length = j;
|
|
11676
|
+
break;
|
|
11677
|
+
}
|
|
11678
|
+
}
|
|
11679
|
+
}
|
|
11680
|
+
const blank = lineIsBlank(contentLine);
|
|
11681
|
+
prevLineBlank = blank;
|
|
11682
|
+
prevLineHtmlish = !blank && previousLineLooksHtmlish(contentLine);
|
|
11683
|
+
prevQuoteKey = quoteKey;
|
|
11684
|
+
idx = hasNl ? nl + 1 : markdown.length;
|
|
11685
|
+
}
|
|
11686
|
+
return out;
|
|
11687
|
+
}
|
|
11401
11688
|
function parseMarkdownToStructure(markdown, md, options = {}) {
|
|
11402
11689
|
const isFinal = !!options.final;
|
|
11403
11690
|
let safeMarkdown = (markdown ?? "").toString().replace(/([^\\])\r(ight|ho)/g, "$1\\r$2").replace(/([^\\])\n(abla|eq|ot|exists)/g, "$1\\n$2");
|
|
@@ -11421,6 +11708,7 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
|
|
|
11421
11708
|
}).filter(Boolean);
|
|
11422
11709
|
if (tags.length) {
|
|
11423
11710
|
safeMarkdown = normalizeCustomHtmlOpeningTagSameLine(safeMarkdown, tags);
|
|
11711
|
+
safeMarkdown = ensureBlankLineBeforeCustomHtmlBlocks(safeMarkdown, tags);
|
|
11424
11712
|
if (!safeMarkdown.includes("</")) {} else for (const tag of tags) {
|
|
11425
11713
|
const re = new RegExp(String.raw`(^[\t ]*<\s*\/\s*${tag}\s*>[\t ]*)(\r?\n)(?![\t ]*\r?\n|$)`, "gim");
|
|
11426
11714
|
safeMarkdown = safeMarkdown.replace(re, "$1$2$2");
|