@ai-react-markdown/engine 2.4.5 → 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 +1 -1
- package/dist/index.cjs +334 -60
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +52 -58
- package/dist/index.d.ts +52 -58
- package/dist/index.dev.cjs +334 -60
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +334 -58
- package/dist/index.dev.js.map +1 -1
- package/dist/index.js +334 -58
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.dev.js
CHANGED
|
@@ -177,10 +177,73 @@ 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
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"];
|
|
180
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
|
+
]);
|
|
181
243
|
var TYPE6_START_RE = /^<\/?([A-Za-z][A-Za-z0-9-]*)(?:[ \t\r]|\/?>|$)/;
|
|
182
244
|
var TYPE1_START_RE = /^<(script|pre|style|textarea)(?:[ \t\r]|>|$)/i;
|
|
183
|
-
var TYPE7_LINE_RE =
|
|
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];
|
|
184
247
|
var VOID_TAGS = /* @__PURE__ */ new Set([
|
|
185
248
|
"area",
|
|
186
249
|
"base",
|
|
@@ -204,7 +267,35 @@ var DEF_RE = /^ {0,3}\[((?:[^[\]\\]|\\.)+)\]:/;
|
|
|
204
267
|
var FENCE_RE = /^ {0,3}(`{3,}|~{3,})/;
|
|
205
268
|
var MATH_RUN_RE = /^ {0,3}(\$\$+)/;
|
|
206
269
|
var TAG_OR_COMMENT_RE = /<(\/?)([A-Za-z][A-Za-z0-9-]*)(?=[\s/>])([^>]*)>|<!--|-->|--!>/g;
|
|
207
|
-
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
|
+
}
|
|
208
299
|
var REF_RE = /!?\[((?:[^[\]\\]|\\.)*)\]/g;
|
|
209
300
|
var BACKTICK_RUN_RE = /`+/g;
|
|
210
301
|
var MD_BLANK_RE = /^[ \t\r]*$/;
|
|
@@ -299,6 +390,8 @@ function freshCheckpoint(defListEnabled, mathFlow, referenceTaint) {
|
|
|
299
390
|
openTotal: 0,
|
|
300
391
|
commentOpen: false,
|
|
301
392
|
piOpen: false,
|
|
393
|
+
bogusOpen: false,
|
|
394
|
+
rawTextOpen: null,
|
|
302
395
|
declOpen: false,
|
|
303
396
|
cdataOpen: false,
|
|
304
397
|
inFence: false,
|
|
@@ -323,6 +416,7 @@ function freshCheckpoint(defListEnabled, mathFlow, referenceTaint) {
|
|
|
323
416
|
pendingTruncatedCloses: [],
|
|
324
417
|
tagAcrossLines: false,
|
|
325
418
|
tagAcrossLinesIndent: 0,
|
|
419
|
+
tagAcrossLinesState: "outside",
|
|
326
420
|
htmlFlowReal: false
|
|
327
421
|
};
|
|
328
422
|
}
|
|
@@ -422,11 +516,21 @@ function computeFreezeBoundary(text, options, resume) {
|
|
|
422
516
|
let start = cp.confirmedOffset;
|
|
423
517
|
let tailLine = null;
|
|
424
518
|
while (start < text.length) {
|
|
425
|
-
let end = text.
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
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);
|
|
430
534
|
const ln = {
|
|
431
535
|
start,
|
|
432
536
|
end,
|
|
@@ -518,14 +622,33 @@ function processConfirmedLine(cp, ln, text) {
|
|
|
518
622
|
newest.defListSettled = ln.blank ? true : !canBecomeDdLine(ln.text, true);
|
|
519
623
|
}
|
|
520
624
|
const isBlockStart = cp.prevLineBlank;
|
|
521
|
-
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)) {
|
|
522
626
|
const defShapedLine = DEF_RE.test(ln.text) || FOOTNOTE_DEF_RE.test(ln.text);
|
|
523
627
|
const commentOnly = ln.text.replace(/<!--[\s\S]*?-->/g, " ").replace(/<!--[\s\S]*$/, " ").replace(/[ \t\r]/g, "") === "";
|
|
524
628
|
if (!defShapedLine && !commentOnly) {
|
|
525
629
|
cp.htmlSeamPending = false;
|
|
526
630
|
}
|
|
527
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
|
+
};
|
|
528
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
|
+
}
|
|
529
652
|
if (closing) {
|
|
530
653
|
const count = cp.tagBalance.get(tag) ?? 0;
|
|
531
654
|
if (count > 0) {
|
|
@@ -538,7 +661,7 @@ function processConfirmedLine(cp, ln, text) {
|
|
|
538
661
|
}
|
|
539
662
|
};
|
|
540
663
|
const commentOpenAtLineStart = cp.commentOpen;
|
|
541
|
-
const rawOpenAtLineStart = cp.commentOpen || cp.piOpen || cp.declOpen || cp.cdataOpen;
|
|
664
|
+
const rawOpenAtLineStart = cp.commentOpen || cp.piOpen || cp.declOpen || cp.cdataOpen || cp.bogusOpen;
|
|
542
665
|
if (cp.inFence) {
|
|
543
666
|
const close = FENCE_RE.exec(ln.text);
|
|
544
667
|
if (close && close[1][0] === cp.fenceChar && close[1].length >= cp.fenceLen && isMdBlank(ln.text.slice(close[0].length))) {
|
|
@@ -621,13 +744,21 @@ function processConfirmedLine(cp, ln, text) {
|
|
|
621
744
|
cp.pendingTruncatedTags = [];
|
|
622
745
|
}
|
|
623
746
|
cp.pendingTruncatedCloses = [];
|
|
747
|
+
if (cp.tagAcrossLines && (cp.tagAcrossLinesState === '"' || cp.tagAcrossLinesState === "'")) {
|
|
748
|
+
cp.phasePoisonedAt = Math.min(cp.phasePoisonedAt, ln.start);
|
|
749
|
+
}
|
|
624
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
|
+
}
|
|
625
756
|
cp.blankRun += 1;
|
|
626
757
|
cp.lastBlankStart = ln.start;
|
|
627
758
|
cp.candidates.push({
|
|
628
759
|
offset: Math.min(ln.end + 1, text.length),
|
|
629
760
|
blankRun: cp.blankRun,
|
|
630
|
-
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,
|
|
631
762
|
hazard: cp.hazardVerdict,
|
|
632
763
|
seamRisk: cp.htmlSeamPending,
|
|
633
764
|
defListSettled: null
|
|
@@ -657,7 +788,7 @@ function processConfirmedLine(cp, ln, text) {
|
|
|
657
788
|
const t7 = TYPE7_LINE_RE.exec(t);
|
|
658
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
|
|
659
790
|
// names (those are type 1 as start tags, paragraph as end tags).
|
|
660
|
-
t7 !== null && !cp.prevLineWasText && !TYPE1_NAMES.has(
|
|
791
|
+
t7 !== null && !cp.prevLineWasText && !TYPE1_NAMES.has(t7Name(t).toLowerCase())) {
|
|
661
792
|
cp.htmlFlowReal = true;
|
|
662
793
|
}
|
|
663
794
|
}
|
|
@@ -759,7 +890,7 @@ ${cont(scanText)}` };
|
|
|
759
890
|
pos = c + 3;
|
|
760
891
|
continue;
|
|
761
892
|
}
|
|
762
|
-
if (cp.declOpen) {
|
|
893
|
+
if (cp.declOpen || cp.bogusOpen) {
|
|
763
894
|
const c = scanText.indexOf(">", pos);
|
|
764
895
|
if (c === -1) {
|
|
765
896
|
rawSpans.push([pos, scanText.length]);
|
|
@@ -767,6 +898,7 @@ ${cont(scanText)}` };
|
|
|
767
898
|
}
|
|
768
899
|
rawSpans.push([pos, c + 1]);
|
|
769
900
|
cp.declOpen = false;
|
|
901
|
+
cp.bogusOpen = false;
|
|
770
902
|
pos = c + 1;
|
|
771
903
|
continue;
|
|
772
904
|
}
|
|
@@ -774,10 +906,16 @@ ${cont(scanText)}` };
|
|
|
774
906
|
const cd = scanText.indexOf("<![CDATA[", pos);
|
|
775
907
|
const dm = scanText.slice(pos).search(/<![A-Za-z]/);
|
|
776
908
|
const decl = dm === -1 ? -1 : pos + dm;
|
|
777
|
-
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);
|
|
778
912
|
if (starts.length === 0) break;
|
|
779
913
|
const first = Math.min(...starts);
|
|
780
|
-
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) {
|
|
781
919
|
rawSpans.push([cd, cd + 9]);
|
|
782
920
|
cp.cdataOpen = true;
|
|
783
921
|
pos = cd + 9;
|
|
@@ -804,22 +942,27 @@ ${cont(scanText)}` };
|
|
|
804
942
|
let skipTagScan = false;
|
|
805
943
|
if (cp.tagAcrossLines) {
|
|
806
944
|
if (ln.indent < cp.tagAcrossLinesIndent) poisonRawDivergence();
|
|
807
|
-
const
|
|
945
|
+
const attrs = { state: cp.tagAcrossLinesState };
|
|
946
|
+
const gt = scanTagAttrs(ln.text, 0, ln.text.length, attrs);
|
|
808
947
|
if (gt === -1) {
|
|
948
|
+
scanTagAttrs("\n", 0, 1, attrs);
|
|
949
|
+
cp.tagAcrossLinesState = attrs.state;
|
|
809
950
|
skipTagScan = true;
|
|
810
951
|
} else {
|
|
811
|
-
if (/["']/.test(ln.text.slice(0, gt))) poisonRawDivergence();
|
|
812
952
|
for (const tag of cp.pendingTruncatedCloses) applyTag(tag, true);
|
|
813
953
|
cp.pendingTruncatedCloses = [];
|
|
814
954
|
cp.tagAcrossLines = false;
|
|
955
|
+
cp.tagAcrossLinesState = "outside";
|
|
815
956
|
tagText = " ".repeat(gt + 1) + tagText.slice(gt + 1);
|
|
816
957
|
}
|
|
817
958
|
}
|
|
959
|
+
let tagHandledAsTruncated = false;
|
|
818
960
|
if (!skipTagScan) {
|
|
819
961
|
TAG_OR_COMMENT_RE.lastIndex = 0;
|
|
820
962
|
let m;
|
|
821
963
|
let lastCommentOpenerIdx = -1;
|
|
822
964
|
while ((m = TAG_OR_COMMENT_RE.exec(tagText)) !== null) {
|
|
965
|
+
if (cp.rawTextOpen !== null && (m[0] === "<!--" || m[0] === "-->" || m[0] === "--!>")) continue;
|
|
823
966
|
if (m[0] === "<!--") {
|
|
824
967
|
const next = tagText.slice(m.index + 4, m.index + 6);
|
|
825
968
|
if (cp.commentOpen) {
|
|
@@ -846,8 +989,31 @@ ${cont(scanText)}` };
|
|
|
846
989
|
const closing = m[1] === "/";
|
|
847
990
|
const tag = m[2].toLowerCase();
|
|
848
991
|
if (TABLE_PART_NAMES.has(tag)) cp.phasePoisonedAt = Math.min(cp.phasePoisonedAt, ln.start + m.index);
|
|
849
|
-
|
|
850
|
-
if (
|
|
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;
|
|
851
1017
|
applyTag(tag, closing);
|
|
852
1018
|
}
|
|
853
1019
|
if (cp.commentOpen && lastCommentOpenerIdx !== -1 && !inRawText) {
|
|
@@ -867,25 +1033,39 @@ ${cont(scanText)}` };
|
|
|
867
1033
|
const closing = mr[1] === "/";
|
|
868
1034
|
const tag = mr[2].toLowerCase();
|
|
869
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;
|
|
870
1037
|
const selfClosing = mr[3] !== void 0 && /\/\s*$/.test(mr[3]);
|
|
871
|
-
if (VOID_TAGS.has(tag) || selfClosing) continue;
|
|
1038
|
+
if (VOID_TAGS.has(tag) || selfClosing && honoursSelfClosing(tag)) continue;
|
|
872
1039
|
applyTag(tag, closing);
|
|
873
1040
|
}
|
|
874
1041
|
}
|
|
875
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
|
+
}
|
|
876
1046
|
cp.pendingTruncatedTags = [];
|
|
877
1047
|
}
|
|
878
|
-
if (!cp.commentOpen) {
|
|
879
|
-
|
|
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
|
+
}
|
|
880
1055
|
if (lastLt !== -1 && !tagText.includes(">", lastLt)) {
|
|
881
1056
|
const m2 = TRUNCATED_TAG_RE.exec(tagText.slice(lastLt));
|
|
882
1057
|
if (m2) {
|
|
883
1058
|
const closing = m2[1] === "/";
|
|
884
1059
|
const tag = m2[2].toLowerCase();
|
|
885
|
-
if (TABLE_PART_NAMES.has(tag)
|
|
1060
|
+
if (TABLE_PART_NAMES.has(tag) && cp.htmlFlowReal) {
|
|
1061
|
+
cp.phasePoisonedAt = Math.min(cp.phasePoisonedAt, ln.start + lastLt);
|
|
1062
|
+
}
|
|
886
1063
|
if (cp.htmlFlowReal) {
|
|
887
1064
|
cp.tagAcrossLines = true;
|
|
888
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;
|
|
889
1069
|
}
|
|
890
1070
|
if (closing) {
|
|
891
1071
|
if (!VOID_TAGS.has(tag) && cp.htmlFlowReal) cp.pendingTruncatedCloses.push(tag);
|
|
@@ -1554,7 +1734,7 @@ function normalizeId(s) {
|
|
|
1554
1734
|
return normalizeIdentifier3(s);
|
|
1555
1735
|
}
|
|
1556
1736
|
function normalizeForMatch(s) {
|
|
1557
|
-
return normalizeIdentifier3(s
|
|
1737
|
+
return normalizeIdentifier3(s);
|
|
1558
1738
|
}
|
|
1559
1739
|
|
|
1560
1740
|
// src/components/collectDefLabels.ts
|
|
@@ -1872,22 +2052,68 @@ function createRegistry(onEmpty) {
|
|
|
1872
2052
|
labelSet: { footnoteLabels: /* @__PURE__ */ new Set(), linkLabels: /* @__PURE__ */ new Set() },
|
|
1873
2053
|
version: 0,
|
|
1874
2054
|
_reactIdMap: /* @__PURE__ */ new Map(),
|
|
2055
|
+
/** Symbol → its `documentIndex`, for chunks that supplied one. */
|
|
2056
|
+
_chunkIndex: /* @__PURE__ */ new Map(),
|
|
1875
2057
|
_subscribers: /* @__PURE__ */ new Set(),
|
|
1876
2058
|
_notifyScheduled: false,
|
|
1877
|
-
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
|
+
}
|
|
1878
2066
|
const existing = this._reactIdMap.get(reactId);
|
|
1879
2067
|
if (existing) {
|
|
1880
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
|
+
}
|
|
1881
2076
|
return existing.symbol;
|
|
1882
2077
|
}
|
|
1883
2078
|
const sym = Symbol(reactId);
|
|
1884
2079
|
this._reactIdMap.set(reactId, { symbol: sym, refcount: 1 });
|
|
1885
|
-
this.
|
|
2080
|
+
this._placeChunk(sym, documentIndex);
|
|
1886
2081
|
this._notify();
|
|
1887
2082
|
return sym;
|
|
1888
2083
|
},
|
|
1889
|
-
|
|
1890
|
-
|
|
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);
|
|
1891
2117
|
this.contributeLabels(sym, footnotes, links);
|
|
1892
2118
|
return sym;
|
|
1893
2119
|
},
|
|
@@ -1910,6 +2136,7 @@ function createRegistry(onEmpty) {
|
|
|
1910
2136
|
this._reactIdMap.delete(reactId);
|
|
1911
2137
|
const idx = this.chunkOrder.indexOf(entry.symbol);
|
|
1912
2138
|
if (idx !== -1) this.chunkOrder.splice(idx, 1);
|
|
2139
|
+
this._chunkIndex.delete(entry.symbol);
|
|
1913
2140
|
this.chunkData.delete(entry.symbol);
|
|
1914
2141
|
const nextFn = /* @__PURE__ */ new Set();
|
|
1915
2142
|
const nextLink = /* @__PURE__ */ new Set();
|
|
@@ -3536,17 +3763,28 @@ function mergeClassNameAllowlist(existing, extraClassNames) {
|
|
|
3536
3763
|
return entries;
|
|
3537
3764
|
}
|
|
3538
3765
|
var crossChunkTags = ["cross-chunk-link", "cross-chunk-image", "footnote-sup"];
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
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
|
+
);
|
|
3550
3788
|
|
|
3551
3789
|
// src/components/crossChunkUrlSanitize.ts
|
|
3552
3790
|
function fakeElement(tagName, key, url) {
|
|
@@ -3869,7 +4107,12 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
3869
4107
|
return;
|
|
3870
4108
|
}
|
|
3871
4109
|
tentativeEnd = ends[ends.length - 1];
|
|
3872
|
-
|
|
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);
|
|
3873
4116
|
for (const end of confirmedEnds) pending.push(end);
|
|
3874
4117
|
};
|
|
3875
4118
|
const snap = (next) => {
|
|
@@ -3997,10 +4240,11 @@ function findClosingBacktickRun(content, start, n) {
|
|
|
3997
4240
|
const runLen = getRepeatedMarkerLength(content, i, "`");
|
|
3998
4241
|
if (runLen === n) return i;
|
|
3999
4242
|
i += runLen;
|
|
4000
|
-
} else if (ch === "\n") {
|
|
4243
|
+
} else if (ch === "\n" || ch === "\r") {
|
|
4001
4244
|
let j = i + 1;
|
|
4002
|
-
|
|
4003
|
-
|
|
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;
|
|
4004
4248
|
i += 1;
|
|
4005
4249
|
} else {
|
|
4006
4250
|
i += 1;
|
|
@@ -4101,26 +4345,54 @@ function escapeMhchemCommands(text) {
|
|
|
4101
4345
|
return text.replaceAll("$\\ce{", "$\\\\ce{").replaceAll("$\\pu{", "$\\\\pu{");
|
|
4102
4346
|
}
|
|
4103
4347
|
var CURRENCY_REGEX = /(?<![\\$])\$(?!\$)(?=\d+(?:,\d{3})*(?:\.\d+)?(?:[KMBkmb])?(?:\s|$|[^a-zA-Z\d]))/g;
|
|
4104
|
-
var NO_ESCAPED_DOLLAR_REGEX = /(?<![\\$])\$(?!\$)/g;
|
|
4105
4348
|
var DELIMITERS_REGEX = /(?<!!)\\\[([\S\s]*?[^\\])\\](?!\()|\\\((.*?)\\\)/g;
|
|
4106
4349
|
var ARRAY_COL_SPEC_OR_PIPE_REGEX = /(\\begin\{(?:array|tabular[x*]?)\}\{[^}]*\})|(?<!\\)\|/g;
|
|
4107
|
-
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
|
+
);
|
|
4108
4355
|
var TEXT_COMMAND = "\\text{";
|
|
4109
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
|
+
}
|
|
4110
4367
|
function escapeCurrencyDollarSigns(text) {
|
|
4111
4368
|
const parts = [];
|
|
4112
4369
|
let lastIndex = 0;
|
|
4113
4370
|
const currencyMatches = Array.from(text.matchAll(CURRENCY_REGEX));
|
|
4114
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
|
+
};
|
|
4115
4387
|
for (let i = 0; i < currencyMatches.length; i++) {
|
|
4116
4388
|
const match = currencyMatches[i];
|
|
4117
4389
|
const segment = text.substring(lastIndex, match.index);
|
|
4118
4390
|
parts.push(segment);
|
|
4119
4391
|
const newlineIdx = Math.max(segment.lastIndexOf("\n"), segment.lastIndexOf("\r"));
|
|
4120
4392
|
if (newlineIdx !== -1) {
|
|
4121
|
-
|
|
4393
|
+
resetLine(segment.substring(newlineIdx + 1));
|
|
4122
4394
|
} else {
|
|
4123
|
-
|
|
4395
|
+
appendToLine(segment);
|
|
4124
4396
|
}
|
|
4125
4397
|
let needEscape = true;
|
|
4126
4398
|
const restStart = match.index + 1;
|
|
@@ -4137,15 +4409,21 @@ function escapeCurrencyDollarSigns(text) {
|
|
|
4137
4409
|
}
|
|
4138
4410
|
firstLineBeforeNextMatch = text.substring(restStart, eol);
|
|
4139
4411
|
}
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
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;
|
|
4145
4423
|
}
|
|
4146
4424
|
const replacement = needEscape ? "\\$" : "$";
|
|
4147
4425
|
parts.push(replacement);
|
|
4148
|
-
|
|
4426
|
+
appendToLine(replacement);
|
|
4149
4427
|
lastIndex = match.index + 1;
|
|
4150
4428
|
}
|
|
4151
4429
|
parts.push(text.substring(lastIndex));
|
|
@@ -4213,8 +4491,7 @@ function escapeLatexPipesInUnclosed(text) {
|
|
|
4213
4491
|
const tail = text.substring(unclosedStart + delimLen);
|
|
4214
4492
|
return before + delim + replaceUnescapedPipes(tail);
|
|
4215
4493
|
}
|
|
4216
|
-
function truncateUnclosedLatexBlock(text) {
|
|
4217
|
-
const unclosedStart = findUnclosedDelimiterStart(text, "double-only");
|
|
4494
|
+
function truncateUnclosedLatexBlock(text, unclosedStart = findUnclosedDelimiterStart(text, "double-only")) {
|
|
4218
4495
|
if (unclosedStart === -1) return text;
|
|
4219
4496
|
return text.substring(0, unclosedStart).trimEnd();
|
|
4220
4497
|
}
|
|
@@ -4325,8 +4602,9 @@ function processSliceInstrumented(slice, probe = true) {
|
|
|
4325
4602
|
if (probe && hasUnclosedTextCommand(text)) quiescent = false;
|
|
4326
4603
|
text = escapeTextUnderscores(text);
|
|
4327
4604
|
text = convertSingleToDoubleDollar(text);
|
|
4605
|
+
let unclosedDouble;
|
|
4328
4606
|
if (probe || index === 0 && LEADING_DOUBLE_DOLLAR_RE.test(text)) {
|
|
4329
|
-
|
|
4607
|
+
unclosedDouble = findUnclosedDelimiterStart(text, "double-only");
|
|
4330
4608
|
if (unclosedDouble !== -1) {
|
|
4331
4609
|
quiescent = false;
|
|
4332
4610
|
if (index === 0 && text.slice(0, unclosedDouble).trim() === "") {
|
|
@@ -4334,7 +4612,7 @@ function processSliceInstrumented(slice, probe = true) {
|
|
|
4334
4612
|
}
|
|
4335
4613
|
}
|
|
4336
4614
|
}
|
|
4337
|
-
text = truncateUnclosedLatexBlock(text);
|
|
4615
|
+
text = truncateUnclosedLatexBlock(text, unclosedDouble);
|
|
4338
4616
|
parts.push(text);
|
|
4339
4617
|
}
|
|
4340
4618
|
return { out: parts.join(""), quiescent, truncatedAtSeamStart };
|
|
@@ -4462,7 +4740,6 @@ function createRemendPreprocessor(options) {
|
|
|
4462
4740
|
}
|
|
4463
4741
|
export {
|
|
4464
4742
|
DEFAULT_PAYLOAD,
|
|
4465
|
-
DEF_LINE_START_RE,
|
|
4466
4743
|
PIPELINE_STAGES,
|
|
4467
4744
|
SENTINEL_FN_CONTENT,
|
|
4468
4745
|
SENTINEL_LINK_URL,
|
|
@@ -4497,7 +4774,6 @@ export {
|
|
|
4497
4774
|
hasLoneSurrogate,
|
|
4498
4775
|
highlight,
|
|
4499
4776
|
isFootnoteSection,
|
|
4500
|
-
lastRegionStart,
|
|
4501
4777
|
measureStage,
|
|
4502
4778
|
mergeClassNameAllowlist,
|
|
4503
4779
|
normalizeForMatch,
|