stream-markdown-parser 0.0.42 → 0.0.44
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.map +1 -1
- package/dist/index.js +424 -57
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -601,7 +601,7 @@ var require_markdown_it_task_checkbox = /* @__PURE__ */ __commonJS({ "../../node
|
|
|
601
601
|
}) });
|
|
602
602
|
|
|
603
603
|
//#endregion
|
|
604
|
-
//#region ../../node_modules/.pnpm/markdown-it-ts@0.0.
|
|
604
|
+
//#region ../../node_modules/.pnpm/markdown-it-ts@0.0.3/node_modules/markdown-it-ts/dist/chunk-Bp6m_JJh.js
|
|
605
605
|
var import_markdown_it_task_checkbox = /* @__PURE__ */ __toESM(require_markdown_it_task_checkbox(), 1);
|
|
606
606
|
var __defProp = Object.defineProperty;
|
|
607
607
|
var __export = (all) => {
|
|
@@ -2187,7 +2187,7 @@ var require_punycode = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/pu
|
|
|
2187
2187
|
}) });
|
|
2188
2188
|
|
|
2189
2189
|
//#endregion
|
|
2190
|
-
//#region ../../node_modules/.pnpm/markdown-it-ts@0.0.
|
|
2190
|
+
//#region ../../node_modules/.pnpm/markdown-it-ts@0.0.3/node_modules/markdown-it-ts/dist/index.js
|
|
2191
2191
|
var import_punycode = /* @__PURE__ */ __toESM(require_punycode(), 1);
|
|
2192
2192
|
var utils_exports = /* @__PURE__ */ __export({
|
|
2193
2193
|
arrayReplaceAt: () => arrayReplaceAt,
|
|
@@ -5302,35 +5302,20 @@ var StateInline = class {
|
|
|
5302
5302
|
const { src, posMax } = this;
|
|
5303
5303
|
const marker = src.charCodeAt(start);
|
|
5304
5304
|
let pos = start;
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
count++;
|
|
5308
|
-
pos++;
|
|
5309
|
-
}
|
|
5305
|
+
while (pos < posMax && src.charCodeAt(pos) === marker) pos++;
|
|
5306
|
+
const count = pos - start;
|
|
5310
5307
|
if (count < 1) return null;
|
|
5311
5308
|
const lastChar = start > 0 ? src.charCodeAt(start - 1) : 32;
|
|
5312
5309
|
const nextChar = pos < posMax ? src.charCodeAt(pos) : 32;
|
|
5313
|
-
const isLastPunctChar = lastChar
|
|
5314
|
-
const isNextPunctChar = nextChar
|
|
5315
|
-
const isLastWhiteSpace = lastChar
|
|
5316
|
-
const isNextWhiteSpace = nextChar
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
if (isNextWhiteSpace) can_open = false;
|
|
5320
|
-
else if (isNextPunctChar) {
|
|
5321
|
-
if (!(isLastWhiteSpace || isLastPunctChar)) can_open = false;
|
|
5322
|
-
}
|
|
5323
|
-
if (isLastWhiteSpace) can_close = false;
|
|
5324
|
-
else if (isLastPunctChar) {
|
|
5325
|
-
if (!(isNextWhiteSpace || isNextPunctChar)) can_close = false;
|
|
5326
|
-
}
|
|
5327
|
-
if (!canSplitWord) {
|
|
5328
|
-
can_open = can_open && (!isLastPunctChar || isLastWhiteSpace);
|
|
5329
|
-
can_close = can_close && (!isNextPunctChar || isNextWhiteSpace);
|
|
5330
|
-
}
|
|
5310
|
+
const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar));
|
|
5311
|
+
const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar));
|
|
5312
|
+
const isLastWhiteSpace = isWhiteSpace(lastChar);
|
|
5313
|
+
const isNextWhiteSpace = isWhiteSpace(nextChar);
|
|
5314
|
+
const left_flanking = !isNextWhiteSpace && (!isNextPunctChar || isLastWhiteSpace || isLastPunctChar);
|
|
5315
|
+
const right_flanking = !isLastWhiteSpace && (!isLastPunctChar || isNextWhiteSpace || isNextPunctChar);
|
|
5331
5316
|
return {
|
|
5332
|
-
can_open,
|
|
5333
|
-
can_close,
|
|
5317
|
+
can_open: left_flanking && (canSplitWord || !right_flanking || isLastPunctChar),
|
|
5318
|
+
can_close: right_flanking && (canSplitWord || !left_flanking || isNextPunctChar),
|
|
5334
5319
|
length: count
|
|
5335
5320
|
};
|
|
5336
5321
|
}
|
|
@@ -6834,6 +6819,7 @@ const BASE_COMMON_HTML_TAGS = new Set([
|
|
|
6834
6819
|
"del",
|
|
6835
6820
|
"dfn",
|
|
6836
6821
|
"em",
|
|
6822
|
+
"font",
|
|
6837
6823
|
"i",
|
|
6838
6824
|
"img",
|
|
6839
6825
|
"input",
|
|
@@ -6889,7 +6875,7 @@ const BASE_COMMON_HTML_TAGS = new Set([
|
|
|
6889
6875
|
const OPEN_TAG_RE = /<([A-Z][\w-]*)(?=[\s/>]|$)/gi;
|
|
6890
6876
|
const CLOSE_TAG_RE = /<\/\s*([A-Z][\w-]*)(?=[\s/>]|$)/gi;
|
|
6891
6877
|
const TAG_NAME_AT_START_RE = /^<\s*(?:\/\s*)?([A-Z][\w-]*)/i;
|
|
6892
|
-
function findTagCloseIndexOutsideQuotes(html) {
|
|
6878
|
+
function findTagCloseIndexOutsideQuotes$1(html) {
|
|
6893
6879
|
let inSingle = false;
|
|
6894
6880
|
let inDouble = false;
|
|
6895
6881
|
for (let i = 0; i < html.length; i++) {
|
|
@@ -6932,8 +6918,8 @@ function findFirstIncompleteTag(content, tagSet) {
|
|
|
6932
6918
|
const idx = m.index ?? -1;
|
|
6933
6919
|
if (idx < 0) continue;
|
|
6934
6920
|
const tag = (m[1] ?? "").toLowerCase();
|
|
6935
|
-
if (!
|
|
6936
|
-
if (findTagCloseIndexOutsideQuotes(content.slice(idx)) !== -1) continue;
|
|
6921
|
+
if (!isCommonHtmlTagOrPrefix(tag, tagSet)) continue;
|
|
6922
|
+
if (findTagCloseIndexOutsideQuotes$1(content.slice(idx)) !== -1) continue;
|
|
6937
6923
|
if (!first || idx < first.index) first = {
|
|
6938
6924
|
index: idx,
|
|
6939
6925
|
tag,
|
|
@@ -6945,7 +6931,7 @@ function findFirstIncompleteTag(content, tagSet) {
|
|
|
6945
6931
|
if (idx < 0) continue;
|
|
6946
6932
|
const tag = (m[1] ?? "").toLowerCase();
|
|
6947
6933
|
if (!isCommonHtmlTagOrPrefix(tag, tagSet)) continue;
|
|
6948
|
-
if (findTagCloseIndexOutsideQuotes(content.slice(idx)) !== -1) continue;
|
|
6934
|
+
if (findTagCloseIndexOutsideQuotes$1(content.slice(idx)) !== -1) continue;
|
|
6949
6935
|
if (!first || idx < first.index) first = {
|
|
6950
6936
|
index: idx,
|
|
6951
6937
|
tag,
|
|
@@ -7011,7 +6997,7 @@ function fixStreamingHtmlInlineChildren(children, tagSet) {
|
|
|
7011
6997
|
cursor = lt + 1;
|
|
7012
6998
|
continue;
|
|
7013
6999
|
}
|
|
7014
|
-
const closeIdx = findTagCloseIndexOutsideQuotes(sub);
|
|
7000
|
+
const closeIdx = findTagCloseIndexOutsideQuotes$1(sub);
|
|
7015
7001
|
if (closeIdx === -1) {
|
|
7016
7002
|
pushTextPart("<", baseToken);
|
|
7017
7003
|
cursor = lt + 1;
|
|
@@ -7049,7 +7035,7 @@ function fixStreamingHtmlInlineChildren(children, tagSet) {
|
|
|
7049
7035
|
if (pending) {
|
|
7050
7036
|
pending.buffer += tokenToRaw$1(child);
|
|
7051
7037
|
pendingAtEnd = pending.buffer;
|
|
7052
|
-
const closeIdx = findTagCloseIndexOutsideQuotes(pending.buffer);
|
|
7038
|
+
const closeIdx = findTagCloseIndexOutsideQuotes$1(pending.buffer);
|
|
7053
7039
|
if (closeIdx === -1) continue;
|
|
7054
7040
|
const tagChunk = pending.buffer.slice(0, closeIdx + 1);
|
|
7055
7041
|
const afterChunk = pending.buffer.slice(closeIdx + 1);
|
|
@@ -7067,7 +7053,7 @@ function fixStreamingHtmlInlineChildren(children, tagSet) {
|
|
|
7067
7053
|
if (child.type === "html_inline") {
|
|
7068
7054
|
const content = tokenToRaw$1(child);
|
|
7069
7055
|
const tagName = (content.match(TAG_NAME_AT_START_RE)?.[1] ?? "").toLowerCase();
|
|
7070
|
-
if (tagName && tagSet.has(tagName) && findTagCloseIndexOutsideQuotes(content) === -1) {
|
|
7056
|
+
if (tagName && tagSet.has(tagName) && findTagCloseIndexOutsideQuotes$1(content) === -1) {
|
|
7071
7057
|
pending = {
|
|
7072
7058
|
tag: tagName,
|
|
7073
7059
|
buffer: content,
|
|
@@ -7147,10 +7133,69 @@ function applyFixHtmlInlineTokens(md, options = {}) {
|
|
|
7147
7133
|
const tagStack = [];
|
|
7148
7134
|
for (let i = 0; i < toks.length; i++) {
|
|
7149
7135
|
const t = toks[i];
|
|
7136
|
+
if (tagStack.length > 0) {
|
|
7137
|
+
const [openTag, openIndex] = tagStack[tagStack.length - 1];
|
|
7138
|
+
if (i !== openIndex) {
|
|
7139
|
+
if (t.type === "paragraph_open" || t.type === "paragraph_close") {
|
|
7140
|
+
toks.splice(i, 1);
|
|
7141
|
+
i--;
|
|
7142
|
+
continue;
|
|
7143
|
+
}
|
|
7144
|
+
const chunk = String(t.content ?? t.raw ?? "");
|
|
7145
|
+
const closeRe = new RegExp(`<\\s*\\/\\s*${openTag}\\s*>`, "i");
|
|
7146
|
+
const closeMatch = chunk ? closeRe.exec(chunk) : null;
|
|
7147
|
+
const isClosingTag$1 = !!closeMatch;
|
|
7148
|
+
if (chunk) {
|
|
7149
|
+
const openToken = toks[openIndex];
|
|
7150
|
+
if (closeMatch && typeof closeMatch.index === "number") {
|
|
7151
|
+
const end = closeMatch.index + String(closeMatch[0] ?? "").length;
|
|
7152
|
+
const before = chunk.slice(0, end);
|
|
7153
|
+
const after = chunk.slice(end);
|
|
7154
|
+
openToken.content = `${String(openToken.content || "")}\n${before}`;
|
|
7155
|
+
openToken.loading = false;
|
|
7156
|
+
const afterTrimmed = after.replace(/^\s+/, "");
|
|
7157
|
+
toks.splice(i, 1);
|
|
7158
|
+
tagStack.pop();
|
|
7159
|
+
if (afterTrimmed) toks.splice(i, 0, afterTrimmed.startsWith("<") ? {
|
|
7160
|
+
type: "html_block",
|
|
7161
|
+
content: afterTrimmed
|
|
7162
|
+
} : {
|
|
7163
|
+
type: "inline",
|
|
7164
|
+
content: afterTrimmed,
|
|
7165
|
+
children: [{
|
|
7166
|
+
type: "text",
|
|
7167
|
+
content: afterTrimmed,
|
|
7168
|
+
raw: afterTrimmed
|
|
7169
|
+
}]
|
|
7170
|
+
});
|
|
7171
|
+
i--;
|
|
7172
|
+
continue;
|
|
7173
|
+
}
|
|
7174
|
+
openToken.content = `${String(openToken.content || "")}\n${chunk}`;
|
|
7175
|
+
if (openToken.loading !== false) openToken.loading = !isClosingTag$1;
|
|
7176
|
+
}
|
|
7177
|
+
toks.splice(i, 1);
|
|
7178
|
+
i--;
|
|
7179
|
+
if (isClosingTag$1) tagStack.pop();
|
|
7180
|
+
continue;
|
|
7181
|
+
}
|
|
7182
|
+
}
|
|
7150
7183
|
if (t.type === "html_block") {
|
|
7151
|
-
const
|
|
7152
|
-
|
|
7153
|
-
|
|
7184
|
+
const rawContent = String(t.content || "");
|
|
7185
|
+
const tag = (rawContent.match(/<\s*(?:\/\s*)?([^\s>/]+)/)?.[1] ?? "").toLowerCase();
|
|
7186
|
+
if (!/^\s*<\s*\//.test(rawContent)) {
|
|
7187
|
+
if (tag) {
|
|
7188
|
+
if (!new RegExp(`<\\s*\\/\\s*${tag}\\s*>`, "i").test(rawContent)) tagStack.push([tag, i]);
|
|
7189
|
+
}
|
|
7190
|
+
} else if (tagStack.length > 0 && tag && tagStack[tagStack.length - 1][0] === tag) {
|
|
7191
|
+
const [, openIndex] = tagStack[tagStack.length - 1];
|
|
7192
|
+
const openToken = toks[openIndex];
|
|
7193
|
+
openToken.content = `${String(openToken.content || "")}\n${rawContent}`;
|
|
7194
|
+
openToken.loading = false;
|
|
7195
|
+
tagStack.pop();
|
|
7196
|
+
toks.splice(i, 1);
|
|
7197
|
+
i--;
|
|
7198
|
+
}
|
|
7154
7199
|
continue;
|
|
7155
7200
|
} else if (tagStack.length > 0) {
|
|
7156
7201
|
if (t.type === "paragraph_open" || t.type === "paragraph_close") {
|
|
@@ -7171,10 +7216,153 @@ function applyFixHtmlInlineTokens(md, options = {}) {
|
|
|
7171
7216
|
i--;
|
|
7172
7217
|
} else continue;
|
|
7173
7218
|
}
|
|
7219
|
+
if (customTagSet.size > 0) {
|
|
7220
|
+
const openReCache = /* @__PURE__ */ new Map();
|
|
7221
|
+
const closeReCache = /* @__PURE__ */ new Map();
|
|
7222
|
+
const getOpenRe = (tag) => {
|
|
7223
|
+
let r = openReCache.get(tag);
|
|
7224
|
+
if (!r) {
|
|
7225
|
+
r = new RegExp(`<\\s*${tag}\\b`, "i");
|
|
7226
|
+
openReCache.set(tag, r);
|
|
7227
|
+
}
|
|
7228
|
+
return r;
|
|
7229
|
+
};
|
|
7230
|
+
const getCloseRe = (tag) => {
|
|
7231
|
+
let r = closeReCache.get(tag);
|
|
7232
|
+
if (!r) {
|
|
7233
|
+
r = new RegExp(`<\\s*\\/\\s*${tag}\\s*>`, "i");
|
|
7234
|
+
closeReCache.set(tag, r);
|
|
7235
|
+
}
|
|
7236
|
+
return r;
|
|
7237
|
+
};
|
|
7238
|
+
const stack = [];
|
|
7239
|
+
for (let i = 0; i < toks.length; i++) {
|
|
7240
|
+
const tok = toks[i];
|
|
7241
|
+
const content = String(tok.content ?? "");
|
|
7242
|
+
if (stack.length > 0) {
|
|
7243
|
+
const top = stack[stack.length - 1];
|
|
7244
|
+
const openTok = toks[top.index];
|
|
7245
|
+
if (tok.type === "html_block" && getCloseRe(top.tag).test(content)) {
|
|
7246
|
+
openTok.content = `${String(openTok.content ?? "")}\n${content}`;
|
|
7247
|
+
if (Array.isArray(openTok.children)) openTok.children.push({
|
|
7248
|
+
type: "html_inline",
|
|
7249
|
+
content: `</${top.tag}>`,
|
|
7250
|
+
raw: `</${top.tag}>`
|
|
7251
|
+
});
|
|
7252
|
+
toks.splice(i, 1);
|
|
7253
|
+
i--;
|
|
7254
|
+
stack.pop();
|
|
7255
|
+
continue;
|
|
7256
|
+
}
|
|
7257
|
+
if (tok.type !== "inline") continue;
|
|
7258
|
+
const children = Array.isArray(tok.children) ? tok.children : [];
|
|
7259
|
+
const closeChildIndex = children.findIndex((c) => {
|
|
7260
|
+
if (!c || c.type !== "html_inline") return false;
|
|
7261
|
+
const cContent = String(c.content ?? "");
|
|
7262
|
+
return /^\s*<\s*\//.test(cContent) && cContent.toLowerCase().includes(top.tag);
|
|
7263
|
+
});
|
|
7264
|
+
if (closeChildIndex !== -1) {
|
|
7265
|
+
const beforeChildren = children.slice(0, closeChildIndex + 1);
|
|
7266
|
+
const afterChildren = children.slice(closeChildIndex + 1);
|
|
7267
|
+
const beforeText = beforeChildren.map((c) => String(c?.content ?? c?.raw ?? "")).join("");
|
|
7268
|
+
openTok.content = `${String(openTok.content ?? "")}\n${beforeText}`;
|
|
7269
|
+
if (Array.isArray(openTok.children)) openTok.children.push(...beforeChildren);
|
|
7270
|
+
if (afterChildren.length) {
|
|
7271
|
+
const afterText = afterChildren.map((c) => String(c.content ?? c.raw ?? "")).join("");
|
|
7272
|
+
if (afterText.trim()) {
|
|
7273
|
+
const trimmed = afterText.replace(/^\s+/, "");
|
|
7274
|
+
if (trimmed.startsWith("<")) toks.splice(i, 1, {
|
|
7275
|
+
type: "html_block",
|
|
7276
|
+
content: trimmed
|
|
7277
|
+
});
|
|
7278
|
+
else toks.splice(i, 1, {
|
|
7279
|
+
type: "paragraph_open",
|
|
7280
|
+
tag: "p",
|
|
7281
|
+
nesting: 1
|
|
7282
|
+
}, {
|
|
7283
|
+
type: "inline",
|
|
7284
|
+
tag: "",
|
|
7285
|
+
nesting: 0,
|
|
7286
|
+
content: afterText,
|
|
7287
|
+
children: [{
|
|
7288
|
+
type: "text",
|
|
7289
|
+
content: afterText,
|
|
7290
|
+
raw: afterText
|
|
7291
|
+
}]
|
|
7292
|
+
}, {
|
|
7293
|
+
type: "paragraph_close",
|
|
7294
|
+
tag: "p",
|
|
7295
|
+
nesting: -1
|
|
7296
|
+
});
|
|
7297
|
+
} else {
|
|
7298
|
+
toks.splice(i, 1);
|
|
7299
|
+
i--;
|
|
7300
|
+
}
|
|
7301
|
+
} else {
|
|
7302
|
+
toks.splice(i, 1);
|
|
7303
|
+
i--;
|
|
7304
|
+
}
|
|
7305
|
+
stack.pop();
|
|
7306
|
+
continue;
|
|
7307
|
+
}
|
|
7308
|
+
openTok.content = `${String(openTok.content ?? "")}\n${content}`;
|
|
7309
|
+
if (Array.isArray(openTok.children)) openTok.children.push(...children);
|
|
7310
|
+
toks.splice(i, 1);
|
|
7311
|
+
i--;
|
|
7312
|
+
continue;
|
|
7313
|
+
}
|
|
7314
|
+
if (tok.type !== "inline") continue;
|
|
7315
|
+
for (const tag of customTagSet) if (getOpenRe(tag).test(content) && !getCloseRe(tag).test(content)) {
|
|
7316
|
+
stack.push({
|
|
7317
|
+
tag,
|
|
7318
|
+
index: i
|
|
7319
|
+
});
|
|
7320
|
+
break;
|
|
7321
|
+
}
|
|
7322
|
+
}
|
|
7323
|
+
}
|
|
7324
|
+
{
|
|
7325
|
+
let depth = 0;
|
|
7326
|
+
for (let i = 0; i < toks.length; i++) {
|
|
7327
|
+
const t = toks[i];
|
|
7328
|
+
if (t.type === "paragraph_open") {
|
|
7329
|
+
depth++;
|
|
7330
|
+
continue;
|
|
7331
|
+
}
|
|
7332
|
+
if (t.type === "paragraph_close") if (depth > 0) depth--;
|
|
7333
|
+
else {
|
|
7334
|
+
toks.splice(i, 1);
|
|
7335
|
+
i--;
|
|
7336
|
+
}
|
|
7337
|
+
}
|
|
7338
|
+
}
|
|
7174
7339
|
for (let i = 0; i < toks.length; i++) {
|
|
7175
7340
|
const t = toks[i];
|
|
7176
7341
|
if (t.type === "html_block") {
|
|
7177
7342
|
const tag = (t.content?.match(/<([^\s>/]+)/)?.[1] ?? "").toLowerCase();
|
|
7343
|
+
if (customTagSet.has(tag)) {
|
|
7344
|
+
const raw$1 = String(t.content ?? "");
|
|
7345
|
+
const closeRe = new RegExp(`<\\/\\s*${tag}\\s*>`, "i");
|
|
7346
|
+
t.loading = closeRe.test(raw$1) ? false : t.loading !== void 0 ? t.loading : true;
|
|
7347
|
+
const closeMatch = closeRe.exec(raw$1);
|
|
7348
|
+
const endTagIndex = closeMatch ? closeMatch.index : -1;
|
|
7349
|
+
const closeLen = closeMatch ? closeMatch[0].length : 0;
|
|
7350
|
+
if (endTagIndex !== -1) {
|
|
7351
|
+
const rawForNode = raw$1.slice(0, endTagIndex + closeLen);
|
|
7352
|
+
t.content = rawForNode;
|
|
7353
|
+
t.raw = rawForNode;
|
|
7354
|
+
const afterTrimmed = (raw$1.slice(endTagIndex + closeLen) || "").replace(/^\s+/, "");
|
|
7355
|
+
if (afterTrimmed) toks.splice(i + 1, 0, afterTrimmed.startsWith("<") ? {
|
|
7356
|
+
type: "html_block",
|
|
7357
|
+
content: afterTrimmed
|
|
7358
|
+
} : {
|
|
7359
|
+
type: "text",
|
|
7360
|
+
content: afterTrimmed,
|
|
7361
|
+
raw: afterTrimmed
|
|
7362
|
+
});
|
|
7363
|
+
}
|
|
7364
|
+
continue;
|
|
7365
|
+
}
|
|
7178
7366
|
if (tag.startsWith("!") || tag.startsWith("?")) {
|
|
7179
7367
|
t.loading = false;
|
|
7180
7368
|
continue;
|
|
@@ -7192,7 +7380,7 @@ function applyFixHtmlInlineTokens(md, options = {}) {
|
|
|
7192
7380
|
"li"
|
|
7193
7381
|
].includes(tag)) continue;
|
|
7194
7382
|
t.type = "inline";
|
|
7195
|
-
const loading =
|
|
7383
|
+
const loading = new RegExp(`<\\/\\s*${tag}\\s*>`, "i").test(String(t.content ?? "")) ? false : t.loading !== void 0 ? t.loading : true;
|
|
7196
7384
|
const attrs = [];
|
|
7197
7385
|
const attrRegex = /\s([\w:-]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+)))?/g;
|
|
7198
7386
|
let match;
|
|
@@ -7202,24 +7390,36 @@ function applyFixHtmlInlineTokens(md, options = {}) {
|
|
|
7202
7390
|
attrs.push([attrName, attrValue]);
|
|
7203
7391
|
}
|
|
7204
7392
|
if (customTagSet.has(tag)) {
|
|
7205
|
-
const
|
|
7206
|
-
const
|
|
7207
|
-
const
|
|
7208
|
-
const
|
|
7393
|
+
const raw$1 = String(t.content ?? "");
|
|
7394
|
+
const closeMatch = new RegExp(`<\\/\\s*${tag}\\s*>`, "i").exec(raw$1);
|
|
7395
|
+
const endTagIndex = closeMatch ? closeMatch.index : -1;
|
|
7396
|
+
const closeLen = closeMatch ? closeMatch[0].length : 0;
|
|
7397
|
+
const rawForNode = endTagIndex !== -1 ? raw$1.slice(0, endTagIndex + closeLen) : raw$1;
|
|
7398
|
+
let inner = "";
|
|
7399
|
+
const openEnd = findTagCloseIndexOutsideQuotes$1(raw$1);
|
|
7400
|
+
if (openEnd !== -1) {
|
|
7401
|
+
if (endTagIndex !== -1 && openEnd < endTagIndex) inner = raw$1.slice(openEnd + 1, endTagIndex);
|
|
7402
|
+
else if (endTagIndex === -1) inner = raw$1.slice(openEnd + 1).replace(/<.*$/, "");
|
|
7403
|
+
}
|
|
7209
7404
|
t.children = [{
|
|
7210
7405
|
type: tag,
|
|
7211
|
-
content:
|
|
7212
|
-
raw:
|
|
7406
|
+
content: inner,
|
|
7407
|
+
raw: rawForNode,
|
|
7213
7408
|
attrs,
|
|
7214
7409
|
tag,
|
|
7215
7410
|
loading
|
|
7216
7411
|
}];
|
|
7217
7412
|
if (endTagIndex !== -1) {
|
|
7218
|
-
|
|
7219
|
-
|
|
7413
|
+
t.content = rawForNode;
|
|
7414
|
+
t.raw = rawForNode;
|
|
7415
|
+
const afterTrimmed = (raw$1.slice(endTagIndex + closeLen) || "").replace(/^\s+/, "");
|
|
7416
|
+
if (afterTrimmed) toks.splice(i + 1, 0, afterTrimmed.startsWith("<") ? {
|
|
7417
|
+
type: "html_block",
|
|
7418
|
+
content: afterTrimmed
|
|
7419
|
+
} : {
|
|
7220
7420
|
type: "text",
|
|
7221
|
-
content:
|
|
7222
|
-
raw:
|
|
7421
|
+
content: afterTrimmed,
|
|
7422
|
+
raw: afterTrimmed
|
|
7223
7423
|
});
|
|
7224
7424
|
}
|
|
7225
7425
|
} else t.children = [{
|
|
@@ -7976,7 +8176,7 @@ function fixTableTokens(tokens) {
|
|
|
7976
8176
|
if (token.type === "inline") {
|
|
7977
8177
|
const tcontent = String(token.content ?? "");
|
|
7978
8178
|
const childContent = String(token.children?.[0]?.content ?? "");
|
|
7979
|
-
if (/^\|(?:[^|\n]+\|?)+/.test(tcontent)) {
|
|
8179
|
+
if (!tcontent.includes("\n") && /^\|(?:[^|\n]+\|?)+/.test(tcontent)) {
|
|
7980
8180
|
const body = childContent.slice(1).split("|").map((i$1) => i$1.trim()).filter(Boolean).flatMap((i$1) => createTh(i$1));
|
|
7981
8181
|
const insert = [
|
|
7982
8182
|
...createStart(),
|
|
@@ -8923,6 +9123,7 @@ function parseHtmlInlineCodeToken(token, tokens, i, parseInlineTokens$1, raw, pP
|
|
|
8923
9123
|
tag,
|
|
8924
9124
|
attrs,
|
|
8925
9125
|
content: fragment.innerTokens.length ? stringifyTokens(fragment.innerTokens) : "",
|
|
9126
|
+
children: fragment.innerTokens.length ? parseInlineTokens$1(fragment.innerTokens, raw, pPreToken, options) : [],
|
|
8926
9127
|
raw: content,
|
|
8927
9128
|
loading: token.loading || loading,
|
|
8928
9129
|
autoClosed
|
|
@@ -9270,7 +9471,7 @@ function parseInlineTokens(tokens, raw, pPreToken, options) {
|
|
|
9270
9471
|
i++;
|
|
9271
9472
|
return true;
|
|
9272
9473
|
}
|
|
9273
|
-
if (/\*\*/.test(content)
|
|
9474
|
+
if (/\*\*/.test(content)) {
|
|
9274
9475
|
const openIdx = content.indexOf("**");
|
|
9275
9476
|
const beforeText = openIdx > -1 ? content.slice(0, openIdx) : "";
|
|
9276
9477
|
if (beforeText) pushText(beforeText, beforeText);
|
|
@@ -10184,7 +10385,7 @@ function parseHtmlBlock(token) {
|
|
|
10184
10385
|
const isVoid = VOID_TAGS.has(tag);
|
|
10185
10386
|
let closeRe = CLOSE_TAG_RE_CACHE.get(tag);
|
|
10186
10387
|
if (!closeRe) {
|
|
10187
|
-
closeRe = new RegExp(
|
|
10388
|
+
closeRe = new RegExp(`<\\s*\\/\\s*${tag}\\s*>`, "i");
|
|
10188
10389
|
CLOSE_TAG_RE_CACHE.set(tag, closeRe);
|
|
10189
10390
|
}
|
|
10190
10391
|
const hasClosing = closeRe.test(raw);
|
|
@@ -10293,6 +10494,98 @@ function parseThematicBreak() {
|
|
|
10293
10494
|
|
|
10294
10495
|
//#endregion
|
|
10295
10496
|
//#region src/parser/node-parsers/block-token-parser.ts
|
|
10497
|
+
function findTagCloseIndexOutsideQuotes(input) {
|
|
10498
|
+
let inSingle = false;
|
|
10499
|
+
let inDouble = false;
|
|
10500
|
+
for (let i = 0; i < input.length; i++) {
|
|
10501
|
+
const ch = input[i];
|
|
10502
|
+
if (ch === "\\") {
|
|
10503
|
+
i++;
|
|
10504
|
+
continue;
|
|
10505
|
+
}
|
|
10506
|
+
if (!inDouble && ch === "'") {
|
|
10507
|
+
inSingle = !inSingle;
|
|
10508
|
+
continue;
|
|
10509
|
+
}
|
|
10510
|
+
if (!inSingle && ch === "\"") {
|
|
10511
|
+
inDouble = !inDouble;
|
|
10512
|
+
continue;
|
|
10513
|
+
}
|
|
10514
|
+
if (!inSingle && !inDouble && ch === ">") return i;
|
|
10515
|
+
}
|
|
10516
|
+
return -1;
|
|
10517
|
+
}
|
|
10518
|
+
function stripWrapperNewlines(s) {
|
|
10519
|
+
return s.replace(/^\r?\n/, "").replace(/\r?\n$/, "");
|
|
10520
|
+
}
|
|
10521
|
+
function stripTrailingPartialClosingTag(inner, tag) {
|
|
10522
|
+
if (!inner || !tag) return inner;
|
|
10523
|
+
const re = new RegExp(String.raw`[\t ]*<\s*\/\s*${tag}[^>]*$`, "i");
|
|
10524
|
+
return inner.replace(re, "");
|
|
10525
|
+
}
|
|
10526
|
+
function findNextCustomHtmlBlockFromSource(source, tag, startIndex) {
|
|
10527
|
+
if (!source || !tag) return null;
|
|
10528
|
+
const lowerTag = tag.toLowerCase();
|
|
10529
|
+
const openRe = new RegExp(String.raw`<\s*${lowerTag}(?=\s|>|/)`, "gi");
|
|
10530
|
+
openRe.lastIndex = Math.max(0, startIndex || 0);
|
|
10531
|
+
const openMatch = openRe.exec(source);
|
|
10532
|
+
if (!openMatch || openMatch.index == null) return null;
|
|
10533
|
+
const openStart = openMatch.index;
|
|
10534
|
+
const openSlice = source.slice(openStart);
|
|
10535
|
+
const openEndRel = findTagCloseIndexOutsideQuotes(openSlice);
|
|
10536
|
+
if (openEndRel === -1) return null;
|
|
10537
|
+
const openEnd = openStart + openEndRel;
|
|
10538
|
+
if (/\/\s*>\s*$/.test(openSlice.slice(0, openEndRel + 1))) {
|
|
10539
|
+
const end = openEnd + 1;
|
|
10540
|
+
return {
|
|
10541
|
+
raw: source.slice(openStart, end),
|
|
10542
|
+
end
|
|
10543
|
+
};
|
|
10544
|
+
}
|
|
10545
|
+
let depth = 1;
|
|
10546
|
+
let i = openEnd + 1;
|
|
10547
|
+
const isOpenAt = (pos) => {
|
|
10548
|
+
const s = source.slice(pos);
|
|
10549
|
+
return new RegExp(String.raw`^<\s*${lowerTag}(?=\s|>|/)`, "i").test(s);
|
|
10550
|
+
};
|
|
10551
|
+
const isCloseAt = (pos) => {
|
|
10552
|
+
const s = source.slice(pos);
|
|
10553
|
+
return new RegExp(String.raw`^<\s*\/\s*${lowerTag}(?=\s|>)`, "i").test(s);
|
|
10554
|
+
};
|
|
10555
|
+
while (i < source.length) {
|
|
10556
|
+
const lt = source.indexOf("<", i);
|
|
10557
|
+
if (lt === -1) return {
|
|
10558
|
+
raw: source.slice(openStart),
|
|
10559
|
+
end: source.length
|
|
10560
|
+
};
|
|
10561
|
+
if (isCloseAt(lt)) {
|
|
10562
|
+
const gt = source.indexOf(">", lt);
|
|
10563
|
+
if (gt === -1) return null;
|
|
10564
|
+
depth--;
|
|
10565
|
+
if (depth === 0) {
|
|
10566
|
+
const end = gt + 1;
|
|
10567
|
+
return {
|
|
10568
|
+
raw: source.slice(openStart, end),
|
|
10569
|
+
end
|
|
10570
|
+
};
|
|
10571
|
+
}
|
|
10572
|
+
i = gt + 1;
|
|
10573
|
+
continue;
|
|
10574
|
+
}
|
|
10575
|
+
if (isOpenAt(lt)) {
|
|
10576
|
+
const rel = findTagCloseIndexOutsideQuotes(source.slice(lt));
|
|
10577
|
+
if (rel === -1) return null;
|
|
10578
|
+
depth++;
|
|
10579
|
+
i = lt + rel + 1;
|
|
10580
|
+
continue;
|
|
10581
|
+
}
|
|
10582
|
+
i = lt + 1;
|
|
10583
|
+
}
|
|
10584
|
+
return {
|
|
10585
|
+
raw: source.slice(openStart),
|
|
10586
|
+
end: source.length
|
|
10587
|
+
};
|
|
10588
|
+
}
|
|
10296
10589
|
function parseBasicBlockToken(tokens, index, options) {
|
|
10297
10590
|
const token = tokens[index];
|
|
10298
10591
|
switch (token.type) {
|
|
@@ -10306,10 +10599,37 @@ function parseBasicBlockToken(tokens, index, options) {
|
|
|
10306
10599
|
if (new Set(options.customHtmlTags.map((t) => {
|
|
10307
10600
|
const m = String(t ?? "").trim().match(/^[<\s/]*([A-Z][\w-]*)/i);
|
|
10308
10601
|
return m ? m[1].toLowerCase() : "";
|
|
10309
|
-
}).filter(Boolean)).has(htmlBlockNode.tag))
|
|
10310
|
-
|
|
10311
|
-
|
|
10312
|
-
|
|
10602
|
+
}).filter(Boolean)).has(htmlBlockNode.tag)) {
|
|
10603
|
+
const tag = htmlBlockNode.tag;
|
|
10604
|
+
const fromSource = findNextCustomHtmlBlockFromSource(String(options?.__sourceMarkdown ?? ""), tag, Number(options?.__customHtmlBlockCursor ?? 0));
|
|
10605
|
+
if (fromSource) options.__customHtmlBlockCursor = fromSource.end;
|
|
10606
|
+
const rawHtml = String(fromSource?.raw ?? htmlBlockNode.content ?? "");
|
|
10607
|
+
const openEnd = findTagCloseIndexOutsideQuotes(rawHtml);
|
|
10608
|
+
const closeMatch = new RegExp(`<\\s*\\/\\s*${tag}\\s*>`, "i").exec(rawHtml);
|
|
10609
|
+
const closeIndex = closeMatch ? closeMatch.index : -1;
|
|
10610
|
+
let inner = "";
|
|
10611
|
+
if (openEnd !== -1) if (closeIndex !== -1 && openEnd < closeIndex) inner = rawHtml.slice(openEnd + 1, closeIndex);
|
|
10612
|
+
else inner = rawHtml.slice(openEnd + 1);
|
|
10613
|
+
if (closeIndex === -1) inner = stripTrailingPartialClosingTag(inner, tag);
|
|
10614
|
+
const attrs = [];
|
|
10615
|
+
const openTag = openEnd !== -1 ? rawHtml.slice(0, openEnd + 1) : rawHtml;
|
|
10616
|
+
const attrRegex = /\s([\w:-]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+)))?/g;
|
|
10617
|
+
let m;
|
|
10618
|
+
while ((m = attrRegex.exec(openTag)) !== null) {
|
|
10619
|
+
const name = m[1];
|
|
10620
|
+
if (!name || name.toLowerCase() === tag) continue;
|
|
10621
|
+
const value = m[2] || m[3] || m[4] || "";
|
|
10622
|
+
attrs.push([name, value]);
|
|
10623
|
+
}
|
|
10624
|
+
return [{
|
|
10625
|
+
type: tag,
|
|
10626
|
+
tag,
|
|
10627
|
+
content: stripWrapperNewlines(inner),
|
|
10628
|
+
raw: String(fromSource?.raw ?? htmlBlockNode.raw ?? rawHtml),
|
|
10629
|
+
loading: htmlBlockNode.loading,
|
|
10630
|
+
attrs: attrs.length ? attrs : void 0
|
|
10631
|
+
}, index + 1];
|
|
10632
|
+
}
|
|
10313
10633
|
}
|
|
10314
10634
|
return [htmlBlockNode, index + 1];
|
|
10315
10635
|
}
|
|
@@ -10623,18 +10943,51 @@ function parseParagraph(tokens, index, options) {
|
|
|
10623
10943
|
|
|
10624
10944
|
//#endregion
|
|
10625
10945
|
//#region src/parser/index.ts
|
|
10946
|
+
function stripDanglingHtmlLikeTail(markdown) {
|
|
10947
|
+
const s = String(markdown ?? "");
|
|
10948
|
+
const lastLt = s.lastIndexOf("<");
|
|
10949
|
+
if (lastLt === -1) return s;
|
|
10950
|
+
const tail = s.slice(lastLt);
|
|
10951
|
+
if (tail.includes(">")) return s;
|
|
10952
|
+
if (!/^<\s*(?:\/\s*)?[A-Z!][\s\S]*$/i.test(tail)) return s;
|
|
10953
|
+
return s.slice(0, lastLt);
|
|
10954
|
+
}
|
|
10626
10955
|
function parseMarkdownToStructure(markdown, md, options = {}) {
|
|
10627
10956
|
let safeMarkdown = (markdown ?? "").toString().replace(/([^\\])\r(ight|ho)/g, "$1\\r$2").replace(/([^\\])\n(abla|eq|ot|exists)/g, "$1\\n$2");
|
|
10628
10957
|
if (safeMarkdown.endsWith("- *")) safeMarkdown = safeMarkdown.replace(/- \*$/, "- \\*");
|
|
10629
|
-
if (
|
|
10958
|
+
if (/(?:^|\n)\s*-\s*$/.test(safeMarkdown)) safeMarkdown = safeMarkdown.replace(/(?:^|\n)\s*-\s*$/, (m) => {
|
|
10959
|
+
return m.startsWith("\n") ? "\n" : "";
|
|
10960
|
+
});
|
|
10961
|
+
else if (/(?:^|\n)\s*--\s*$/.test(safeMarkdown)) safeMarkdown = safeMarkdown.replace(/(?:^|\n)\s*--\s*$/, (m) => {
|
|
10962
|
+
return m.startsWith("\n") ? "\n" : "";
|
|
10963
|
+
});
|
|
10964
|
+
else if (/(?:^|\n)\s*>\s*$/.test(safeMarkdown)) safeMarkdown = safeMarkdown.replace(/(?:^|\n)\s*>\s*$/, (m) => {
|
|
10965
|
+
return m.startsWith("\n") ? "\n" : "";
|
|
10966
|
+
});
|
|
10967
|
+
else if (/\n\s*[*+]\s*$/.test(safeMarkdown)) safeMarkdown = safeMarkdown.replace(/\n\s*[*+]\s*$/, "\n");
|
|
10630
10968
|
else if (/\n[[(]\n*$/.test(safeMarkdown)) safeMarkdown = safeMarkdown.replace(/(\n\[|\n\()+\n*$/g, "\n");
|
|
10969
|
+
if (options.customHtmlTags?.length) {
|
|
10970
|
+
const tags = options.customHtmlTags.map((t) => String(t ?? "").trim()).filter(Boolean).map((t) => {
|
|
10971
|
+
return (t.match(/^[<\s/]*([A-Z][\w-]*)/i)?.[1] ?? "").toLowerCase();
|
|
10972
|
+
}).filter(Boolean);
|
|
10973
|
+
if (tags.length) if (!safeMarkdown.includes("</")) {} else for (const tag of tags) {
|
|
10974
|
+
const re = new RegExp(String.raw`(^[\t ]*<\s*\/\s*${tag}\s*>[\t ]*)(\r?\n)(?![\t ]*\r?\n|$)`, "gim");
|
|
10975
|
+
safeMarkdown = safeMarkdown.replace(re, "$1$2$2");
|
|
10976
|
+
}
|
|
10977
|
+
}
|
|
10978
|
+
safeMarkdown = stripDanglingHtmlLikeTail(safeMarkdown);
|
|
10631
10979
|
const tokens = md.parse(safeMarkdown, {});
|
|
10632
10980
|
if (!tokens || !Array.isArray(tokens)) return [];
|
|
10633
10981
|
const pre = options.preTransformTokens;
|
|
10634
10982
|
const post = options.postTransformTokens;
|
|
10635
10983
|
let transformedTokens = tokens;
|
|
10636
10984
|
if (pre && typeof pre === "function") transformedTokens = pre(transformedTokens) || transformedTokens;
|
|
10637
|
-
|
|
10985
|
+
const internalOptions = {
|
|
10986
|
+
...options,
|
|
10987
|
+
__sourceMarkdown: safeMarkdown,
|
|
10988
|
+
__customHtmlBlockCursor: 0
|
|
10989
|
+
};
|
|
10990
|
+
let result = processTokens(transformedTokens, internalOptions);
|
|
10638
10991
|
if (post && typeof post === "function") {
|
|
10639
10992
|
const postResult = post(transformedTokens);
|
|
10640
10993
|
if (Array.isArray(postResult)) {
|
|
@@ -10692,6 +11045,20 @@ function processTokens(tokens, options) {
|
|
|
10692
11045
|
result.push(parseHardBreak());
|
|
10693
11046
|
i++;
|
|
10694
11047
|
break;
|
|
11048
|
+
case "text": {
|
|
11049
|
+
const content = String(token.content ?? "");
|
|
11050
|
+
result.push({
|
|
11051
|
+
type: "paragraph",
|
|
11052
|
+
raw: content,
|
|
11053
|
+
children: content ? [{
|
|
11054
|
+
type: "text",
|
|
11055
|
+
content,
|
|
11056
|
+
raw: content
|
|
11057
|
+
}] : []
|
|
11058
|
+
});
|
|
11059
|
+
i++;
|
|
11060
|
+
break;
|
|
11061
|
+
}
|
|
10695
11062
|
case "inline":
|
|
10696
11063
|
result.push(...parseInlineTokens(token.children || [], String(token.content ?? ""), void 0, {
|
|
10697
11064
|
requireClosingStrong: options?.requireClosingStrong,
|