@ai-react-markdown/engine 2.4.3 → 2.5.0
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 +95 -0
- package/dist/index.cjs +440 -83
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +109 -58
- package/dist/index.d.ts +109 -58
- package/dist/index.dev.cjs +440 -83
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +440 -81
- package/dist/index.dev.js.map +1 -1
- package/dist/index.js +440 -81
- package/dist/index.js.map +1 -1
- package/package.json +12 -2
package/dist/index.dev.js
CHANGED
|
@@ -176,6 +176,74 @@ var defaultUrlTransform = (value) => {
|
|
|
176
176
|
import { htmlBlockNames } from "micromark-util-html-tag-name";
|
|
177
177
|
import { normalizeIdentifier } from "micromark-util-normalize-identifier";
|
|
178
178
|
var TYPE6_NAMES = new Set(htmlBlockNames);
|
|
179
|
+
var TABLE_PART_NAMES = /* @__PURE__ */ new Set(["td", "th", "tr", "tbody", "thead", "tfoot", "caption", "col", "colgroup"]);
|
|
180
|
+
var HTML_BREAKOUT_TAGS = /* @__PURE__ */ new Set([
|
|
181
|
+
"b",
|
|
182
|
+
"big",
|
|
183
|
+
"blockquote",
|
|
184
|
+
"body",
|
|
185
|
+
"br",
|
|
186
|
+
"center",
|
|
187
|
+
"code",
|
|
188
|
+
"dd",
|
|
189
|
+
"div",
|
|
190
|
+
"dl",
|
|
191
|
+
"dt",
|
|
192
|
+
"em",
|
|
193
|
+
"embed",
|
|
194
|
+
"h1",
|
|
195
|
+
"h2",
|
|
196
|
+
"h3",
|
|
197
|
+
"h4",
|
|
198
|
+
"h5",
|
|
199
|
+
"h6",
|
|
200
|
+
"head",
|
|
201
|
+
"hr",
|
|
202
|
+
"i",
|
|
203
|
+
"img",
|
|
204
|
+
"li",
|
|
205
|
+
"listing",
|
|
206
|
+
"menu",
|
|
207
|
+
"meta",
|
|
208
|
+
"nobr",
|
|
209
|
+
"ol",
|
|
210
|
+
"p",
|
|
211
|
+
"pre",
|
|
212
|
+
"ruby",
|
|
213
|
+
"s",
|
|
214
|
+
"small",
|
|
215
|
+
"span",
|
|
216
|
+
"strong",
|
|
217
|
+
"strike",
|
|
218
|
+
"sub",
|
|
219
|
+
"sup",
|
|
220
|
+
"table",
|
|
221
|
+
"tt",
|
|
222
|
+
"u",
|
|
223
|
+
"ul",
|
|
224
|
+
"var"
|
|
225
|
+
]);
|
|
226
|
+
var HTML_INTEGRATION_POINTS = ["foreignobject", "desc", "mi", "mo", "mn", "ms", "mtext", "annotation-xml"];
|
|
227
|
+
var TYPE1_NAMES = /* @__PURE__ */ new Set(["script", "pre", "style", "textarea"]);
|
|
228
|
+
var RAW_TEXT_ELEMENTS = /* @__PURE__ */ new Set([
|
|
229
|
+
"script",
|
|
230
|
+
"style",
|
|
231
|
+
"textarea",
|
|
232
|
+
"title",
|
|
233
|
+
"xmp",
|
|
234
|
+
"iframe",
|
|
235
|
+
"noembed",
|
|
236
|
+
"noframes",
|
|
237
|
+
// NOT `noscript`: hast-util-raw constructs parse5 with
|
|
238
|
+
// `scriptingEnabled: false`, under which `<noscript>` content is ordinary
|
|
239
|
+
// HTML — modelling it as raw text ignored a `<b>` inside and under-blocked
|
|
240
|
+
// (oracle review of the r2 batch; regression caught before release).
|
|
241
|
+
"plaintext"
|
|
242
|
+
]);
|
|
243
|
+
var TYPE6_START_RE = /^<\/?([A-Za-z][A-Za-z0-9-]*)(?:[ \t\r]|\/?>|$)/;
|
|
244
|
+
var TYPE1_START_RE = /^<(script|pre|style|textarea)(?:[ \t\r]|>|$)/i;
|
|
245
|
+
var TYPE7_LINE_RE = /^(?:<[A-Za-z][A-Za-z0-9-]*(?:[ \t\r][^>]*|\/)?>|<\/[A-Za-z][A-Za-z0-9-]*[ \t\r]*>)[ \t\r]*$/;
|
|
246
|
+
var t7Name = (line) => /^<\/?([A-Za-z][A-Za-z0-9-]*)/.exec(line)[1];
|
|
179
247
|
var VOID_TAGS = /* @__PURE__ */ new Set([
|
|
180
248
|
"area",
|
|
181
249
|
"base",
|
|
@@ -199,7 +267,35 @@ var DEF_RE = /^ {0,3}\[((?:[^[\]\\]|\\.)+)\]:/;
|
|
|
199
267
|
var FENCE_RE = /^ {0,3}(`{3,}|~{3,})/;
|
|
200
268
|
var MATH_RUN_RE = /^ {0,3}(\$\$+)/;
|
|
201
269
|
var TAG_OR_COMMENT_RE = /<(\/?)([A-Za-z][A-Za-z0-9-]*)(?=[\s/>])([^>]*)>|<!--|-->|--!>/g;
|
|
202
|
-
var TRUNCATED_TAG_RE = /<(\/?)([A-Za-z][A-Za-z0-9-]*)([
|
|
270
|
+
var TRUNCATED_TAG_RE = /<(\/?)([A-Za-z][A-Za-z0-9-]*)([^>]*)$/;
|
|
271
|
+
var TAG_START_LT_RE = /<\/?[A-Za-z]/g;
|
|
272
|
+
function scanTagAttrs(text, from, to, out) {
|
|
273
|
+
let st = out.state;
|
|
274
|
+
for (let i = from; i < to; i++) {
|
|
275
|
+
const c = text[i];
|
|
276
|
+
if (st === '"' || st === "'") {
|
|
277
|
+
if (c === st) st = "outside";
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
const ws = c === " " || c === " " || c === "\n" || c === "\r" || c === "\f";
|
|
281
|
+
if (st === "afterEq") {
|
|
282
|
+
if (ws) continue;
|
|
283
|
+
if (c === '"' || c === "'") st = c;
|
|
284
|
+
else if (c === ">") return i;
|
|
285
|
+
else st = "unquoted";
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
if (st === "unquoted") {
|
|
289
|
+
if (ws) st = "outside";
|
|
290
|
+
else if (c === ">") return i;
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
if (c === "=") st = "afterEq";
|
|
294
|
+
else if (c === ">") return i;
|
|
295
|
+
}
|
|
296
|
+
out.state = st;
|
|
297
|
+
return -1;
|
|
298
|
+
}
|
|
203
299
|
var REF_RE = /!?\[((?:[^[\]\\]|\\.)*)\]/g;
|
|
204
300
|
var BACKTICK_RUN_RE = /`+/g;
|
|
205
301
|
var MD_BLANK_RE = /^[ \t\r]*$/;
|
|
@@ -294,6 +390,8 @@ function freshCheckpoint(defListEnabled, mathFlow, referenceTaint) {
|
|
|
294
390
|
openTotal: 0,
|
|
295
391
|
commentOpen: false,
|
|
296
392
|
piOpen: false,
|
|
393
|
+
bogusOpen: false,
|
|
394
|
+
rawTextOpen: null,
|
|
297
395
|
declOpen: false,
|
|
298
396
|
cdataOpen: false,
|
|
299
397
|
inFence: false,
|
|
@@ -314,7 +412,12 @@ function freshCheckpoint(defListEnabled, mathFlow, referenceTaint) {
|
|
|
314
412
|
htmlFlowSinceBlank: false,
|
|
315
413
|
htmlSeamPending: false,
|
|
316
414
|
phasePoisonedAt: Infinity,
|
|
317
|
-
pendingTruncatedTags: []
|
|
415
|
+
pendingTruncatedTags: [],
|
|
416
|
+
pendingTruncatedCloses: [],
|
|
417
|
+
tagAcrossLines: false,
|
|
418
|
+
tagAcrossLinesIndent: 0,
|
|
419
|
+
tagAcrossLinesState: "outside",
|
|
420
|
+
htmlFlowReal: false
|
|
318
421
|
};
|
|
319
422
|
}
|
|
320
423
|
function isPlausibleLinkDefRest(rest) {
|
|
@@ -413,11 +516,21 @@ function computeFreezeBoundary(text, options, resume) {
|
|
|
413
516
|
let start = cp.confirmedOffset;
|
|
414
517
|
let tailLine = null;
|
|
415
518
|
while (start < text.length) {
|
|
416
|
-
let end = text.
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
519
|
+
let end = text.length;
|
|
520
|
+
let textEnd = text.length;
|
|
521
|
+
{
|
|
522
|
+
const nl = text.indexOf("\n", start);
|
|
523
|
+
const cr = text.indexOf("\r", start);
|
|
524
|
+
if (cr !== -1 && (nl === -1 || cr < nl)) {
|
|
525
|
+
textEnd = cr;
|
|
526
|
+
end = text.charCodeAt(cr + 1) === 10 ? cr + 1 : cr;
|
|
527
|
+
} else if (nl !== -1) {
|
|
528
|
+
textEnd = nl;
|
|
529
|
+
end = nl;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
const confirmed = end < text.length && !(end === text.length - 1 && text.charCodeAt(end) === 13);
|
|
533
|
+
const lineText = text.slice(start, textEnd);
|
|
421
534
|
const ln = {
|
|
422
535
|
start,
|
|
423
536
|
end,
|
|
@@ -509,14 +622,33 @@ function processConfirmedLine(cp, ln, text) {
|
|
|
509
622
|
newest.defListSettled = ln.blank ? true : !canBecomeDdLine(ln.text, true);
|
|
510
623
|
}
|
|
511
624
|
const isBlockStart = cp.prevLineBlank;
|
|
512
|
-
if (cp.htmlSeamPending && !ln.blank && !cp.htmlFlowSinceBlank && !(cp.commentOpen || cp.piOpen || cp.declOpen || cp.cdataOpen)) {
|
|
625
|
+
if (cp.htmlSeamPending && !ln.blank && !cp.htmlFlowSinceBlank && !(cp.commentOpen || cp.piOpen || cp.declOpen || cp.cdataOpen || cp.bogusOpen)) {
|
|
513
626
|
const defShapedLine = DEF_RE.test(ln.text) || FOOTNOTE_DEF_RE.test(ln.text);
|
|
514
627
|
const commentOnly = ln.text.replace(/<!--[\s\S]*?-->/g, " ").replace(/<!--[\s\S]*$/, " ").replace(/[ \t\r]/g, "") === "";
|
|
515
628
|
if (!defShapedLine && !commentOnly) {
|
|
516
629
|
cp.htmlSeamPending = false;
|
|
517
630
|
}
|
|
518
631
|
}
|
|
632
|
+
const inForeignContent = () => (cp.tagBalance.get("svg") ?? 0) > 0 || (cp.tagBalance.get("math") ?? 0) > 0;
|
|
633
|
+
const honoursSelfClosing = (tag) => {
|
|
634
|
+
if (tag === "svg" || tag === "math") return true;
|
|
635
|
+
if (!inForeignContent() || HTML_BREAKOUT_TAGS.has(tag)) return false;
|
|
636
|
+
for (const ip of HTML_INTEGRATION_POINTS) if ((cp.tagBalance.get(ip) ?? 0) > 0) return false;
|
|
637
|
+
return true;
|
|
638
|
+
};
|
|
639
|
+
const htmlRulesApply = () => {
|
|
640
|
+
if (!inForeignContent()) return true;
|
|
641
|
+
for (const ip of HTML_INTEGRATION_POINTS) if ((cp.tagBalance.get(ip) ?? 0) > 0) return true;
|
|
642
|
+
return false;
|
|
643
|
+
};
|
|
519
644
|
const applyTag = (tag, closing) => {
|
|
645
|
+
if (cp.rawTextOpen !== null) {
|
|
646
|
+
if (!(closing && tag === cp.rawTextOpen)) return;
|
|
647
|
+
cp.rawTextOpen = null;
|
|
648
|
+
} else if (!closing && RAW_TEXT_ELEMENTS.has(tag) && htmlRulesApply()) {
|
|
649
|
+
cp.rawTextOpen = tag;
|
|
650
|
+
if (tag === "plaintext") cp.phasePoisonedAt = Math.min(cp.phasePoisonedAt, ln.start);
|
|
651
|
+
}
|
|
520
652
|
if (closing) {
|
|
521
653
|
const count = cp.tagBalance.get(tag) ?? 0;
|
|
522
654
|
if (count > 0) {
|
|
@@ -529,7 +661,7 @@ function processConfirmedLine(cp, ln, text) {
|
|
|
529
661
|
}
|
|
530
662
|
};
|
|
531
663
|
const commentOpenAtLineStart = cp.commentOpen;
|
|
532
|
-
const rawOpenAtLineStart = cp.commentOpen || cp.piOpen || cp.declOpen || cp.cdataOpen;
|
|
664
|
+
const rawOpenAtLineStart = cp.commentOpen || cp.piOpen || cp.declOpen || cp.cdataOpen || cp.bogusOpen;
|
|
533
665
|
if (cp.inFence) {
|
|
534
666
|
const close = FENCE_RE.exec(ln.text);
|
|
535
667
|
if (close && close[1][0] === cp.fenceChar && close[1].length >= cp.fenceLen && isMdBlank(ln.text.slice(close[0].length))) {
|
|
@@ -611,12 +743,22 @@ function processConfirmedLine(cp, ln, text) {
|
|
|
611
743
|
for (const tag of cp.pendingTruncatedTags) applyTag(tag, true);
|
|
612
744
|
cp.pendingTruncatedTags = [];
|
|
613
745
|
}
|
|
746
|
+
cp.pendingTruncatedCloses = [];
|
|
747
|
+
if (cp.tagAcrossLines && (cp.tagAcrossLinesState === '"' || cp.tagAcrossLinesState === "'")) {
|
|
748
|
+
cp.phasePoisonedAt = Math.min(cp.phasePoisonedAt, ln.start);
|
|
749
|
+
}
|
|
750
|
+
cp.tagAcrossLines = false;
|
|
751
|
+
cp.tagAcrossLinesState = "outside";
|
|
752
|
+
if (cp.bogusOpen) {
|
|
753
|
+
cp.phasePoisonedAt = Math.min(cp.phasePoisonedAt, ln.start);
|
|
754
|
+
cp.bogusOpen = false;
|
|
755
|
+
}
|
|
614
756
|
cp.blankRun += 1;
|
|
615
757
|
cp.lastBlankStart = ln.start;
|
|
616
758
|
cp.candidates.push({
|
|
617
759
|
offset: Math.min(ln.end + 1, text.length),
|
|
618
760
|
blankRun: cp.blankRun,
|
|
619
|
-
htmlBalanced: cp.openTotal === 0 && !cp.commentOpen && !cp.piOpen && !cp.declOpen && !cp.cdataOpen,
|
|
761
|
+
htmlBalanced: cp.openTotal === 0 && !cp.commentOpen && !cp.piOpen && !cp.declOpen && !cp.cdataOpen && !cp.bogusOpen,
|
|
620
762
|
hazard: cp.hazardVerdict,
|
|
621
763
|
seamRisk: cp.htmlSeamPending,
|
|
622
764
|
defListSettled: null
|
|
@@ -624,6 +766,7 @@ function processConfirmedLine(cp, ln, text) {
|
|
|
624
766
|
cp.paragraphHasUnpairedRun = false;
|
|
625
767
|
cp.openBracket = null;
|
|
626
768
|
cp.htmlFlowSinceBlank = false;
|
|
769
|
+
cp.htmlFlowReal = false;
|
|
627
770
|
cp.prevLineBlank = true;
|
|
628
771
|
cp.prevLineWasText = false;
|
|
629
772
|
cp.prevLineWasValidDef = false;
|
|
@@ -639,6 +782,16 @@ function processConfirmedLine(cp, ln, text) {
|
|
|
639
782
|
if (tagStart) {
|
|
640
783
|
cp.htmlFlowSinceBlank = true;
|
|
641
784
|
if (!TYPE6_NAMES.has(tagStart[1].toLowerCase())) cp.hazardVerdict = true;
|
|
785
|
+
if (!cp.htmlFlowReal) {
|
|
786
|
+
const t = mdTrimStart(ln.text);
|
|
787
|
+
const t6 = TYPE6_START_RE.exec(t);
|
|
788
|
+
const t7 = TYPE7_LINE_RE.exec(t);
|
|
789
|
+
if (t6 !== null && TYPE6_NAMES.has(t6[1].toLowerCase()) || TYPE1_START_RE.test(t) || // Type 7 cannot interrupt a paragraph, and excludes the raw-text
|
|
790
|
+
// names (those are type 1 as start tags, paragraph as end tags).
|
|
791
|
+
t7 !== null && !cp.prevLineWasText && !TYPE1_NAMES.has(t7Name(t).toLowerCase())) {
|
|
792
|
+
cp.htmlFlowReal = true;
|
|
793
|
+
}
|
|
794
|
+
}
|
|
642
795
|
}
|
|
643
796
|
const inRawText = cp.htmlFlowSinceBlank || rawOpenAtLineStart;
|
|
644
797
|
const rawFlowStart = ln.indent <= 3 && /^<(?:!--|\?|![A-Za-z]|!\[CDATA\[)/.test(mdTrimStart(ln.text));
|
|
@@ -737,7 +890,7 @@ ${cont(scanText)}` };
|
|
|
737
890
|
pos = c + 3;
|
|
738
891
|
continue;
|
|
739
892
|
}
|
|
740
|
-
if (cp.declOpen) {
|
|
893
|
+
if (cp.declOpen || cp.bogusOpen) {
|
|
741
894
|
const c = scanText.indexOf(">", pos);
|
|
742
895
|
if (c === -1) {
|
|
743
896
|
rawSpans.push([pos, scanText.length]);
|
|
@@ -745,6 +898,7 @@ ${cont(scanText)}` };
|
|
|
745
898
|
}
|
|
746
899
|
rawSpans.push([pos, c + 1]);
|
|
747
900
|
cp.declOpen = false;
|
|
901
|
+
cp.bogusOpen = false;
|
|
748
902
|
pos = c + 1;
|
|
749
903
|
continue;
|
|
750
904
|
}
|
|
@@ -752,10 +906,16 @@ ${cont(scanText)}` };
|
|
|
752
906
|
const cd = scanText.indexOf("<![CDATA[", pos);
|
|
753
907
|
const dm = scanText.slice(pos).search(/<![A-Za-z]/);
|
|
754
908
|
const decl = dm === -1 ? -1 : pos + dm;
|
|
755
|
-
const
|
|
909
|
+
const bm = cp.htmlFlowReal ? scanText.slice(pos).search(/<!(?!--|[A-Za-z]|\[CDATA\[)|<\/(?![A-Za-z])/) : -1;
|
|
910
|
+
const bogus = bm === -1 ? -1 : pos + bm;
|
|
911
|
+
const starts = [pi, cd, decl, bogus].filter((x) => x !== -1);
|
|
756
912
|
if (starts.length === 0) break;
|
|
757
913
|
const first = Math.min(...starts);
|
|
758
|
-
if (first ===
|
|
914
|
+
if (first === bogus) {
|
|
915
|
+
rawSpans.push([bogus, bogus + 2]);
|
|
916
|
+
cp.bogusOpen = true;
|
|
917
|
+
pos = bogus + 2;
|
|
918
|
+
} else if (first === cd) {
|
|
759
919
|
rawSpans.push([cd, cd + 9]);
|
|
760
920
|
cp.cdataOpen = true;
|
|
761
921
|
pos = cd + 9;
|
|
@@ -779,11 +939,30 @@ ${cont(scanText)}` };
|
|
|
779
939
|
for (const [from, to] of rawSpans) {
|
|
780
940
|
tagText = tagText.slice(0, from) + " ".repeat(to - from) + tagText.slice(to);
|
|
781
941
|
}
|
|
782
|
-
|
|
942
|
+
let skipTagScan = false;
|
|
943
|
+
if (cp.tagAcrossLines) {
|
|
944
|
+
if (ln.indent < cp.tagAcrossLinesIndent) poisonRawDivergence();
|
|
945
|
+
const attrs = { state: cp.tagAcrossLinesState };
|
|
946
|
+
const gt = scanTagAttrs(ln.text, 0, ln.text.length, attrs);
|
|
947
|
+
if (gt === -1) {
|
|
948
|
+
scanTagAttrs("\n", 0, 1, attrs);
|
|
949
|
+
cp.tagAcrossLinesState = attrs.state;
|
|
950
|
+
skipTagScan = true;
|
|
951
|
+
} else {
|
|
952
|
+
for (const tag of cp.pendingTruncatedCloses) applyTag(tag, true);
|
|
953
|
+
cp.pendingTruncatedCloses = [];
|
|
954
|
+
cp.tagAcrossLines = false;
|
|
955
|
+
cp.tagAcrossLinesState = "outside";
|
|
956
|
+
tagText = " ".repeat(gt + 1) + tagText.slice(gt + 1);
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
let tagHandledAsTruncated = false;
|
|
960
|
+
if (!skipTagScan) {
|
|
783
961
|
TAG_OR_COMMENT_RE.lastIndex = 0;
|
|
784
962
|
let m;
|
|
785
963
|
let lastCommentOpenerIdx = -1;
|
|
786
964
|
while ((m = TAG_OR_COMMENT_RE.exec(tagText)) !== null) {
|
|
965
|
+
if (cp.rawTextOpen !== null && (m[0] === "<!--" || m[0] === "-->" || m[0] === "--!>")) continue;
|
|
787
966
|
if (m[0] === "<!--") {
|
|
788
967
|
const next = tagText.slice(m.index + 4, m.index + 6);
|
|
789
968
|
if (cp.commentOpen) {
|
|
@@ -809,8 +988,32 @@ ${cont(scanText)}` };
|
|
|
809
988
|
if (cp.commentOpen) continue;
|
|
810
989
|
const closing = m[1] === "/";
|
|
811
990
|
const tag = m[2].toLowerCase();
|
|
812
|
-
|
|
813
|
-
|
|
991
|
+
if (TABLE_PART_NAMES.has(tag)) cp.phasePoisonedAt = Math.min(cp.phasePoisonedAt, ln.start + m.index);
|
|
992
|
+
let attrs = m[3] ?? "";
|
|
993
|
+
if (cp.htmlFlowReal && (cp.rawTextOpen === null || closing && tag === cp.rawTextOpen)) {
|
|
994
|
+
const attrStart = m.index + 1 + (closing ? 1 : 0) + m[2].length;
|
|
995
|
+
const st = { state: "outside" };
|
|
996
|
+
const gt = scanTagAttrs(tagText, attrStart, tagText.length, st);
|
|
997
|
+
if (gt === -1) {
|
|
998
|
+
if (!VOID_TAGS.has(tag)) {
|
|
999
|
+
if (closing) cp.pendingTruncatedCloses.push(tag);
|
|
1000
|
+
else applyTag(tag, false);
|
|
1001
|
+
}
|
|
1002
|
+
scanTagAttrs("\n", 0, 1, st);
|
|
1003
|
+
cp.tagAcrossLines = true;
|
|
1004
|
+
cp.tagAcrossLinesIndent = ln.indent;
|
|
1005
|
+
cp.tagAcrossLinesState = st.state;
|
|
1006
|
+
tagHandledAsTruncated = true;
|
|
1007
|
+
break;
|
|
1008
|
+
}
|
|
1009
|
+
if (gt + 1 !== m.index + m[0].length) {
|
|
1010
|
+
attrs = tagText.slice(attrStart, gt);
|
|
1011
|
+
TAG_OR_COMMENT_RE.lastIndex = gt + 1;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
if (closing && !cp.htmlFlowReal && !/^\s*$/.test(attrs)) continue;
|
|
1015
|
+
const selfClosing = /\/\s*$/.test(attrs);
|
|
1016
|
+
if (VOID_TAGS.has(tag) || selfClosing && honoursSelfClosing(tag)) continue;
|
|
814
1017
|
applyTag(tag, closing);
|
|
815
1018
|
}
|
|
816
1019
|
if (cp.commentOpen && lastCommentOpenerIdx !== -1 && !inRawText) {
|
|
@@ -829,22 +1032,44 @@ ${cont(scanText)}` };
|
|
|
829
1032
|
if (startMasked || wholeVisible || inRaw(mr.index) || cp.commentOpen) continue;
|
|
830
1033
|
const closing = mr[1] === "/";
|
|
831
1034
|
const tag = mr[2].toLowerCase();
|
|
1035
|
+
if (TABLE_PART_NAMES.has(tag)) cp.phasePoisonedAt = Math.min(cp.phasePoisonedAt, ln.start + mr.index);
|
|
1036
|
+
if (closing && mr[3] !== void 0 && !/^\s*$/.test(mr[3])) continue;
|
|
832
1037
|
const selfClosing = mr[3] !== void 0 && /\/\s*$/.test(mr[3]);
|
|
833
|
-
if (VOID_TAGS.has(tag) || selfClosing) continue;
|
|
1038
|
+
if (VOID_TAGS.has(tag) || selfClosing && honoursSelfClosing(tag)) continue;
|
|
834
1039
|
applyTag(tag, closing);
|
|
835
1040
|
}
|
|
836
1041
|
}
|
|
837
1042
|
if (cp.pendingTruncatedTags.length > 0 && ln.text.includes(">")) {
|
|
1043
|
+
if (cp.pendingTruncatedTags.some((t) => TABLE_PART_NAMES.has(t))) {
|
|
1044
|
+
cp.phasePoisonedAt = Math.min(cp.phasePoisonedAt, ln.start);
|
|
1045
|
+
}
|
|
838
1046
|
cp.pendingTruncatedTags = [];
|
|
839
1047
|
}
|
|
840
|
-
if (!cp.commentOpen) {
|
|
841
|
-
|
|
1048
|
+
if (!cp.commentOpen && !tagHandledAsTruncated) {
|
|
1049
|
+
let lastLt = -1;
|
|
1050
|
+
TAG_START_LT_RE.lastIndex = 0;
|
|
1051
|
+
for (let ms = TAG_START_LT_RE.exec(tagText); ms !== null; ms = TAG_START_LT_RE.exec(tagText)) {
|
|
1052
|
+
lastLt = ms.index;
|
|
1053
|
+
TAG_START_LT_RE.lastIndex = ms.index + 1;
|
|
1054
|
+
}
|
|
842
1055
|
if (lastLt !== -1 && !tagText.includes(">", lastLt)) {
|
|
843
1056
|
const m2 = TRUNCATED_TAG_RE.exec(tagText.slice(lastLt));
|
|
844
1057
|
if (m2) {
|
|
845
1058
|
const closing = m2[1] === "/";
|
|
846
1059
|
const tag = m2[2].toLowerCase();
|
|
847
|
-
if (
|
|
1060
|
+
if (TABLE_PART_NAMES.has(tag) && cp.htmlFlowReal) {
|
|
1061
|
+
cp.phasePoisonedAt = Math.min(cp.phasePoisonedAt, ln.start + lastLt);
|
|
1062
|
+
}
|
|
1063
|
+
if (cp.htmlFlowReal) {
|
|
1064
|
+
cp.tagAcrossLines = true;
|
|
1065
|
+
cp.tagAcrossLinesIndent = ln.indent;
|
|
1066
|
+
const attrs = { state: "outside" };
|
|
1067
|
+
scanTagAttrs(m2[3] + "\n", 0, m2[3].length + 1, attrs);
|
|
1068
|
+
cp.tagAcrossLinesState = attrs.state;
|
|
1069
|
+
}
|
|
1070
|
+
if (closing) {
|
|
1071
|
+
if (!VOID_TAGS.has(tag) && cp.htmlFlowReal) cp.pendingTruncatedCloses.push(tag);
|
|
1072
|
+
} else if (!VOID_TAGS.has(tag)) {
|
|
848
1073
|
applyTag(tag, closing);
|
|
849
1074
|
const rawLastLt = ln.text.lastIndexOf("<");
|
|
850
1075
|
const rawTruncated = rawLastLt !== -1 && !ln.text.includes(">", rawLastLt);
|
|
@@ -1387,6 +1612,9 @@ function countTrailingNewlines(value) {
|
|
|
1387
1612
|
function countNewlines(text, end = text.length) {
|
|
1388
1613
|
let count = 0;
|
|
1389
1614
|
for (let i = text.indexOf("\n"); i !== -1 && i < end; i = text.indexOf("\n", i + 1)) count += 1;
|
|
1615
|
+
for (let i = text.indexOf("\r"); i !== -1 && i < end; i = text.indexOf("\r", i + 1)) {
|
|
1616
|
+
if (text.charCodeAt(i + 1) !== 10) count += 1;
|
|
1617
|
+
}
|
|
1390
1618
|
return count;
|
|
1391
1619
|
}
|
|
1392
1620
|
|
|
@@ -1506,7 +1734,7 @@ function normalizeId(s) {
|
|
|
1506
1734
|
return normalizeIdentifier3(s);
|
|
1507
1735
|
}
|
|
1508
1736
|
function normalizeForMatch(s) {
|
|
1509
|
-
return normalizeIdentifier3(s
|
|
1737
|
+
return normalizeIdentifier3(s);
|
|
1510
1738
|
}
|
|
1511
1739
|
|
|
1512
1740
|
// src/components/collectDefLabels.ts
|
|
@@ -1824,22 +2052,68 @@ function createRegistry(onEmpty) {
|
|
|
1824
2052
|
labelSet: { footnoteLabels: /* @__PURE__ */ new Set(), linkLabels: /* @__PURE__ */ new Set() },
|
|
1825
2053
|
version: 0,
|
|
1826
2054
|
_reactIdMap: /* @__PURE__ */ new Map(),
|
|
2055
|
+
/** Symbol → its `documentIndex`, for chunks that supplied one. */
|
|
2056
|
+
_chunkIndex: /* @__PURE__ */ new Map(),
|
|
1827
2057
|
_subscribers: /* @__PURE__ */ new Set(),
|
|
1828
2058
|
_notifyScheduled: false,
|
|
1829
|
-
allocateSymbol(reactId) {
|
|
2059
|
+
allocateSymbol(reactId, rawDocumentIndex) {
|
|
2060
|
+
const documentIndex = rawDocumentIndex !== void 0 && Number.isFinite(rawDocumentIndex) ? rawDocumentIndex : void 0;
|
|
2061
|
+
if (rawDocumentIndex !== void 0 && documentIndex === void 0) {
|
|
2062
|
+
console.warn(
|
|
2063
|
+
`[ai-react-markdown] documentIndex must be a finite number \u2014 received ${String(rawDocumentIndex)}; ignoring it for this chunk.`
|
|
2064
|
+
);
|
|
2065
|
+
}
|
|
1830
2066
|
const existing = this._reactIdMap.get(reactId);
|
|
1831
2067
|
if (existing) {
|
|
1832
2068
|
existing.refcount++;
|
|
2069
|
+
const moved = documentIndex !== void 0 ? this._chunkIndex.get(existing.symbol) !== documentIndex : this._chunkIndex.has(existing.symbol);
|
|
2070
|
+
if (moved) {
|
|
2071
|
+
const at = this.chunkOrder.indexOf(existing.symbol);
|
|
2072
|
+
if (at !== -1) this.chunkOrder.splice(at, 1);
|
|
2073
|
+
this._placeChunk(existing.symbol, documentIndex);
|
|
2074
|
+
this._notify();
|
|
2075
|
+
}
|
|
1833
2076
|
return existing.symbol;
|
|
1834
2077
|
}
|
|
1835
2078
|
const sym = Symbol(reactId);
|
|
1836
2079
|
this._reactIdMap.set(reactId, { symbol: sym, refcount: 1 });
|
|
1837
|
-
this.
|
|
2080
|
+
this._placeChunk(sym, documentIndex);
|
|
1838
2081
|
this._notify();
|
|
1839
2082
|
return sym;
|
|
1840
2083
|
},
|
|
1841
|
-
|
|
1842
|
-
|
|
2084
|
+
/** Put `sym` into `chunkOrder` at its document position. Without an index
|
|
2085
|
+
* it goes last (mount order — the historical behaviour); with one it
|
|
2086
|
+
* sorts before the first chunk that sits later, where a chunk WITHOUT an
|
|
2087
|
+
* index counts as "later" so an indexed chunk never lands behind one
|
|
2088
|
+
* whose position is unknown. */
|
|
2089
|
+
_placeChunk(sym, documentIndex) {
|
|
2090
|
+
if (this.chunkOrder.length > 0) {
|
|
2091
|
+
const anyIndexed = documentIndex !== void 0 || this.chunkOrder.some((s) => this._chunkIndex.has(s));
|
|
2092
|
+
const anyPlain = documentIndex === void 0 || this.chunkOrder.some((s) => !this._chunkIndex.has(s));
|
|
2093
|
+
if (anyIndexed && anyPlain) {
|
|
2094
|
+
console.warn(
|
|
2095
|
+
"[ai-react-markdown] Some chunks of this document supply `documentIndex` and some do not. Indexed chunks always sort ahead of un-indexed ones, so footnote numbering and aggregate-footer placement will not follow document order. Pass `documentIndex` to every chunk, or to none."
|
|
2096
|
+
);
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
if (documentIndex === void 0) {
|
|
2100
|
+
this._chunkIndex.delete(sym);
|
|
2101
|
+
this.chunkOrder.push(sym);
|
|
2102
|
+
return;
|
|
2103
|
+
}
|
|
2104
|
+
this._chunkIndex.set(sym, documentIndex);
|
|
2105
|
+
let at = this.chunkOrder.length;
|
|
2106
|
+
for (let i = 0; i < this.chunkOrder.length; i++) {
|
|
2107
|
+
const other = this._chunkIndex.get(this.chunkOrder[i]);
|
|
2108
|
+
if (other === void 0 || other > documentIndex) {
|
|
2109
|
+
at = i;
|
|
2110
|
+
break;
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
this.chunkOrder.splice(at, 0, sym);
|
|
2114
|
+
},
|
|
2115
|
+
registerChunk(reactId, footnotes, links, documentIndex) {
|
|
2116
|
+
const sym = this.allocateSymbol(reactId, documentIndex);
|
|
1843
2117
|
this.contributeLabels(sym, footnotes, links);
|
|
1844
2118
|
return sym;
|
|
1845
2119
|
},
|
|
@@ -1862,6 +2136,7 @@ function createRegistry(onEmpty) {
|
|
|
1862
2136
|
this._reactIdMap.delete(reactId);
|
|
1863
2137
|
const idx = this.chunkOrder.indexOf(entry.symbol);
|
|
1864
2138
|
if (idx !== -1) this.chunkOrder.splice(idx, 1);
|
|
2139
|
+
this._chunkIndex.delete(entry.symbol);
|
|
1865
2140
|
this.chunkData.delete(entry.symbol);
|
|
1866
2141
|
const nextFn = /* @__PURE__ */ new Set();
|
|
1867
2142
|
const nextLink = /* @__PURE__ */ new Set();
|
|
@@ -3488,17 +3763,28 @@ function mergeClassNameAllowlist(existing, extraClassNames) {
|
|
|
3488
3763
|
return entries;
|
|
3489
3764
|
}
|
|
3490
3765
|
var crossChunkTags = ["cross-chunk-link", "cross-chunk-image", "footnote-sup"];
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3766
|
+
function deepFreeze(value) {
|
|
3767
|
+
if (value !== null && typeof value === "object" && !Object.isFrozen(value)) {
|
|
3768
|
+
Object.freeze(value);
|
|
3769
|
+
for (const key of Object.keys(value)) deepFreeze(value[key]);
|
|
3770
|
+
}
|
|
3771
|
+
return value;
|
|
3772
|
+
}
|
|
3773
|
+
var STRIPPED_TAGS = ["script", "style", "title", "textarea", "noframes", "noembed", "xmp", "iframe", "plaintext"];
|
|
3774
|
+
var sanitizeSchema = deepFreeze(
|
|
3775
|
+
cloneDeep_default({
|
|
3776
|
+
...defaultSchema,
|
|
3777
|
+
tagNames: [...defaultSchema.tagNames || [], "mark", ...crossChunkTags],
|
|
3778
|
+
attributes: {
|
|
3779
|
+
...defaultSchema.attributes,
|
|
3780
|
+
code: mergeClassNameAllowlist(defaultSchema.attributes?.code, ["math-inline", "math-display"]),
|
|
3781
|
+
"cross-chunk-link": ["label", "referenceType", "documentId", "localUrl", "localTitle"],
|
|
3782
|
+
"cross-chunk-image": ["label", "referenceType", "documentId", "alt", "localUrl", "localTitle"],
|
|
3783
|
+
"footnote-sup": ["label", "localOccurrence", "localNumber", "documentId"]
|
|
3784
|
+
},
|
|
3785
|
+
strip: [.../* @__PURE__ */ new Set([...defaultSchema.strip || [], ...STRIPPED_TAGS])]
|
|
3786
|
+
})
|
|
3787
|
+
);
|
|
3502
3788
|
|
|
3503
3789
|
// src/components/crossChunkUrlSanitize.ts
|
|
3504
3790
|
function fakeElement(tagName, key, url) {
|
|
@@ -3821,7 +4107,12 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
3821
4107
|
return;
|
|
3822
4108
|
}
|
|
3823
4109
|
tentativeEnd = ends[ends.length - 1];
|
|
3824
|
-
|
|
4110
|
+
let hold = 1;
|
|
4111
|
+
if (!finished && ends.length > 1) {
|
|
4112
|
+
const last = source.charCodeAt(source.length - 1);
|
|
4113
|
+
if (last >= 55296 && last <= 56319) hold = 2;
|
|
4114
|
+
}
|
|
4115
|
+
const confirmedEnds = finished ? ends : ends.slice(0, -hold);
|
|
3825
4116
|
for (const end of confirmedEnds) pending.push(end);
|
|
3826
4117
|
};
|
|
3827
4118
|
const snap = (next) => {
|
|
@@ -3944,10 +4235,17 @@ function lineIndentBefore(content, pos) {
|
|
|
3944
4235
|
function findClosingBacktickRun(content, start, n) {
|
|
3945
4236
|
let i = start;
|
|
3946
4237
|
while (i < content.length) {
|
|
3947
|
-
|
|
4238
|
+
const ch = content[i];
|
|
4239
|
+
if (ch === "`") {
|
|
3948
4240
|
const runLen = getRepeatedMarkerLength(content, i, "`");
|
|
3949
4241
|
if (runLen === n) return i;
|
|
3950
4242
|
i += runLen;
|
|
4243
|
+
} else if (ch === "\n" || ch === "\r") {
|
|
4244
|
+
let j = i + 1;
|
|
4245
|
+
if (ch === "\r" && content[j] === "\n") j += 1;
|
|
4246
|
+
while (j < content.length && (content[j] === " " || content[j] === " ")) j += 1;
|
|
4247
|
+
if (j >= content.length || content[j] === "\n" || content[j] === "\r") return -1;
|
|
4248
|
+
i += 1;
|
|
3951
4249
|
} else {
|
|
3952
4250
|
i += 1;
|
|
3953
4251
|
}
|
|
@@ -4047,47 +4345,85 @@ function escapeMhchemCommands(text) {
|
|
|
4047
4345
|
return text.replaceAll("$\\ce{", "$\\\\ce{").replaceAll("$\\pu{", "$\\\\pu{");
|
|
4048
4346
|
}
|
|
4049
4347
|
var CURRENCY_REGEX = /(?<![\\$])\$(?!\$)(?=\d+(?:,\d{3})*(?:\.\d+)?(?:[KMBkmb])?(?:\s|$|[^a-zA-Z\d]))/g;
|
|
4050
|
-
var NO_ESCAPED_DOLLAR_REGEX = /(?<![\\$])\$(?!\$)/g;
|
|
4051
4348
|
var DELIMITERS_REGEX = /(?<!!)\\\[([\S\s]*?[^\\])\\](?!\()|\\\((.*?)\\\)/g;
|
|
4052
4349
|
var ARRAY_COL_SPEC_OR_PIPE_REGEX = /(\\begin\{(?:array|tabular[x*]?)\}\{[^}]*\})|(?<!\\)\|/g;
|
|
4053
|
-
var
|
|
4350
|
+
var EVEN_BACKSLASHES = String.raw`(?<=(?:^|[^\\])(?:\\\\)*)`;
|
|
4351
|
+
var LATEX_BLOCK_REGEX = new RegExp(
|
|
4352
|
+
String.raw`${EVEN_BACKSLASHES}\$\$([\S\s]*?)${EVEN_BACKSLASHES}\$\$|(?<![\\$])\$(?!\$)((?:[^$\n]|\\\$)*?)(?<![\\` + "`" + String.raw`])\$(?!\$)`,
|
|
4353
|
+
"g"
|
|
4354
|
+
);
|
|
4054
4355
|
var TEXT_COMMAND = "\\text{";
|
|
4055
4356
|
var SINGLE_DOLLAR_REGEX = /(?<![\\$])\$(?!\$)((?:[^$\n]|\\[$])+?)(?<!\\)(?<!`)\$(?!\$)/g;
|
|
4357
|
+
function countBareDollars(str, from, to, prev, next) {
|
|
4358
|
+
let n = 0;
|
|
4359
|
+
for (let j = from; j < to; j++) {
|
|
4360
|
+
if (str.charCodeAt(j) !== 36) continue;
|
|
4361
|
+
const before = j > from ? str[j - 1] : prev;
|
|
4362
|
+
const after = j + 1 < to ? str[j + 1] : next;
|
|
4363
|
+
if (before !== "\\" && before !== "$" && after !== "$") n += 1;
|
|
4364
|
+
}
|
|
4365
|
+
return n;
|
|
4366
|
+
}
|
|
4056
4367
|
function escapeCurrencyDollarSigns(text) {
|
|
4057
4368
|
const parts = [];
|
|
4058
4369
|
let lastIndex = 0;
|
|
4059
4370
|
const currencyMatches = Array.from(text.matchAll(CURRENCY_REGEX));
|
|
4060
4371
|
let currentLineProcessed = "";
|
|
4372
|
+
let currentLineDollars = 0;
|
|
4373
|
+
const appendToLine = (piece) => {
|
|
4374
|
+
if (piece.length === 0) return;
|
|
4375
|
+
const prevLast = currentLineProcessed.length > 0 ? currentLineProcessed[currentLineProcessed.length - 1] : "";
|
|
4376
|
+
const prevBeforeLast = currentLineProcessed.length > 1 ? currentLineProcessed[currentLineProcessed.length - 2] : "";
|
|
4377
|
+
const prevLastCounted = prevLast === "$" && prevBeforeLast !== "\\" && prevBeforeLast !== "$";
|
|
4378
|
+
if (prevLastCounted && piece[0] === "$") currentLineDollars -= 1;
|
|
4379
|
+
currentLineDollars += countBareDollars(piece, 0, piece.length, prevLast, "");
|
|
4380
|
+
currentLineProcessed += piece;
|
|
4381
|
+
};
|
|
4382
|
+
const resetLine = (rest) => {
|
|
4383
|
+
currentLineProcessed = "";
|
|
4384
|
+
currentLineDollars = 0;
|
|
4385
|
+
appendToLine(rest);
|
|
4386
|
+
};
|
|
4061
4387
|
for (let i = 0; i < currencyMatches.length; i++) {
|
|
4062
4388
|
const match = currencyMatches[i];
|
|
4063
4389
|
const segment = text.substring(lastIndex, match.index);
|
|
4064
4390
|
parts.push(segment);
|
|
4065
4391
|
const newlineIdx = Math.max(segment.lastIndexOf("\n"), segment.lastIndexOf("\r"));
|
|
4066
4392
|
if (newlineIdx !== -1) {
|
|
4067
|
-
|
|
4393
|
+
resetLine(segment.substring(newlineIdx + 1));
|
|
4068
4394
|
} else {
|
|
4069
|
-
|
|
4395
|
+
appendToLine(segment);
|
|
4070
4396
|
}
|
|
4071
4397
|
let needEscape = true;
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4398
|
+
const restStart = match.index + 1;
|
|
4399
|
+
const restEnd = i < currencyMatches.length - 1 ? currencyMatches[i + 1].index : text.length;
|
|
4400
|
+
let firstLineBeforeNextMatch = "";
|
|
4401
|
+
if (restEnd - restStart > 0) {
|
|
4402
|
+
let eol = restEnd;
|
|
4403
|
+
for (let k = restStart; k < restEnd; k++) {
|
|
4404
|
+
const c = text.charCodeAt(k);
|
|
4405
|
+
if (c === 10 || c === 13) {
|
|
4406
|
+
eol = k;
|
|
4407
|
+
break;
|
|
4408
|
+
}
|
|
4077
4409
|
}
|
|
4078
|
-
|
|
4079
|
-
restBeforeNextMatchOrEnd = text.substring(match.index + 1);
|
|
4410
|
+
firstLineBeforeNextMatch = text.substring(restStart, eol);
|
|
4080
4411
|
}
|
|
4081
|
-
const
|
|
4082
|
-
if (
|
|
4083
|
-
const
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4412
|
+
const restDollars = countBareDollars(firstLineBeforeNextMatch, 0, firstLineBeforeNextMatch.length, "", "");
|
|
4413
|
+
if (restDollars % 2 !== 0) {
|
|
4414
|
+
const L = currentLineProcessed;
|
|
4415
|
+
const lLast = L.length > 0 ? L[L.length - 1] : "";
|
|
4416
|
+
const lBeforeLast = L.length > 1 ? L[L.length - 2] : "";
|
|
4417
|
+
const lLastCounted = lLast === "$" && lBeforeLast !== "\\" && lBeforeLast !== "$";
|
|
4418
|
+
const f0 = firstLineBeforeNextMatch[0];
|
|
4419
|
+
let whole = currentLineDollars + restDollars;
|
|
4420
|
+
if (lLastCounted && f0 === "$") whole -= 1;
|
|
4421
|
+
if (f0 === "$" && (lLast === "\\" || lLast === "$") && firstLineBeforeNextMatch[1] !== "$") whole -= 1;
|
|
4422
|
+
if (whole % 2 !== 0) needEscape = false;
|
|
4087
4423
|
}
|
|
4088
4424
|
const replacement = needEscape ? "\\$" : "$";
|
|
4089
4425
|
parts.push(replacement);
|
|
4090
|
-
|
|
4426
|
+
appendToLine(replacement);
|
|
4091
4427
|
lastIndex = match.index + 1;
|
|
4092
4428
|
}
|
|
4093
4429
|
parts.push(text.substring(lastIndex));
|
|
@@ -4155,8 +4491,7 @@ function escapeLatexPipesInUnclosed(text) {
|
|
|
4155
4491
|
const tail = text.substring(unclosedStart + delimLen);
|
|
4156
4492
|
return before + delim + replaceUnescapedPipes(tail);
|
|
4157
4493
|
}
|
|
4158
|
-
function truncateUnclosedLatexBlock(text) {
|
|
4159
|
-
const unclosedStart = findUnclosedDelimiterStart(text, "double-only");
|
|
4494
|
+
function truncateUnclosedLatexBlock(text, unclosedStart = findUnclosedDelimiterStart(text, "double-only")) {
|
|
4160
4495
|
if (unclosedStart === -1) return text;
|
|
4161
4496
|
return text.substring(0, unclosedStart).trimEnd();
|
|
4162
4497
|
}
|
|
@@ -4244,39 +4579,50 @@ function hasUnclosedTextCommand(text) {
|
|
|
4244
4579
|
return false;
|
|
4245
4580
|
}
|
|
4246
4581
|
var RESIDUAL_OPEN_BRACKET_RE = /(?<!!)\\\[/;
|
|
4247
|
-
|
|
4582
|
+
var LEADING_DOUBLE_DOLLAR_RE = /^\s*\$\$/;
|
|
4583
|
+
function processSliceInstrumented(slice, probe = true) {
|
|
4248
4584
|
const segments = splitByProtectedRegions(slice);
|
|
4249
|
-
|
|
4585
|
+
const parts = [];
|
|
4250
4586
|
let quiescent = true;
|
|
4251
4587
|
let truncatedAtSeamStart = false;
|
|
4252
4588
|
for (let index = 0; index < segments.length; index++) {
|
|
4253
4589
|
const segment = segments[index];
|
|
4254
4590
|
if (segment.isCode) {
|
|
4255
|
-
|
|
4591
|
+
parts.push(segment.text);
|
|
4256
4592
|
continue;
|
|
4257
4593
|
}
|
|
4258
4594
|
let text = segment.text;
|
|
4259
4595
|
text = escapeMhchemCommands(text);
|
|
4260
4596
|
text = escapeCurrencyDollarSigns(text);
|
|
4261
4597
|
text = convertLatexDelimiters(text);
|
|
4262
|
-
if (RESIDUAL_OPEN_BRACKET_RE.test(text)) quiescent = false;
|
|
4598
|
+
if (probe && RESIDUAL_OPEN_BRACKET_RE.test(text)) quiescent = false;
|
|
4263
4599
|
text = escapeLatexPipes(text);
|
|
4264
|
-
if (findUnclosedDelimiterStart(text, "both") !== -1) quiescent = false;
|
|
4600
|
+
if (probe && findUnclosedDelimiterStart(text, "both") !== -1) quiescent = false;
|
|
4265
4601
|
text = escapeLatexPipesInUnclosed(text);
|
|
4266
|
-
if (hasUnclosedTextCommand(text)) quiescent = false;
|
|
4602
|
+
if (probe && hasUnclosedTextCommand(text)) quiescent = false;
|
|
4267
4603
|
text = escapeTextUnderscores(text);
|
|
4268
4604
|
text = convertSingleToDoubleDollar(text);
|
|
4269
|
-
|
|
4270
|
-
if (
|
|
4271
|
-
|
|
4272
|
-
if (
|
|
4273
|
-
|
|
4605
|
+
let unclosedDouble;
|
|
4606
|
+
if (probe || index === 0 && LEADING_DOUBLE_DOLLAR_RE.test(text)) {
|
|
4607
|
+
unclosedDouble = findUnclosedDelimiterStart(text, "double-only");
|
|
4608
|
+
if (unclosedDouble !== -1) {
|
|
4609
|
+
quiescent = false;
|
|
4610
|
+
if (index === 0 && text.slice(0, unclosedDouble).trim() === "") {
|
|
4611
|
+
truncatedAtSeamStart = true;
|
|
4612
|
+
}
|
|
4274
4613
|
}
|
|
4275
4614
|
}
|
|
4276
|
-
text = truncateUnclosedLatexBlock(text);
|
|
4277
|
-
|
|
4615
|
+
text = truncateUnclosedLatexBlock(text, unclosedDouble);
|
|
4616
|
+
parts.push(text);
|
|
4278
4617
|
}
|
|
4279
|
-
return { out, quiescent, truncatedAtSeamStart };
|
|
4618
|
+
return { out: parts.join(""), quiescent, truncatedAtSeamStart };
|
|
4619
|
+
}
|
|
4620
|
+
function isBlankRawLine(text, from, to) {
|
|
4621
|
+
for (let i = from; i < to; i++) {
|
|
4622
|
+
const c = text.charCodeAt(i);
|
|
4623
|
+
if (c !== 32 && c !== 9 && c !== 13) return false;
|
|
4624
|
+
}
|
|
4625
|
+
return true;
|
|
4280
4626
|
}
|
|
4281
4627
|
function findRawSafeCut(active) {
|
|
4282
4628
|
const segments = splitByProtectedRegions(active);
|
|
@@ -4291,10 +4637,12 @@ function findRawSafeCut(active) {
|
|
|
4291
4637
|
continue;
|
|
4292
4638
|
}
|
|
4293
4639
|
const text = segment.text;
|
|
4640
|
+
let atLineStart = offset === 0 || active.charCodeAt(offset - 1) === 10;
|
|
4294
4641
|
let lineStart = 0;
|
|
4295
4642
|
while (lineStart <= text.length) {
|
|
4296
4643
|
const nl = text.indexOf("\n", lineStart);
|
|
4297
4644
|
const lineEnd = nl === -1 ? text.length : nl;
|
|
4645
|
+
if (atLineStart && nl !== -1 && isBlankRawLine(text, lineStart, lineEnd)) backtickHazard = false;
|
|
4298
4646
|
for (let i = lineStart; i < lineEnd; i++) {
|
|
4299
4647
|
const ch = text[i];
|
|
4300
4648
|
if (ch === "`") backtickHazard = true;
|
|
@@ -4307,6 +4655,7 @@ function findRawSafeCut(active) {
|
|
|
4307
4655
|
if (nl === -1) break;
|
|
4308
4656
|
if (!backtickHazard && !latentLt) lastCut = offset + nl + 1;
|
|
4309
4657
|
lineStart = nl + 1;
|
|
4658
|
+
atLineStart = true;
|
|
4310
4659
|
}
|
|
4311
4660
|
offset += text.length;
|
|
4312
4661
|
}
|
|
@@ -4315,11 +4664,14 @@ function findRawSafeCut(active) {
|
|
|
4315
4664
|
var DEFAULT_FREEZE_ATTEMPT_THRESHOLD = 512;
|
|
4316
4665
|
function createIncrementalLatexPreprocessor(options) {
|
|
4317
4666
|
const freezeThreshold = options?.freezeThreshold ?? DEFAULT_FREEZE_ATTEMPT_THRESHOLD;
|
|
4667
|
+
const onAttempt = options?.onAttempt;
|
|
4668
|
+
const backoff = options?.backoff ?? true;
|
|
4318
4669
|
let prevSource = "";
|
|
4319
4670
|
let prevOutput = "";
|
|
4320
4671
|
let frozenSrcEnd = 0;
|
|
4321
4672
|
let frozenOut = "";
|
|
4322
4673
|
let triggered = false;
|
|
4674
|
+
let nextAttemptLen = 0;
|
|
4323
4675
|
return function incrementalPreprocessLaTeX(source) {
|
|
4324
4676
|
if (source === prevSource) return prevOutput;
|
|
4325
4677
|
const isAppend = source.length > prevSource.length && source.startsWith(prevSource);
|
|
@@ -4327,6 +4679,7 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
4327
4679
|
frozenSrcEnd = 0;
|
|
4328
4680
|
frozenOut = "";
|
|
4329
4681
|
triggered = false;
|
|
4682
|
+
nextAttemptLen = 0;
|
|
4330
4683
|
}
|
|
4331
4684
|
if (!triggered) {
|
|
4332
4685
|
const checkFrom = isAppend ? Math.max(0, prevSource.length - 1) : 0;
|
|
@@ -4338,18 +4691,26 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
4338
4691
|
triggered = true;
|
|
4339
4692
|
}
|
|
4340
4693
|
let active = source.slice(frozenSrcEnd);
|
|
4341
|
-
if (active.length > freezeThreshold) {
|
|
4694
|
+
if (active.length > freezeThreshold && active.length >= nextAttemptLen) {
|
|
4695
|
+
const activeLength = active.length;
|
|
4696
|
+
let advanced = false;
|
|
4697
|
+
let frozenBytes = 0;
|
|
4698
|
+
const freeze = (cut2, slice) => {
|
|
4699
|
+
frozenOut += slice.out;
|
|
4700
|
+
frozenSrcEnd += cut2;
|
|
4701
|
+
active = source.slice(frozenSrcEnd);
|
|
4702
|
+
advanced = true;
|
|
4703
|
+
frozenBytes = cut2;
|
|
4704
|
+
};
|
|
4342
4705
|
const cut = findRawSafeCut(active);
|
|
4343
4706
|
if (cut > 0) {
|
|
4344
4707
|
const candidate = processSliceInstrumented(active.slice(0, cut));
|
|
4345
|
-
if (candidate.quiescent)
|
|
4346
|
-
frozenOut += candidate.out;
|
|
4347
|
-
frozenSrcEnd += cut;
|
|
4348
|
-
active = source.slice(frozenSrcEnd);
|
|
4349
|
-
}
|
|
4708
|
+
if (candidate.quiescent) freeze(cut, candidate);
|
|
4350
4709
|
}
|
|
4710
|
+
nextAttemptLen = advanced || !backoff ? 0 : active.length * 2;
|
|
4711
|
+
onAttempt?.({ activeLength, frozenBytes });
|
|
4351
4712
|
}
|
|
4352
|
-
const tail = processSliceInstrumented(active);
|
|
4713
|
+
const tail = processSliceInstrumented(active, false);
|
|
4353
4714
|
const head = tail.truncatedAtSeamStart ? frozenOut.replace(/\s+$/, "") : frozenOut;
|
|
4354
4715
|
const out = head + tail.out;
|
|
4355
4716
|
prevSource = source;
|
|
@@ -4379,7 +4740,6 @@ function createRemendPreprocessor(options) {
|
|
|
4379
4740
|
}
|
|
4380
4741
|
export {
|
|
4381
4742
|
DEFAULT_PAYLOAD,
|
|
4382
|
-
DEF_LINE_START_RE,
|
|
4383
4743
|
PIPELINE_STAGES,
|
|
4384
4744
|
SENTINEL_FN_CONTENT,
|
|
4385
4745
|
SENTINEL_LINK_URL,
|
|
@@ -4414,7 +4774,6 @@ export {
|
|
|
4414
4774
|
hasLoneSurrogate,
|
|
4415
4775
|
highlight,
|
|
4416
4776
|
isFootnoteSection,
|
|
4417
|
-
lastRegionStart,
|
|
4418
4777
|
measureStage,
|
|
4419
4778
|
mergeClassNameAllowlist,
|
|
4420
4779
|
normalizeForMatch,
|