@ai-react-markdown/engine 2.11.0 → 2.13.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/dist/index.cjs +715 -534
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +72 -77
- package/dist/index.d.ts +72 -77
- package/dist/index.dev.cjs +715 -534
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +714 -534
- package/dist/index.dev.js.map +1 -1
- package/dist/index.js +714 -534
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -79,6 +79,7 @@ __export(src_exports, {
|
|
|
79
79
|
rehypeRebaseHashLinks: () => rehypeRebaseHashLinks_default,
|
|
80
80
|
rehypeVerifyEngineTags: () => rehypeVerifyEngineTags,
|
|
81
81
|
removeComments: () => removeComments,
|
|
82
|
+
resolveCrossChunkReference: () => resolveCrossChunkReference,
|
|
82
83
|
sanitizeCrossChunkUrl: () => sanitizeCrossChunkUrl,
|
|
83
84
|
sanitizeSchema: () => sanitizeSchema,
|
|
84
85
|
shortenDocumentId: () => shortenDocumentId,
|
|
@@ -264,8 +265,51 @@ var defaultUrlTransform = (value) => {
|
|
|
264
265
|
return "";
|
|
265
266
|
};
|
|
266
267
|
|
|
267
|
-
// src/components/incrementalParse/
|
|
268
|
-
|
|
268
|
+
// src/components/incrementalParse/freezeScanState.ts
|
|
269
|
+
function freshCheckpoint(defListEnabled, mathFlow, referenceTaint) {
|
|
270
|
+
return {
|
|
271
|
+
defListEnabled,
|
|
272
|
+
mathFlow,
|
|
273
|
+
referenceTaint,
|
|
274
|
+
confirmedOffset: 0,
|
|
275
|
+
candidates: [],
|
|
276
|
+
defs: /* @__PURE__ */ new Map(),
|
|
277
|
+
footnoteDefs: /* @__PURE__ */ new Map(),
|
|
278
|
+
unresolvedRefs: [],
|
|
279
|
+
tagBalance: /* @__PURE__ */ new Map(),
|
|
280
|
+
openTotal: 0,
|
|
281
|
+
p5Tok: { kind: "data" },
|
|
282
|
+
formPointerMaybeSet: false,
|
|
283
|
+
openStack: [],
|
|
284
|
+
mdBlock: { kind: "none" },
|
|
285
|
+
blankRun: 0,
|
|
286
|
+
lastBlankStart: -1,
|
|
287
|
+
hazardVerdict: false,
|
|
288
|
+
prevLineBlank: true,
|
|
289
|
+
// doc start counts as a block start
|
|
290
|
+
prevLineWasText: false,
|
|
291
|
+
prevLineWasValidDef: false,
|
|
292
|
+
prevLineOpenContent: false,
|
|
293
|
+
tableMaybeOpen: false,
|
|
294
|
+
containerMaybeOpen: false,
|
|
295
|
+
paragraphHasUnpairedRun: false,
|
|
296
|
+
openBracket: null,
|
|
297
|
+
p5SealPending: false,
|
|
298
|
+
defBlockMaybeOpen: false,
|
|
299
|
+
fnDefResumable: false,
|
|
300
|
+
phasePoisonedAt: Infinity,
|
|
301
|
+
pendingTruncatedTags: [],
|
|
302
|
+
pendingTruncatedCloses: [],
|
|
303
|
+
pendingTag: null
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
function pendingFenceCloser(checkpoint) {
|
|
307
|
+
const cp = checkpoint;
|
|
308
|
+
if (cp.phasePoisonedAt !== Infinity) return "";
|
|
309
|
+
if (cp.mdBlock.kind === "fence" && cp.mdBlock.indent === 0) return cp.mdBlock.char.repeat(cp.mdBlock.len);
|
|
310
|
+
if (cp.mdBlock.kind === "math" && cp.mdBlock.indent === 0) return "$".repeat(cp.mdBlock.len);
|
|
311
|
+
return "";
|
|
312
|
+
}
|
|
269
313
|
|
|
270
314
|
// src/components/incrementalParse/mdLineText.ts
|
|
271
315
|
var MD_BLANK_RE = /^[ \t\r]*$/;
|
|
@@ -273,6 +317,9 @@ var isMdBlank = (text) => MD_BLANK_RE.test(text);
|
|
|
273
317
|
var mdTrim = (text) => text.replace(/^[ \t\r]+|[ \t\r]+$/g, "");
|
|
274
318
|
var mdTrimStart = (text) => text.replace(/^[ \t\r]+/, "");
|
|
275
319
|
|
|
320
|
+
// src/components/incrementalParse/freezeLineSyntax.ts
|
|
321
|
+
var import_micromark_util_html_tag_name = require("micromark-util-html-tag-name");
|
|
322
|
+
|
|
276
323
|
// src/components/incrementalParse/referenceTaint.ts
|
|
277
324
|
var import_micromark_util_normalize_identifier = require("micromark-util-normalize-identifier");
|
|
278
325
|
var FOOTNOTE_DEF_RE = /^ {0,3}\[\^[^\]]*\]:/;
|
|
@@ -458,7 +505,7 @@ function settleRefsAndEarliestUnresolved(cp) {
|
|
|
458
505
|
return earliestUnresolved;
|
|
459
506
|
}
|
|
460
507
|
|
|
461
|
-
// src/components/incrementalParse/
|
|
508
|
+
// src/components/incrementalParse/freezeLineSyntax.ts
|
|
462
509
|
var TYPE6_NAMES = new Set(import_micromark_util_html_tag_name.htmlBlockNames);
|
|
463
510
|
var TABLE_PART_NAMES = /* @__PURE__ */ new Set(["td", "th", "tr", "tbody", "thead", "tfoot", "caption", "col", "colgroup"]);
|
|
464
511
|
var DOCUMENT_STRUCTURE_NAMES = /* @__PURE__ */ new Set(["html", "head", "body", "frameset"]);
|
|
@@ -709,43 +756,6 @@ function maskIntraLineCodeSpans(text, carryOpen) {
|
|
|
709
756
|
out += text.slice(cursor);
|
|
710
757
|
return { masked: out, unpaired: false };
|
|
711
758
|
}
|
|
712
|
-
function freshCheckpoint(defListEnabled, mathFlow, referenceTaint) {
|
|
713
|
-
return {
|
|
714
|
-
defListEnabled,
|
|
715
|
-
mathFlow,
|
|
716
|
-
referenceTaint,
|
|
717
|
-
confirmedOffset: 0,
|
|
718
|
-
candidates: [],
|
|
719
|
-
defs: /* @__PURE__ */ new Map(),
|
|
720
|
-
footnoteDefs: /* @__PURE__ */ new Map(),
|
|
721
|
-
unresolvedRefs: [],
|
|
722
|
-
tagBalance: /* @__PURE__ */ new Map(),
|
|
723
|
-
openTotal: 0,
|
|
724
|
-
p5Tok: { kind: "data" },
|
|
725
|
-
formPointerMaybeSet: false,
|
|
726
|
-
openStack: [],
|
|
727
|
-
mdBlock: { kind: "none" },
|
|
728
|
-
blankRun: 0,
|
|
729
|
-
lastBlankStart: -1,
|
|
730
|
-
hazardVerdict: false,
|
|
731
|
-
prevLineBlank: true,
|
|
732
|
-
// doc start counts as a block start
|
|
733
|
-
prevLineWasText: false,
|
|
734
|
-
prevLineWasValidDef: false,
|
|
735
|
-
prevLineOpenContent: false,
|
|
736
|
-
tableMaybeOpen: false,
|
|
737
|
-
containerMaybeOpen: false,
|
|
738
|
-
paragraphHasUnpairedRun: false,
|
|
739
|
-
openBracket: null,
|
|
740
|
-
p5SealPending: false,
|
|
741
|
-
defBlockMaybeOpen: false,
|
|
742
|
-
fnDefResumable: false,
|
|
743
|
-
phasePoisonedAt: Infinity,
|
|
744
|
-
pendingTruncatedTags: [],
|
|
745
|
-
pendingTruncatedCloses: [],
|
|
746
|
-
pendingTag: null
|
|
747
|
-
};
|
|
748
|
-
}
|
|
749
759
|
function classifyBlockStart(text, indent, defListEnabled) {
|
|
750
760
|
if (indent >= 4) return true;
|
|
751
761
|
if (LIST_MARKER_RE.test(text) || FOOTNOTE_DEF_RE.test(text)) return true;
|
|
@@ -753,71 +763,23 @@ function classifyBlockStart(text, indent, defListEnabled) {
|
|
|
753
763
|
if (indent === 0) return false;
|
|
754
764
|
return null;
|
|
755
765
|
}
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
textEnd = nl;
|
|
774
|
-
end = nl;
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
const confirmed = end < text.length && !(end === text.length - 1 && text.charCodeAt(end) === 13);
|
|
778
|
-
const lineText = text.slice(start, textEnd);
|
|
779
|
-
const ln = {
|
|
780
|
-
start,
|
|
781
|
-
end,
|
|
782
|
-
text: lineText,
|
|
783
|
-
blank: confirmed && isMdBlank(lineText),
|
|
784
|
-
indent: computeIndent(lineText)
|
|
785
|
-
};
|
|
786
|
-
if (!confirmed) {
|
|
787
|
-
tailLine = ln;
|
|
788
|
-
break;
|
|
789
|
-
}
|
|
790
|
-
processConfirmedLine(cp, ln, text);
|
|
791
|
-
cp.confirmedOffset = end + 1;
|
|
792
|
-
start = end + 1;
|
|
793
|
-
}
|
|
794
|
-
const earliestUnresolved = settleRefsAndEarliestUnresolved(cp);
|
|
795
|
-
const defListSettled = (c) => {
|
|
796
|
-
if (!options.defListEnabled || c.blankRun >= 2) return true;
|
|
797
|
-
if (c.defListSettled !== null) return c.defListSettled;
|
|
798
|
-
if (tailLine) return !canBecomeDdLine(tailLine.text, false);
|
|
799
|
-
return false;
|
|
800
|
-
};
|
|
801
|
-
const tailRetroactive = tailLine !== null && tailCarriesRetroactive(tailLine.text);
|
|
802
|
-
let boundary = 0;
|
|
803
|
-
for (let i = cp.candidates.length - 1; i >= 0 && !tailRetroactive; i--) {
|
|
804
|
-
const c = cp.candidates[i];
|
|
805
|
-
if (!c.htmlBalanced || c.hazard || c.seamRisk) continue;
|
|
806
|
-
if (c.offset > cp.phasePoisonedAt) continue;
|
|
807
|
-
if (c.offset > earliestUnresolved) continue;
|
|
808
|
-
if (!defListSettled(c)) continue;
|
|
809
|
-
boundary = c.offset;
|
|
810
|
-
break;
|
|
811
|
-
}
|
|
812
|
-
return { boundary, checkpoint: cp };
|
|
813
|
-
}
|
|
814
|
-
function pendingFenceCloser(checkpoint) {
|
|
815
|
-
const cp = checkpoint;
|
|
816
|
-
if (cp.phasePoisonedAt !== Infinity) return "";
|
|
817
|
-
if (cp.mdBlock.kind === "fence" && cp.mdBlock.indent === 0) return cp.mdBlock.char.repeat(cp.mdBlock.len);
|
|
818
|
-
if (cp.mdBlock.kind === "math" && cp.mdBlock.indent === 0) return "$".repeat(cp.mdBlock.len);
|
|
819
|
-
return "";
|
|
820
|
-
}
|
|
766
|
+
var SCANNER_NAME_LISTS = [
|
|
767
|
+
["type1", TYPE1_NAMES],
|
|
768
|
+
["rawText", RAW_TEXT_ELEMENTS],
|
|
769
|
+
["type6", TYPE6_NAMES],
|
|
770
|
+
["void", VOID_TAGS],
|
|
771
|
+
["documentStructure", DOCUMENT_STRUCTURE_NAMES],
|
|
772
|
+
// Added with F28, and it is the list that would have made F28 visible: the
|
|
773
|
+
// derived census alphabet partitions names by their membership across THIS
|
|
774
|
+
// table, so before it existed `frame` shared one 39-name class with `div`
|
|
775
|
+
// and could never be sampled apart from it.
|
|
776
|
+
["noElement", NO_ELEMENT_NAMES],
|
|
777
|
+
["tablePart", TABLE_PART_NAMES],
|
|
778
|
+
["scopeBarrier", SCOPE_BARRIER_NAMES],
|
|
779
|
+
["foreignRoot", new Set(FOREIGN_ROOT_NAMES)]
|
|
780
|
+
];
|
|
781
|
+
|
|
782
|
+
// src/components/incrementalParse/freezeLineTransition.ts
|
|
821
783
|
function floatingResidue(text, commentOpenAtStart) {
|
|
822
784
|
let out = "";
|
|
823
785
|
let open = commentOpenAtStart;
|
|
@@ -1461,24 +1423,66 @@ function processConfirmedLine(cp, ln, text) {
|
|
|
1461
1423
|
}
|
|
1462
1424
|
}
|
|
1463
1425
|
}
|
|
1464
|
-
var SCANNER_NAME_LISTS = [
|
|
1465
|
-
["type1", TYPE1_NAMES],
|
|
1466
|
-
["rawText", RAW_TEXT_ELEMENTS],
|
|
1467
|
-
["type6", TYPE6_NAMES],
|
|
1468
|
-
["void", VOID_TAGS],
|
|
1469
|
-
["documentStructure", DOCUMENT_STRUCTURE_NAMES],
|
|
1470
|
-
// Added with F28, and it is the list that would have made F28 visible: the
|
|
1471
|
-
// derived census alphabet partitions names by their membership across THIS
|
|
1472
|
-
// table, so before it existed `frame` shared one 39-name class with `div`
|
|
1473
|
-
// and could never be sampled apart from it.
|
|
1474
|
-
["noElement", NO_ELEMENT_NAMES],
|
|
1475
|
-
["tablePart", TABLE_PART_NAMES],
|
|
1476
|
-
["scopeBarrier", SCOPE_BARRIER_NAMES],
|
|
1477
|
-
["foreignRoot", new Set(FOREIGN_ROOT_NAMES)]
|
|
1478
|
-
];
|
|
1479
1426
|
|
|
1480
|
-
// src/components/incrementalParse/
|
|
1481
|
-
|
|
1427
|
+
// src/components/incrementalParse/computeFreezeBoundary.ts
|
|
1428
|
+
function computeFreezeBoundary(text, options, resume) {
|
|
1429
|
+
const mathFlow = options.mathFlow ?? true;
|
|
1430
|
+
const referenceTaint = options.referenceTaint ?? true;
|
|
1431
|
+
const prev = resume;
|
|
1432
|
+
const cp = prev && prev.defListEnabled === options.defListEnabled && prev.mathFlow === mathFlow && prev.referenceTaint === referenceTaint && prev.confirmedOffset <= text.length ? prev : freshCheckpoint(options.defListEnabled, mathFlow, referenceTaint);
|
|
1433
|
+
let start = cp.confirmedOffset;
|
|
1434
|
+
let tailLine = null;
|
|
1435
|
+
while (start < text.length) {
|
|
1436
|
+
let end = text.length;
|
|
1437
|
+
let textEnd = text.length;
|
|
1438
|
+
{
|
|
1439
|
+
const nl = text.indexOf("\n", start);
|
|
1440
|
+
const cr = text.indexOf("\r", start);
|
|
1441
|
+
if (cr !== -1 && (nl === -1 || cr < nl)) {
|
|
1442
|
+
textEnd = cr;
|
|
1443
|
+
end = text.charCodeAt(cr + 1) === 10 ? cr + 1 : cr;
|
|
1444
|
+
} else if (nl !== -1) {
|
|
1445
|
+
textEnd = nl;
|
|
1446
|
+
end = nl;
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
const confirmed = end < text.length && !(end === text.length - 1 && text.charCodeAt(end) === 13);
|
|
1450
|
+
const lineText = text.slice(start, textEnd);
|
|
1451
|
+
const ln = {
|
|
1452
|
+
start,
|
|
1453
|
+
end,
|
|
1454
|
+
text: lineText,
|
|
1455
|
+
blank: confirmed && isMdBlank(lineText),
|
|
1456
|
+
indent: computeIndent(lineText)
|
|
1457
|
+
};
|
|
1458
|
+
if (!confirmed) {
|
|
1459
|
+
tailLine = ln;
|
|
1460
|
+
break;
|
|
1461
|
+
}
|
|
1462
|
+
processConfirmedLine(cp, ln, text);
|
|
1463
|
+
cp.confirmedOffset = end + 1;
|
|
1464
|
+
start = end + 1;
|
|
1465
|
+
}
|
|
1466
|
+
const earliestUnresolved = settleRefsAndEarliestUnresolved(cp);
|
|
1467
|
+
const defListSettled = (c) => {
|
|
1468
|
+
if (!options.defListEnabled || c.blankRun >= 2) return true;
|
|
1469
|
+
if (c.defListSettled !== null) return c.defListSettled;
|
|
1470
|
+
if (tailLine) return !canBecomeDdLine(tailLine.text, false);
|
|
1471
|
+
return false;
|
|
1472
|
+
};
|
|
1473
|
+
const tailRetroactive = tailLine !== null && tailCarriesRetroactive(tailLine.text);
|
|
1474
|
+
let boundary = 0;
|
|
1475
|
+
for (let i = cp.candidates.length - 1; i >= 0 && !tailRetroactive; i--) {
|
|
1476
|
+
const c = cp.candidates[i];
|
|
1477
|
+
if (!c.htmlBalanced || c.hazard || c.seamRisk) continue;
|
|
1478
|
+
if (c.offset > cp.phasePoisonedAt) continue;
|
|
1479
|
+
if (c.offset > earliestUnresolved) continue;
|
|
1480
|
+
if (!defListSettled(c)) continue;
|
|
1481
|
+
boundary = c.offset;
|
|
1482
|
+
break;
|
|
1483
|
+
}
|
|
1484
|
+
return { boundary, checkpoint: cp };
|
|
1485
|
+
}
|
|
1482
1486
|
|
|
1483
1487
|
// src/components/hastPredicates.ts
|
|
1484
1488
|
function isFootnoteSection(node) {
|
|
@@ -1526,121 +1530,7 @@ function attributeHastChildren(mdast, hast, stopAt = Infinity) {
|
|
|
1526
1530
|
}
|
|
1527
1531
|
}
|
|
1528
1532
|
|
|
1529
|
-
// src/components/incrementalParse/
|
|
1530
|
-
function collectPrefixInjection(mdast, content, boundary, resume) {
|
|
1531
|
-
const resumeValid = resume != null && resume.boundary <= boundary;
|
|
1532
|
-
if (resumeValid && resume.uninjectable) return { events: resume.events, uninjectable: true };
|
|
1533
|
-
const resumeAt = resumeValid ? resume.boundary : 0;
|
|
1534
|
-
const events = resumeAt > 0 ? cloneEventsForAppend(resume.events) : [];
|
|
1535
|
-
let uninjectable = false;
|
|
1536
|
-
let cacheable = true;
|
|
1537
|
-
const pushRef = (token) => {
|
|
1538
|
-
const last = events[events.length - 1];
|
|
1539
|
-
if (last && last.kind === "refs") last.tokens.push(token);
|
|
1540
|
-
else events.push({ kind: "refs", tokens: [token] });
|
|
1541
|
-
};
|
|
1542
|
-
const visit7 = (node, nested) => {
|
|
1543
|
-
const type = node.type;
|
|
1544
|
-
if (type === "definition") {
|
|
1545
|
-
const start = node.position?.start?.offset;
|
|
1546
|
-
const end = node.position?.end?.offset;
|
|
1547
|
-
if (start !== void 0 && end !== void 0 && start < boundary) {
|
|
1548
|
-
const slice = content.slice(start, end);
|
|
1549
|
-
if (nested && slice.includes("\n")) uninjectable = true;
|
|
1550
|
-
else events.push({ kind: "def", source: slice });
|
|
1551
|
-
}
|
|
1552
|
-
return;
|
|
1553
|
-
}
|
|
1554
|
-
if (type === "footnoteDefinition") {
|
|
1555
|
-
const start = node.position?.start;
|
|
1556
|
-
const end = node.position?.end?.offset;
|
|
1557
|
-
if (start?.offset === void 0 || end === void 0 || start.offset >= boundary) return;
|
|
1558
|
-
if (nested) {
|
|
1559
|
-
uninjectable = true;
|
|
1560
|
-
return;
|
|
1561
|
-
}
|
|
1562
|
-
const lineStart = start.offset - (start.column - 1);
|
|
1563
|
-
events.push({
|
|
1564
|
-
kind: "footnoteDef",
|
|
1565
|
-
source: content.slice(lineStart, end),
|
|
1566
|
-
origStart: lineStart,
|
|
1567
|
-
origLine: start.line
|
|
1568
|
-
});
|
|
1569
|
-
return;
|
|
1570
|
-
}
|
|
1571
|
-
if (type === "footnoteReference") {
|
|
1572
|
-
const start = node.position?.start?.offset;
|
|
1573
|
-
const end = node.position?.end?.offset;
|
|
1574
|
-
if (start === void 0 || end === void 0) {
|
|
1575
|
-
uninjectable = true;
|
|
1576
|
-
return;
|
|
1577
|
-
}
|
|
1578
|
-
pushRef(content.slice(start, end));
|
|
1579
|
-
return;
|
|
1580
|
-
}
|
|
1581
|
-
const children = node.children;
|
|
1582
|
-
if (children) {
|
|
1583
|
-
for (const child of children) visit7(child, true);
|
|
1584
|
-
}
|
|
1585
|
-
};
|
|
1586
|
-
let lastStart = -1;
|
|
1587
|
-
for (const child of mdast.children) {
|
|
1588
|
-
const start = child.position?.start?.offset;
|
|
1589
|
-
if (start !== void 0) {
|
|
1590
|
-
if (start < lastStart) return { events: [], uninjectable: true, cacheable: false };
|
|
1591
|
-
lastStart = start;
|
|
1592
|
-
}
|
|
1593
|
-
if (start === void 0) {
|
|
1594
|
-
if (resumeAt > 0) return collectPrefixInjection(mdast, content, boundary, null);
|
|
1595
|
-
cacheable = false;
|
|
1596
|
-
visit7(child, false);
|
|
1597
|
-
continue;
|
|
1598
|
-
}
|
|
1599
|
-
if (start >= boundary || start < resumeAt) continue;
|
|
1600
|
-
visit7(child, false);
|
|
1601
|
-
}
|
|
1602
|
-
return { events, uninjectable, cacheable };
|
|
1603
|
-
}
|
|
1604
|
-
function cloneEventsForAppend(events) {
|
|
1605
|
-
const out = events.slice();
|
|
1606
|
-
const last = out[out.length - 1];
|
|
1607
|
-
if (last && last.kind === "refs") out[out.length - 1] = { kind: "refs", tokens: last.tokens.slice() };
|
|
1608
|
-
return out;
|
|
1609
|
-
}
|
|
1610
|
-
var TERMINATOR_LABEL = "__aimd_injection_terminator__";
|
|
1611
|
-
var INJECTION_TERMINATOR = `[${TERMINATOR_LABEL}]: __aimd_sentinel_link__`;
|
|
1612
|
-
function tailMentionsTerminator(tailSource) {
|
|
1613
|
-
return (0, import_micromark_util_normalize_identifier2.normalizeIdentifier)(tailSource).replace(/\[ /g, "[").includes(`[${(0, import_micromark_util_normalize_identifier2.normalizeIdentifier)(TERMINATOR_LABEL)}`);
|
|
1614
|
-
}
|
|
1615
|
-
function buildInjectionPrefix(events) {
|
|
1616
|
-
if (events.length === 0) return { text: "", segments: [] };
|
|
1617
|
-
let text = "";
|
|
1618
|
-
let line = 1;
|
|
1619
|
-
const segments = [];
|
|
1620
|
-
for (const event of events) {
|
|
1621
|
-
if (text.length > 0) {
|
|
1622
|
-
text += "\n\n";
|
|
1623
|
-
line += 2;
|
|
1624
|
-
}
|
|
1625
|
-
const injStart = text.length;
|
|
1626
|
-
const source = event.kind === "refs" ? event.tokens.join(" ") : event.source;
|
|
1627
|
-
if (event.kind === "footnoteDef") {
|
|
1628
|
-
segments.push({
|
|
1629
|
-
injStart,
|
|
1630
|
-
injEnd: injStart + source.length,
|
|
1631
|
-
offsetDelta: event.origStart - injStart,
|
|
1632
|
-
lineDelta: event.origLine - line
|
|
1633
|
-
});
|
|
1634
|
-
}
|
|
1635
|
-
text += source;
|
|
1636
|
-
line += countNewlines(source);
|
|
1637
|
-
}
|
|
1638
|
-
return { text: `${text}
|
|
1639
|
-
|
|
1640
|
-
${INJECTION_TERMINATOR}
|
|
1641
|
-
|
|
1642
|
-
`, segments };
|
|
1643
|
-
}
|
|
1533
|
+
// src/components/incrementalParse/spliceCoordinates.ts
|
|
1644
1534
|
function rebaseTree(node, offsetDelta, lineDelta) {
|
|
1645
1535
|
rebaseTreeDual(node, EMPTY_SEGMENTS, offsetDelta, lineDelta);
|
|
1646
1536
|
}
|
|
@@ -1669,6 +1559,23 @@ function rebaseDualWalk(node, segments, maxEnd, offsetDelta, lineDelta) {
|
|
|
1669
1559
|
for (const child of children) rebaseDualWalk(child, segments, maxEnd, offsetDelta, lineDelta);
|
|
1670
1560
|
}
|
|
1671
1561
|
}
|
|
1562
|
+
function rebasePoint(point, offsetDelta, lineDelta) {
|
|
1563
|
+
return {
|
|
1564
|
+
line: point.line + lineDelta,
|
|
1565
|
+
column: point.column,
|
|
1566
|
+
offset: point.offset !== void 0 ? point.offset + offsetDelta : void 0
|
|
1567
|
+
};
|
|
1568
|
+
}
|
|
1569
|
+
function countNewlines(text, end = text.length) {
|
|
1570
|
+
let count = 0;
|
|
1571
|
+
for (let i = text.indexOf("\n"); i !== -1 && i < end; i = text.indexOf("\n", i + 1)) count += 1;
|
|
1572
|
+
for (let i = text.indexOf("\r"); i !== -1 && i < end; i = text.indexOf("\r", i + 1)) {
|
|
1573
|
+
if (text.charCodeAt(i + 1) !== 10) count += 1;
|
|
1574
|
+
}
|
|
1575
|
+
return count;
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
// src/components/incrementalParse/spliceHtmlGuards.ts
|
|
1672
1579
|
var TABLE_PART_TAG_RE = /<(?:td|th|tr|tbody|thead|tfoot|caption|col|colgroup)\b/i;
|
|
1673
1580
|
var TABLE_TOKEN_RE = /<(\/?)(table|td|th|tr|tbody|thead|tfoot|caption|col|colgroup)\b/gi;
|
|
1674
1581
|
function hasStrayTablePart(values) {
|
|
@@ -1750,127 +1657,26 @@ function rawTextRegionCrossesOut(values) {
|
|
|
1750
1657
|
}
|
|
1751
1658
|
return false;
|
|
1752
1659
|
}
|
|
1753
|
-
function
|
|
1754
|
-
const
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
}
|
|
1765
|
-
const attrs = attributeHastChildren(prevMdast, prevHast, boundary);
|
|
1766
|
-
const cutRegion = [];
|
|
1767
|
-
for (let i = 0; i < prevHast.children.length; i++) {
|
|
1768
|
-
if (attrs[i] < boundary) {
|
|
1769
|
-
const node2 = prevHast.children[i];
|
|
1770
|
-
const end = node2.position?.end?.offset;
|
|
1771
|
-
if (end !== void 0 && end > boundary) return null;
|
|
1772
|
-
if (isTrailingLiteralText(node2)) {
|
|
1773
|
-
const prev = i > 0 ? prevHast.children[i - 1] : void 0;
|
|
1774
|
-
if (!prev || prev.type !== "element" || prev.position === void 0) return null;
|
|
1775
|
-
if (!ownsTrailingLiteral(prev, node2, prefixMdast))
|
|
1776
|
-
return null;
|
|
1777
|
-
}
|
|
1778
|
-
cutRegion.push(node2);
|
|
1779
|
-
continue;
|
|
1780
|
-
}
|
|
1781
|
-
const node = prevHast.children[i];
|
|
1782
|
-
if (i > 0 && attrs[i - 1] < boundary && prevHast.children[i - 1].type === "element" && isTrailingLiteralText(node) && // …and only when that element really IS an html block's output: a
|
|
1783
|
-
// raw literal can only trail an `html` mdast node. A position-less
|
|
1784
|
-
// text after a `<p>` is the NEXT block's remnant — a stray end tag
|
|
1785
|
-
// (`</t>\na`) parse5 dropped, whose text merged with the wrap
|
|
1786
|
-
// separator — owned by the tail, which re-parses it; freezing it
|
|
1787
|
-
// here duplicated it (v2.4.0 review P3). Falls through to the
|
|
1788
|
-
// remnant look-ahead below, which bails to a full parse. And the
|
|
1789
|
-
// literal must really be THAT block's trailing text: the block's raw
|
|
1790
|
-
// source ends with it. A dropped-tag block right after a frozen html
|
|
1791
|
-
// element (`</details>\n\n</t>\ntext`) puts its remnant in the same
|
|
1792
|
-
// position, and freezing it duplicated it (release soak of the fix).
|
|
1793
|
-
ownsTrailingLiteral(prevHast.children[i - 1], node, prefixMdast)) {
|
|
1794
|
-
cutRegion.push(node);
|
|
1795
|
-
break;
|
|
1796
|
-
}
|
|
1797
|
-
for (let j = i; j < prevHast.children.length; j++) {
|
|
1798
|
-
const look = prevHast.children[j];
|
|
1799
|
-
if (look.type === "element" || look.position !== void 0) break;
|
|
1800
|
-
if (isTrailingLiteralText(look)) return null;
|
|
1801
|
-
}
|
|
1802
|
-
break;
|
|
1803
|
-
}
|
|
1804
|
-
const tailMdastChildren = tailMdast.children.filter((child) => {
|
|
1805
|
-
const start = child.position?.start?.offset;
|
|
1806
|
-
return !(start !== void 0 && start < injectedLen);
|
|
1807
|
-
});
|
|
1808
|
-
const tailWrapVisible = tailMdastChildren.some((child) => !isWrapInvisible(child));
|
|
1809
|
-
const prefixHtmlValues = prefixMdast.flatMap((c) => c.type === "html" ? [c.value] : []);
|
|
1810
|
-
if (hasStrayTablePart(prefixHtmlValues)) return null;
|
|
1811
|
-
if (rawTextRegionCrossesOut(prefixHtmlValues)) return null;
|
|
1812
|
-
const leadingHtml = [];
|
|
1813
|
-
for (const child of tailMdastChildren) {
|
|
1814
|
-
if (isWrapInvisible(child)) continue;
|
|
1815
|
-
if (child.type !== "html") break;
|
|
1816
|
-
if (STRAY_SYNTHESIZED_END_TAG_RE.test(child.value) || TABLE_PART_TAG_RE.test(child.value)) return null;
|
|
1817
|
-
leadingHtml.push(child.value);
|
|
1660
|
+
function isSanitizeStrippedConstruct(value) {
|
|
1661
|
+
const v = value.trim();
|
|
1662
|
+
return v.startsWith("<!--") && v.endsWith("-->") || v.startsWith("<?") && v.endsWith("?>") || v.startsWith("<![CDATA[") && v.endsWith("]]>") || /^<![A-Za-z]/.test(v) && !/^<!doctype/i.test(v) && v.endsWith(">");
|
|
1663
|
+
}
|
|
1664
|
+
function isExactSanitizeStrippedConstruct(value) {
|
|
1665
|
+
if (value.startsWith("<!--")) {
|
|
1666
|
+
if (value.length < 7 || !value.endsWith("-->")) return false;
|
|
1667
|
+
const close = value.indexOf("-->", 4);
|
|
1668
|
+
const bangClose = value.indexOf("--!>", 4);
|
|
1669
|
+
if (close !== value.length - 3) return false;
|
|
1670
|
+
return bangClose === -1 || bangClose > close;
|
|
1818
1671
|
}
|
|
1819
|
-
if (
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
const hastChildren = aligned.children;
|
|
1823
|
-
const interiorFinalLiteral = aligned.interiorFinalLiteral;
|
|
1824
|
-
const stripResult = stripInjectedHast(tailMdast, tailHast, injectedLen, tailWrapVisible);
|
|
1825
|
-
if (stripResult === null) return null;
|
|
1826
|
-
const strippedTailHast = stripResult.rest;
|
|
1827
|
-
for (const child of tailMdastChildren) rebaseTree(child, offsetDelta, lineDelta);
|
|
1828
|
-
for (const child of strippedTailHast) rebaseTreeDual(child, injectedSegments, offsetDelta, lineDelta);
|
|
1829
|
-
const mdastChildren = prefixMdast.concat(tailMdastChildren);
|
|
1830
|
-
const seamMergeVerdict = stripResult.remnantMerged ?? tailLeadingTextIsHoist(tailMdastChildren, strippedTailHast);
|
|
1831
|
-
if (seamMergeVerdict === null) return null;
|
|
1832
|
-
const seamMergeAllowed = seamMergeVerdict;
|
|
1833
|
-
let firstTailChild = true;
|
|
1834
|
-
for (const child of strippedTailHast) {
|
|
1835
|
-
const tailEnd = hastChildren[hastChildren.length - 1];
|
|
1836
|
-
if (firstTailChild && child.type === "text" && child.position !== void 0) {
|
|
1837
|
-
return null;
|
|
1838
|
-
}
|
|
1839
|
-
if (firstTailChild && tailEnd && tailEnd.type === "text" && child.type === "text" && child.position === void 0) {
|
|
1840
|
-
if (interiorFinalLiteral && tailEnd.value.trim() !== "") {
|
|
1841
|
-
if (seamMergeAllowed) return null;
|
|
1842
|
-
firstTailChild = false;
|
|
1843
|
-
hastChildren.push(child);
|
|
1844
|
-
continue;
|
|
1845
|
-
}
|
|
1846
|
-
const literalSeam = tailEnd.value.trim() !== "" && !tailWrapVisible;
|
|
1847
|
-
if (seamMergeAllowed || literalSeam) {
|
|
1848
|
-
hastChildren[hastChildren.length - 1] = { type: "text", value: tailEnd.value + child.value };
|
|
1849
|
-
firstTailChild = false;
|
|
1850
|
-
continue;
|
|
1851
|
-
}
|
|
1852
|
-
}
|
|
1853
|
-
firstTailChild = false;
|
|
1854
|
-
hastChildren.push(child);
|
|
1672
|
+
if (/^<!doctype/i.test(value)) return false;
|
|
1673
|
+
if (value.startsWith("<?") || /^<!(?:[A-Za-z]|\[CDATA\[)/.test(value)) {
|
|
1674
|
+
return value.indexOf(">") === value.length - 1;
|
|
1855
1675
|
}
|
|
1856
|
-
|
|
1857
|
-
const docStart = { line: 1, column: 1, offset: 0 };
|
|
1858
|
-
const mdastRootPosition = tailMdast.position ? { start: docStart, end: rebasePoint(tailMdast.position.end, offsetDelta, lineDelta) } : prevMdast.position;
|
|
1859
|
-
const hastRootPosition = mdastRootPosition;
|
|
1860
|
-
const mdast = { type: "root", children: mdastChildren };
|
|
1861
|
-
if (mdastRootPosition) mdast.position = mdastRootPosition;
|
|
1862
|
-
const hast = { type: "root", children: hastChildren };
|
|
1863
|
-
if (hastRootPosition) hast.position = hastRootPosition;
|
|
1864
|
-
if (prevHast.data !== void 0) hast.data = prevHast.data;
|
|
1865
|
-
return { mdast, hast };
|
|
1866
|
-
}
|
|
1867
|
-
function rebasePoint(point, offsetDelta, lineDelta) {
|
|
1868
|
-
return {
|
|
1869
|
-
line: point.line + lineDelta,
|
|
1870
|
-
column: point.column,
|
|
1871
|
-
offset: point.offset !== void 0 ? point.offset + offsetDelta : void 0
|
|
1872
|
-
};
|
|
1676
|
+
return false;
|
|
1873
1677
|
}
|
|
1678
|
+
|
|
1679
|
+
// src/components/incrementalParse/prefixAlignment.ts
|
|
1874
1680
|
function isWrapInvisible(node) {
|
|
1875
1681
|
return node.type === "definition" || node.type === "footnoteDefinition";
|
|
1876
1682
|
}
|
|
@@ -2012,96 +1818,303 @@ function stripInjectedHast(tailMdast, tailHast, injectedLen, tailWrapVisible) {
|
|
|
2012
1818
|
idx += 1;
|
|
2013
1819
|
continue;
|
|
2014
1820
|
}
|
|
2015
|
-
const start = node.position?.start?.offset;
|
|
2016
|
-
if (start === void 0 || start >= injectedLen) return null;
|
|
2017
|
-
consumed += 1;
|
|
2018
|
-
idx += 1;
|
|
1821
|
+
const start = node.position?.start?.offset;
|
|
1822
|
+
if (start === void 0 || start >= injectedLen) return null;
|
|
1823
|
+
consumed += 1;
|
|
1824
|
+
idx += 1;
|
|
1825
|
+
}
|
|
1826
|
+
if (consumed < injectedVisibleCount) return null;
|
|
1827
|
+
let remnant = "";
|
|
1828
|
+
let remnantMerged = null;
|
|
1829
|
+
if (tailWrapVisible) {
|
|
1830
|
+
const gap = children[idx];
|
|
1831
|
+
if (!gap || !isSeparatorText(gap)) return null;
|
|
1832
|
+
remnant = gap.value.slice(1);
|
|
1833
|
+
remnantMerged = remnant !== "";
|
|
1834
|
+
idx += 1;
|
|
1835
|
+
}
|
|
1836
|
+
const rest = children.slice(idx);
|
|
1837
|
+
if (remnant !== "") rest.unshift({ type: "text", value: remnant });
|
|
1838
|
+
return { rest, remnantMerged };
|
|
1839
|
+
}
|
|
1840
|
+
function tailLeadingTextIsHoist(tailMdastChildren, tailHastChildren) {
|
|
1841
|
+
const firstText = tailHastChildren[0];
|
|
1842
|
+
const firstVisible = tailMdastChildren.find((c) => !isWrapInvisible(c));
|
|
1843
|
+
if (firstVisible?.type === "html" && STRAY_SYNTHESIZED_END_TAG_RE.test(firstVisible.value)) return null;
|
|
1844
|
+
if (!firstText) return false;
|
|
1845
|
+
if (!isSeparatorText(firstText)) {
|
|
1846
|
+
if (firstText.type === "text" && firstText.position === void 0 && firstVisible?.type === "html") {
|
|
1847
|
+
if (/^\s*<\/[A-Za-z][A-Za-z0-9-]*\s*>/.test(firstVisible.value)) return true;
|
|
1848
|
+
if (isSanitizeStrippedConstruct(firstVisible.value)) return false;
|
|
1849
|
+
return null;
|
|
1850
|
+
}
|
|
1851
|
+
return false;
|
|
1852
|
+
}
|
|
1853
|
+
if (!firstVisible) return false;
|
|
1854
|
+
const firstContent = tailHastChildren.find((c) => !isSeparatorText(c));
|
|
1855
|
+
if (firstContent) {
|
|
1856
|
+
const start = firstContent.position?.start?.offset;
|
|
1857
|
+
const vStart = firstVisible.position?.start?.offset;
|
|
1858
|
+
const vEnd = firstVisible.position?.end?.offset;
|
|
1859
|
+
if (start !== void 0 && vStart !== void 0 && vEnd !== void 0) {
|
|
1860
|
+
if (start >= vStart && start < vEnd) return true;
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
if (firstVisible.type === "math") return false;
|
|
1864
|
+
if (firstVisible.type === "html" && isSanitizeStrippedConstruct(firstVisible.value)) return false;
|
|
1865
|
+
return null;
|
|
1866
|
+
}
|
|
1867
|
+
function isSeparatorText(node) {
|
|
1868
|
+
return node.type === "text" && node.position === void 0 && node.value.trim() === "";
|
|
1869
|
+
}
|
|
1870
|
+
function ownsTrailingLiteral(el, literal, prefixMdast) {
|
|
1871
|
+
const start = el.position?.start?.offset;
|
|
1872
|
+
if (start === void 0) return false;
|
|
1873
|
+
const owner = prefixMdast.find((c) => c.type === "html" && c.position?.start?.offset === start);
|
|
1874
|
+
if (!owner || owner.type !== "html") return false;
|
|
1875
|
+
const text = literal.value.trim();
|
|
1876
|
+
return text !== "" && owner.value.trimEnd().endsWith(text);
|
|
1877
|
+
}
|
|
1878
|
+
function isTrailingLiteralText(node) {
|
|
1879
|
+
return node.type === "text" && node.position === void 0 && node.value.trim() !== "";
|
|
1880
|
+
}
|
|
1881
|
+
function countTrailingNewlines(value) {
|
|
1882
|
+
let n = 0;
|
|
1883
|
+
for (let i = value.length - 1; i >= 0 && value[i] === "\n"; i--) n += 1;
|
|
1884
|
+
return n;
|
|
1885
|
+
}
|
|
1886
|
+
|
|
1887
|
+
// src/components/incrementalParse/prefixInjection.ts
|
|
1888
|
+
var import_micromark_util_normalize_identifier2 = require("micromark-util-normalize-identifier");
|
|
1889
|
+
function collectPrefixInjection(mdast, content, boundary, resume) {
|
|
1890
|
+
const resumeValid = resume != null && resume.boundary <= boundary;
|
|
1891
|
+
if (resumeValid && resume.uninjectable) return { events: resume.events, uninjectable: true };
|
|
1892
|
+
const resumeAt = resumeValid ? resume.boundary : 0;
|
|
1893
|
+
const events = resumeAt > 0 ? cloneEventsForAppend(resume.events) : [];
|
|
1894
|
+
let uninjectable = false;
|
|
1895
|
+
let cacheable = true;
|
|
1896
|
+
const pushRef = (token) => {
|
|
1897
|
+
const last = events[events.length - 1];
|
|
1898
|
+
if (last && last.kind === "refs") last.tokens.push(token);
|
|
1899
|
+
else events.push({ kind: "refs", tokens: [token] });
|
|
1900
|
+
};
|
|
1901
|
+
const visit7 = (node, nested) => {
|
|
1902
|
+
const type = node.type;
|
|
1903
|
+
if (type === "definition") {
|
|
1904
|
+
const start = node.position?.start?.offset;
|
|
1905
|
+
const end = node.position?.end?.offset;
|
|
1906
|
+
if (start !== void 0 && end !== void 0 && start < boundary) {
|
|
1907
|
+
const slice = content.slice(start, end);
|
|
1908
|
+
if (nested && slice.includes("\n")) uninjectable = true;
|
|
1909
|
+
else events.push({ kind: "def", source: slice });
|
|
1910
|
+
}
|
|
1911
|
+
return;
|
|
1912
|
+
}
|
|
1913
|
+
if (type === "footnoteDefinition") {
|
|
1914
|
+
const start = node.position?.start;
|
|
1915
|
+
const end = node.position?.end?.offset;
|
|
1916
|
+
if (start?.offset === void 0 || end === void 0 || start.offset >= boundary) return;
|
|
1917
|
+
if (nested) {
|
|
1918
|
+
uninjectable = true;
|
|
1919
|
+
return;
|
|
1920
|
+
}
|
|
1921
|
+
const lineStart = start.offset - (start.column - 1);
|
|
1922
|
+
events.push({
|
|
1923
|
+
kind: "footnoteDef",
|
|
1924
|
+
source: content.slice(lineStart, end),
|
|
1925
|
+
origStart: lineStart,
|
|
1926
|
+
origLine: start.line
|
|
1927
|
+
});
|
|
1928
|
+
return;
|
|
1929
|
+
}
|
|
1930
|
+
if (type === "footnoteReference") {
|
|
1931
|
+
const start = node.position?.start?.offset;
|
|
1932
|
+
const end = node.position?.end?.offset;
|
|
1933
|
+
if (start === void 0 || end === void 0) {
|
|
1934
|
+
uninjectable = true;
|
|
1935
|
+
return;
|
|
1936
|
+
}
|
|
1937
|
+
pushRef(content.slice(start, end));
|
|
1938
|
+
return;
|
|
1939
|
+
}
|
|
1940
|
+
const children = node.children;
|
|
1941
|
+
if (children) {
|
|
1942
|
+
for (const child of children) visit7(child, true);
|
|
1943
|
+
}
|
|
1944
|
+
};
|
|
1945
|
+
let lastStart = -1;
|
|
1946
|
+
for (const child of mdast.children) {
|
|
1947
|
+
const start = child.position?.start?.offset;
|
|
1948
|
+
if (start !== void 0) {
|
|
1949
|
+
if (start < lastStart) return { events: [], uninjectable: true, cacheable: false };
|
|
1950
|
+
lastStart = start;
|
|
1951
|
+
}
|
|
1952
|
+
if (start === void 0) {
|
|
1953
|
+
if (resumeAt > 0) return collectPrefixInjection(mdast, content, boundary, null);
|
|
1954
|
+
cacheable = false;
|
|
1955
|
+
visit7(child, false);
|
|
1956
|
+
continue;
|
|
1957
|
+
}
|
|
1958
|
+
if (start >= boundary || start < resumeAt) continue;
|
|
1959
|
+
visit7(child, false);
|
|
1960
|
+
}
|
|
1961
|
+
return { events, uninjectable, cacheable };
|
|
1962
|
+
}
|
|
1963
|
+
function cloneEventsForAppend(events) {
|
|
1964
|
+
const out = events.slice();
|
|
1965
|
+
const last = out[out.length - 1];
|
|
1966
|
+
if (last && last.kind === "refs") out[out.length - 1] = { kind: "refs", tokens: last.tokens.slice() };
|
|
1967
|
+
return out;
|
|
1968
|
+
}
|
|
1969
|
+
var TERMINATOR_LABEL = "__aimd_injection_terminator__";
|
|
1970
|
+
var INJECTION_TERMINATOR = `[${TERMINATOR_LABEL}]: __aimd_sentinel_link__`;
|
|
1971
|
+
function tailMentionsTerminator(tailSource) {
|
|
1972
|
+
return (0, import_micromark_util_normalize_identifier2.normalizeIdentifier)(tailSource).replace(/\[ /g, "[").includes(`[${(0, import_micromark_util_normalize_identifier2.normalizeIdentifier)(TERMINATOR_LABEL)}`);
|
|
1973
|
+
}
|
|
1974
|
+
function buildInjectionPrefix(events) {
|
|
1975
|
+
if (events.length === 0) return { text: "", segments: [] };
|
|
1976
|
+
let text = "";
|
|
1977
|
+
let line = 1;
|
|
1978
|
+
const segments = [];
|
|
1979
|
+
for (const event of events) {
|
|
1980
|
+
if (text.length > 0) {
|
|
1981
|
+
text += "\n\n";
|
|
1982
|
+
line += 2;
|
|
1983
|
+
}
|
|
1984
|
+
const injStart = text.length;
|
|
1985
|
+
const source = event.kind === "refs" ? event.tokens.join(" ") : event.source;
|
|
1986
|
+
if (event.kind === "footnoteDef") {
|
|
1987
|
+
segments.push({
|
|
1988
|
+
injStart,
|
|
1989
|
+
injEnd: injStart + source.length,
|
|
1990
|
+
offsetDelta: event.origStart - injStart,
|
|
1991
|
+
lineDelta: event.origLine - line
|
|
1992
|
+
});
|
|
1993
|
+
}
|
|
1994
|
+
text += source;
|
|
1995
|
+
line += countNewlines(source);
|
|
1996
|
+
}
|
|
1997
|
+
return { text: `${text}
|
|
1998
|
+
|
|
1999
|
+
${INJECTION_TERMINATOR}
|
|
2000
|
+
|
|
2001
|
+
`, segments };
|
|
2002
|
+
}
|
|
2003
|
+
|
|
2004
|
+
// src/components/incrementalParse/spliceParse.ts
|
|
2005
|
+
function spliceTrees(input) {
|
|
2006
|
+
const { prevMdast, prevHast, tailMdast, tailHast, content, boundary, injectionPrefix, injectedSegments } = input;
|
|
2007
|
+
const injectedLen = injectionPrefix.length;
|
|
2008
|
+
const injectedLines = countNewlines(injectionPrefix);
|
|
2009
|
+
const prefixLines = countNewlines(content, boundary);
|
|
2010
|
+
const offsetDelta = boundary - injectedLen;
|
|
2011
|
+
const lineDelta = prefixLines - injectedLines;
|
|
2012
|
+
const prefixMdast = [];
|
|
2013
|
+
for (const child of prevMdast.children) {
|
|
2014
|
+
const start = child.position?.start?.offset;
|
|
2015
|
+
if (start !== void 0 && start < boundary) prefixMdast.push(child);
|
|
2016
|
+
}
|
|
2017
|
+
const attrs = attributeHastChildren(prevMdast, prevHast, boundary);
|
|
2018
|
+
const cutRegion = [];
|
|
2019
|
+
for (let i = 0; i < prevHast.children.length; i++) {
|
|
2020
|
+
if (attrs[i] < boundary) {
|
|
2021
|
+
const node2 = prevHast.children[i];
|
|
2022
|
+
const end = node2.position?.end?.offset;
|
|
2023
|
+
if (end !== void 0 && end > boundary) return null;
|
|
2024
|
+
if (isTrailingLiteralText(node2)) {
|
|
2025
|
+
const prev = i > 0 ? prevHast.children[i - 1] : void 0;
|
|
2026
|
+
if (!prev || prev.type !== "element" || prev.position === void 0) return null;
|
|
2027
|
+
if (!ownsTrailingLiteral(prev, node2, prefixMdast))
|
|
2028
|
+
return null;
|
|
2029
|
+
}
|
|
2030
|
+
cutRegion.push(node2);
|
|
2031
|
+
continue;
|
|
2032
|
+
}
|
|
2033
|
+
const node = prevHast.children[i];
|
|
2034
|
+
if (i > 0 && attrs[i - 1] < boundary && prevHast.children[i - 1].type === "element" && isTrailingLiteralText(node) && // …and only when that element really IS an html block's output: a
|
|
2035
|
+
// raw literal can only trail an `html` mdast node. A position-less
|
|
2036
|
+
// text after a `<p>` is the NEXT block's remnant — a stray end tag
|
|
2037
|
+
// (`</t>\na`) parse5 dropped, whose text merged with the wrap
|
|
2038
|
+
// separator — owned by the tail, which re-parses it; freezing it
|
|
2039
|
+
// here duplicated it (v2.4.0 review P3). Falls through to the
|
|
2040
|
+
// remnant look-ahead below, which bails to a full parse. And the
|
|
2041
|
+
// literal must really be THAT block's trailing text: the block's raw
|
|
2042
|
+
// source ends with it. A dropped-tag block right after a frozen html
|
|
2043
|
+
// element (`</details>\n\n</t>\ntext`) puts its remnant in the same
|
|
2044
|
+
// position, and freezing it duplicated it (release soak of the fix).
|
|
2045
|
+
ownsTrailingLiteral(prevHast.children[i - 1], node, prefixMdast)) {
|
|
2046
|
+
cutRegion.push(node);
|
|
2047
|
+
break;
|
|
2048
|
+
}
|
|
2049
|
+
for (let j = i; j < prevHast.children.length; j++) {
|
|
2050
|
+
const look = prevHast.children[j];
|
|
2051
|
+
if (look.type === "element" || look.position !== void 0) break;
|
|
2052
|
+
if (isTrailingLiteralText(look)) return null;
|
|
2053
|
+
}
|
|
2054
|
+
break;
|
|
2019
2055
|
}
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2056
|
+
const tailMdastChildren = tailMdast.children.filter((child) => {
|
|
2057
|
+
const start = child.position?.start?.offset;
|
|
2058
|
+
return !(start !== void 0 && start < injectedLen);
|
|
2059
|
+
});
|
|
2060
|
+
const tailWrapVisible = tailMdastChildren.some((child) => !isWrapInvisible(child));
|
|
2061
|
+
const prefixHtmlValues = prefixMdast.flatMap((c) => c.type === "html" ? [c.value] : []);
|
|
2062
|
+
if (hasStrayTablePart(prefixHtmlValues)) return null;
|
|
2063
|
+
if (rawTextRegionCrossesOut(prefixHtmlValues)) return null;
|
|
2064
|
+
const leadingHtml = [];
|
|
2065
|
+
for (const child of tailMdastChildren) {
|
|
2066
|
+
if (isWrapInvisible(child)) continue;
|
|
2067
|
+
if (child.type !== "html") break;
|
|
2068
|
+
if (STRAY_SYNTHESIZED_END_TAG_RE.test(child.value) || TABLE_PART_TAG_RE.test(child.value)) return null;
|
|
2069
|
+
leadingHtml.push(child.value);
|
|
2029
2070
|
}
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
const
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2071
|
+
if (headRoutedCaptureUnclosed(leadingHtml)) return null;
|
|
2072
|
+
const aligned = alignPrefixCut(prefixMdast, cutRegion, tailWrapVisible);
|
|
2073
|
+
if (aligned === null) return null;
|
|
2074
|
+
const hastChildren = aligned.children;
|
|
2075
|
+
const interiorFinalLiteral = aligned.interiorFinalLiteral;
|
|
2076
|
+
const stripResult = stripInjectedHast(tailMdast, tailHast, injectedLen, tailWrapVisible);
|
|
2077
|
+
if (stripResult === null) return null;
|
|
2078
|
+
const strippedTailHast = stripResult.rest;
|
|
2079
|
+
for (const child of tailMdastChildren) rebaseTree(child, offsetDelta, lineDelta);
|
|
2080
|
+
for (const child of strippedTailHast) rebaseTreeDual(child, injectedSegments, offsetDelta, lineDelta);
|
|
2081
|
+
const mdastChildren = prefixMdast.concat(tailMdastChildren);
|
|
2082
|
+
const seamMergeVerdict = stripResult.remnantMerged ?? tailLeadingTextIsHoist(tailMdastChildren, strippedTailHast);
|
|
2083
|
+
if (seamMergeVerdict === null) return null;
|
|
2084
|
+
const seamMergeAllowed = seamMergeVerdict;
|
|
2085
|
+
let firstTailChild = true;
|
|
2086
|
+
for (const child of strippedTailHast) {
|
|
2087
|
+
const tailEnd = hastChildren[hastChildren.length - 1];
|
|
2088
|
+
if (firstTailChild && child.type === "text" && child.position !== void 0) {
|
|
2043
2089
|
return null;
|
|
2044
2090
|
}
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2091
|
+
if (firstTailChild && tailEnd && tailEnd.type === "text" && child.type === "text" && child.position === void 0) {
|
|
2092
|
+
if (interiorFinalLiteral && tailEnd.value.trim() !== "") {
|
|
2093
|
+
if (seamMergeAllowed) return null;
|
|
2094
|
+
firstTailChild = false;
|
|
2095
|
+
hastChildren.push(child);
|
|
2096
|
+
continue;
|
|
2097
|
+
}
|
|
2098
|
+
const literalSeam = tailEnd.value.trim() !== "" && !tailWrapVisible;
|
|
2099
|
+
if (seamMergeAllowed || literalSeam) {
|
|
2100
|
+
hastChildren[hastChildren.length - 1] = { type: "text", value: tailEnd.value + child.value };
|
|
2101
|
+
firstTailChild = false;
|
|
2102
|
+
continue;
|
|
2103
|
+
}
|
|
2055
2104
|
}
|
|
2105
|
+
firstTailChild = false;
|
|
2106
|
+
hastChildren.push(child);
|
|
2056
2107
|
}
|
|
2057
|
-
if (
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
if (value.length < 7 || !value.endsWith("-->")) return false;
|
|
2068
|
-
const close = value.indexOf("-->", 4);
|
|
2069
|
-
const bangClose = value.indexOf("--!>", 4);
|
|
2070
|
-
if (close !== value.length - 3) return false;
|
|
2071
|
-
return bangClose === -1 || bangClose > close;
|
|
2072
|
-
}
|
|
2073
|
-
if (/^<!doctype/i.test(value)) return false;
|
|
2074
|
-
if (value.startsWith("<?") || /^<!(?:[A-Za-z]|\[CDATA\[)/.test(value)) {
|
|
2075
|
-
return value.indexOf(">") === value.length - 1;
|
|
2076
|
-
}
|
|
2077
|
-
return false;
|
|
2078
|
-
}
|
|
2079
|
-
function isSeparatorText(node) {
|
|
2080
|
-
return node.type === "text" && node.position === void 0 && node.value.trim() === "";
|
|
2081
|
-
}
|
|
2082
|
-
function ownsTrailingLiteral(el, literal, prefixMdast) {
|
|
2083
|
-
const start = el.position?.start?.offset;
|
|
2084
|
-
if (start === void 0) return false;
|
|
2085
|
-
const owner = prefixMdast.find((c) => c.type === "html" && c.position?.start?.offset === start);
|
|
2086
|
-
if (!owner || owner.type !== "html") return false;
|
|
2087
|
-
const text = literal.value.trim();
|
|
2088
|
-
return text !== "" && owner.value.trimEnd().endsWith(text);
|
|
2089
|
-
}
|
|
2090
|
-
function isTrailingLiteralText(node) {
|
|
2091
|
-
return node.type === "text" && node.position === void 0 && node.value.trim() !== "";
|
|
2092
|
-
}
|
|
2093
|
-
function countTrailingNewlines(value) {
|
|
2094
|
-
let n = 0;
|
|
2095
|
-
for (let i = value.length - 1; i >= 0 && value[i] === "\n"; i--) n += 1;
|
|
2096
|
-
return n;
|
|
2097
|
-
}
|
|
2098
|
-
function countNewlines(text, end = text.length) {
|
|
2099
|
-
let count = 0;
|
|
2100
|
-
for (let i = text.indexOf("\n"); i !== -1 && i < end; i = text.indexOf("\n", i + 1)) count += 1;
|
|
2101
|
-
for (let i = text.indexOf("\r"); i !== -1 && i < end; i = text.indexOf("\r", i + 1)) {
|
|
2102
|
-
if (text.charCodeAt(i + 1) !== 10) count += 1;
|
|
2103
|
-
}
|
|
2104
|
-
return count;
|
|
2108
|
+
if (!hastChildren.some((child) => child.position !== void 0)) return null;
|
|
2109
|
+
const docStart = { line: 1, column: 1, offset: 0 };
|
|
2110
|
+
const mdastRootPosition = tailMdast.position ? { start: docStart, end: rebasePoint(tailMdast.position.end, offsetDelta, lineDelta) } : prevMdast.position;
|
|
2111
|
+
const hastRootPosition = mdastRootPosition;
|
|
2112
|
+
const mdast = { type: "root", children: mdastChildren };
|
|
2113
|
+
if (mdastRootPosition) mdast.position = mdastRootPosition;
|
|
2114
|
+
const hast = { type: "root", children: hastChildren };
|
|
2115
|
+
if (hastRootPosition) hast.position = hastRootPosition;
|
|
2116
|
+
if (prevHast.data !== void 0) hast.data = prevHast.data;
|
|
2117
|
+
return { mdast, hast };
|
|
2105
2118
|
}
|
|
2106
2119
|
|
|
2107
2120
|
// src/components/incrementalParse/advanceIncrementalParse.ts
|
|
@@ -2223,6 +2236,38 @@ function normalizeForMatch(s) {
|
|
|
2223
2236
|
return (0, import_micromark_util_normalize_identifier3.normalizeIdentifier)(s);
|
|
2224
2237
|
}
|
|
2225
2238
|
|
|
2239
|
+
// src/components/blankLineScanner.ts
|
|
2240
|
+
function createBlankLineScanner() {
|
|
2241
|
+
let end = 0;
|
|
2242
|
+
let newline = false;
|
|
2243
|
+
let cr = false;
|
|
2244
|
+
return (source, from = 0) => {
|
|
2245
|
+
if (from === 0) {
|
|
2246
|
+
end = 0;
|
|
2247
|
+
newline = false;
|
|
2248
|
+
cr = false;
|
|
2249
|
+
}
|
|
2250
|
+
for (let i = from; i < source.length; i++) {
|
|
2251
|
+
const c = source[i];
|
|
2252
|
+
if (c === "\n") {
|
|
2253
|
+
if (newline) {
|
|
2254
|
+
end = i + 1;
|
|
2255
|
+
newline = false;
|
|
2256
|
+
} else newline = true;
|
|
2257
|
+
cr = false;
|
|
2258
|
+
} else if (newline) {
|
|
2259
|
+
if ((c === " " || c === " ") && !cr) continue;
|
|
2260
|
+
if (c === "\r" && !cr) cr = true;
|
|
2261
|
+
else {
|
|
2262
|
+
newline = false;
|
|
2263
|
+
cr = false;
|
|
2264
|
+
}
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
return end;
|
|
2268
|
+
};
|
|
2269
|
+
}
|
|
2270
|
+
|
|
2226
2271
|
// src/components/collectDefLabels.ts
|
|
2227
2272
|
var SCANNER_BOUNDARY_PROFILE = { defListEnabled: false, mathFlow: false, referenceTaint: false };
|
|
2228
2273
|
function buildProcessor() {
|
|
@@ -2254,19 +2299,12 @@ var setsEqual = (a, b) => {
|
|
|
2254
2299
|
for (const v of a) if (!b.has(v)) return false;
|
|
2255
2300
|
return true;
|
|
2256
2301
|
};
|
|
2257
|
-
var BLANK_LINE_RE = /\r?\n[ \t]*\r?\n/g;
|
|
2258
|
-
function lastRegionStart(source) {
|
|
2259
|
-
BLANK_LINE_RE.lastIndex = 0;
|
|
2260
|
-
let start = 0;
|
|
2261
|
-
for (let m = BLANK_LINE_RE.exec(source); m !== null; m = BLANK_LINE_RE.exec(source)) {
|
|
2262
|
-
start = m.index + m[0].length;
|
|
2263
|
-
}
|
|
2264
|
-
return start;
|
|
2265
|
-
}
|
|
2266
2302
|
var DEF_LINE_START_RE = /^[ \t>*+\d.)-]*\[(?:[^\]\\]|\\[\s\S])*\]:/m;
|
|
2267
2303
|
function createDefLabelScanner(parse = collectDefLabels) {
|
|
2268
2304
|
let prevSource = null;
|
|
2269
2305
|
let prevLabels = null;
|
|
2306
|
+
const scanBlankLines = createBlankLineScanner();
|
|
2307
|
+
let regionStart = 0;
|
|
2270
2308
|
let frozenEnd = 0;
|
|
2271
2309
|
let frozenFootnotes = /* @__PURE__ */ new Set();
|
|
2272
2310
|
let frozenLinks = /* @__PURE__ */ new Set();
|
|
@@ -2279,13 +2317,16 @@ function createDefLabelScanner(parse = collectDefLabels) {
|
|
|
2279
2317
|
};
|
|
2280
2318
|
return {
|
|
2281
2319
|
scan(source) {
|
|
2320
|
+
if (source === prevSource && prevLabels !== null) return prevLabels;
|
|
2321
|
+
const previousRegionStart = regionStart;
|
|
2322
|
+
const appended = prevSource !== null && source.startsWith(prevSource);
|
|
2323
|
+
regionStart = scanBlankLines(source, appended ? prevSource.length : 0);
|
|
2282
2324
|
let isAppend = false;
|
|
2283
2325
|
if (prevSource !== null && prevLabels !== null) {
|
|
2284
2326
|
if (source === prevSource) return prevLabels;
|
|
2285
2327
|
if (source.startsWith(prevSource)) {
|
|
2286
2328
|
isAppend = true;
|
|
2287
|
-
const
|
|
2288
|
-
const region = prevSource.slice(regionStart) + source.slice(prevSource.length);
|
|
2329
|
+
const region = source.slice(previousRegionStart);
|
|
2289
2330
|
if (!DEF_LINE_START_RE.test(region)) {
|
|
2290
2331
|
prevSource = source;
|
|
2291
2332
|
return prevLabels;
|
|
@@ -2518,8 +2559,115 @@ function* extractContributions(mdast, options = {}) {
|
|
|
2518
2559
|
for (const c of out) yield c;
|
|
2519
2560
|
}
|
|
2520
2561
|
|
|
2562
|
+
// src/components/registryIndex.ts
|
|
2563
|
+
function buildRegistryIndex(registry) {
|
|
2564
|
+
const index = {
|
|
2565
|
+
footnotes: /* @__PURE__ */ new Map(),
|
|
2566
|
+
links: /* @__PURE__ */ new Map(),
|
|
2567
|
+
numbers: /* @__PURE__ */ new Map(),
|
|
2568
|
+
counts: /* @__PURE__ */ new Map(),
|
|
2569
|
+
occurrences: /* @__PURE__ */ new Map(),
|
|
2570
|
+
labelOccurrences: /* @__PURE__ */ new Map()
|
|
2571
|
+
};
|
|
2572
|
+
for (const sym of registry.chunkOrder) {
|
|
2573
|
+
const data = registry.chunkData.get(sym);
|
|
2574
|
+
if (!data) continue;
|
|
2575
|
+
for (const label of data.defs.keys()) if (!index.footnotes.has(label)) index.footnotes.set(label, sym);
|
|
2576
|
+
for (const label of data.linkDefs.keys()) if (!index.links.has(label)) index.links.set(label, sym);
|
|
2577
|
+
const local = /* @__PURE__ */ new Map();
|
|
2578
|
+
index.occurrences.set(sym, local);
|
|
2579
|
+
for (const ref of data.refs) {
|
|
2580
|
+
if (ref.kind !== "footnote") continue;
|
|
2581
|
+
const label = ref.label;
|
|
2582
|
+
if (!index.numbers.has(label)) index.numbers.set(label, index.numbers.size + 1);
|
|
2583
|
+
const total = (index.counts.get(label) ?? 0) + 1;
|
|
2584
|
+
index.counts.set(label, total);
|
|
2585
|
+
const prior = local.get(label);
|
|
2586
|
+
if (prior) prior.count++;
|
|
2587
|
+
else {
|
|
2588
|
+
const range = { start: total, count: 1 };
|
|
2589
|
+
local.set(label, range);
|
|
2590
|
+
let byChunk = index.labelOccurrences.get(label);
|
|
2591
|
+
if (!byChunk) index.labelOccurrences.set(label, byChunk = /* @__PURE__ */ new Map());
|
|
2592
|
+
byChunk.set(sym, range);
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2596
|
+
return index;
|
|
2597
|
+
}
|
|
2598
|
+
|
|
2599
|
+
// src/components/registrySubscriptions.ts
|
|
2600
|
+
function equal(a, b) {
|
|
2601
|
+
if (a.owner !== b.owner || a.url !== b.url || a.title !== b.title || a.number !== b.number || a.count !== b.count)
|
|
2602
|
+
return false;
|
|
2603
|
+
if (a.occurrences?.size !== b.occurrences?.size) return false;
|
|
2604
|
+
if (a.occurrences) {
|
|
2605
|
+
for (const [chunk, range] of a.occurrences) {
|
|
2606
|
+
const next = b.occurrences?.get(chunk);
|
|
2607
|
+
if (!next || next.start !== range.start || next.count !== range.count) return false;
|
|
2608
|
+
}
|
|
2609
|
+
}
|
|
2610
|
+
return true;
|
|
2611
|
+
}
|
|
2612
|
+
function createRegistrySubscriptions(read) {
|
|
2613
|
+
const groups = { link: /* @__PURE__ */ new Map(), footnote: /* @__PURE__ */ new Map() };
|
|
2614
|
+
const snapshot = (kind, label, { registry, index }) => {
|
|
2615
|
+
if (kind === "link") {
|
|
2616
|
+
const owner = index.links.get(label);
|
|
2617
|
+
const def = owner ? registry.chunkData.get(owner)?.linkDefs.get(label) : void 0;
|
|
2618
|
+
return { owner, url: def?.url, title: def?.title };
|
|
2619
|
+
}
|
|
2620
|
+
return {
|
|
2621
|
+
owner: index.footnotes.get(label),
|
|
2622
|
+
number: index.numbers.get(label),
|
|
2623
|
+
count: index.counts.get(label),
|
|
2624
|
+
occurrences: index.labelOccurrences.get(label)
|
|
2625
|
+
};
|
|
2626
|
+
};
|
|
2627
|
+
return {
|
|
2628
|
+
subscribe(kind, rawLabel, cb) {
|
|
2629
|
+
const label = normalizeId(rawLabel);
|
|
2630
|
+
const map = groups[kind];
|
|
2631
|
+
let group = map.get(label);
|
|
2632
|
+
if (!group) {
|
|
2633
|
+
group = { snapshot: snapshot(kind, label, read()), listeners: /* @__PURE__ */ new Set() };
|
|
2634
|
+
map.set(label, group);
|
|
2635
|
+
}
|
|
2636
|
+
const listener = () => cb();
|
|
2637
|
+
group.listeners.add(listener);
|
|
2638
|
+
return () => {
|
|
2639
|
+
group.listeners.delete(listener);
|
|
2640
|
+
if (group.listeners.size === 0 && map.get(label) === group) map.delete(label);
|
|
2641
|
+
};
|
|
2642
|
+
},
|
|
2643
|
+
collect() {
|
|
2644
|
+
if (groups.link.size === 0 && groups.footnote.size === 0) return [];
|
|
2645
|
+
const state = read();
|
|
2646
|
+
const callbacks = [];
|
|
2647
|
+
for (const kind of ["link", "footnote"]) {
|
|
2648
|
+
for (const [label, group] of groups[kind]) {
|
|
2649
|
+
const next = snapshot(kind, label, state);
|
|
2650
|
+
if (!equal(group.snapshot, next)) callbacks.push(...group.listeners);
|
|
2651
|
+
group.snapshot = next;
|
|
2652
|
+
}
|
|
2653
|
+
}
|
|
2654
|
+
return callbacks;
|
|
2655
|
+
}
|
|
2656
|
+
};
|
|
2657
|
+
}
|
|
2658
|
+
|
|
2521
2659
|
// src/components/documentRegistry.ts
|
|
2522
2660
|
function createRegistry(onEmpty) {
|
|
2661
|
+
let index;
|
|
2662
|
+
let indexedVersion = -1;
|
|
2663
|
+
const getIndex = () => {
|
|
2664
|
+
if (!index || indexedVersion !== reg.version) {
|
|
2665
|
+
index = buildRegistryIndex(reg);
|
|
2666
|
+
indexedVersion = reg.version;
|
|
2667
|
+
}
|
|
2668
|
+
return index;
|
|
2669
|
+
};
|
|
2670
|
+
const labels = createRegistrySubscriptions(() => ({ registry: reg, index: getIndex() }));
|
|
2523
2671
|
const reg = {
|
|
2524
2672
|
chunkOrder: [],
|
|
2525
2673
|
chunkData: /* @__PURE__ */ new Map(),
|
|
@@ -2670,73 +2818,29 @@ function createRegistry(onEmpty) {
|
|
|
2670
2818
|
this._subscribers.delete(cb);
|
|
2671
2819
|
};
|
|
2672
2820
|
},
|
|
2821
|
+
subscribeLabel(kind, label, cb) {
|
|
2822
|
+
return labels.subscribe(kind, label, cb);
|
|
2823
|
+
},
|
|
2673
2824
|
canonicalFootnoteFor(label) {
|
|
2674
|
-
|
|
2675
|
-
for (const sym of this.chunkOrder) {
|
|
2676
|
-
const data = this.chunkData.get(sym);
|
|
2677
|
-
if (data?.defs.has(id)) return sym;
|
|
2678
|
-
}
|
|
2679
|
-
return null;
|
|
2825
|
+
return getIndex().footnotes.get(normalizeId(label)) ?? null;
|
|
2680
2826
|
},
|
|
2681
2827
|
canonicalLinkFor(label) {
|
|
2682
|
-
|
|
2683
|
-
for (const sym of this.chunkOrder) {
|
|
2684
|
-
const data = this.chunkData.get(sym);
|
|
2685
|
-
if (data?.linkDefs.has(id)) return sym;
|
|
2686
|
-
}
|
|
2687
|
-
return null;
|
|
2828
|
+
return getIndex().links.get(normalizeId(label)) ?? null;
|
|
2688
2829
|
},
|
|
2689
2830
|
globalNumber(label) {
|
|
2690
|
-
|
|
2691
|
-
let n = 0;
|
|
2692
|
-
const seen = /* @__PURE__ */ new Set();
|
|
2693
|
-
for (const sym of this.chunkOrder) {
|
|
2694
|
-
const data = this.chunkData.get(sym);
|
|
2695
|
-
if (!data) continue;
|
|
2696
|
-
for (const ref of data.refs) {
|
|
2697
|
-
if (ref.kind !== "footnote") continue;
|
|
2698
|
-
if (!seen.has(ref.label)) {
|
|
2699
|
-
seen.add(ref.label);
|
|
2700
|
-
n++;
|
|
2701
|
-
if (ref.label === id) return n;
|
|
2702
|
-
}
|
|
2703
|
-
}
|
|
2704
|
-
}
|
|
2705
|
-
return null;
|
|
2831
|
+
return getIndex().numbers.get(normalizeId(label)) ?? null;
|
|
2706
2832
|
},
|
|
2707
2833
|
resolveLinkDef(label) {
|
|
2708
|
-
const
|
|
2709
|
-
|
|
2710
|
-
return this.chunkData.get(sym)?.linkDefs.get(
|
|
2834
|
+
const id = normalizeId(label);
|
|
2835
|
+
const sym = getIndex().links.get(id);
|
|
2836
|
+
return sym ? this.chunkData.get(sym)?.linkDefs.get(id) ?? null : null;
|
|
2711
2837
|
},
|
|
2712
2838
|
getRefsForLabel(label) {
|
|
2713
|
-
|
|
2714
|
-
let n = 0;
|
|
2715
|
-
for (const sym of this.chunkOrder) {
|
|
2716
|
-
const data = this.chunkData.get(sym);
|
|
2717
|
-
if (!data) continue;
|
|
2718
|
-
for (const ref of data.refs) {
|
|
2719
|
-
if (ref.kind === "footnote" && ref.label === id) n++;
|
|
2720
|
-
}
|
|
2721
|
-
}
|
|
2722
|
-
return n;
|
|
2839
|
+
return getIndex().counts.get(normalizeId(label)) ?? 0;
|
|
2723
2840
|
},
|
|
2724
2841
|
globalOccurrenceForRef(chunkSym, label, localOccurrence) {
|
|
2725
|
-
const
|
|
2726
|
-
|
|
2727
|
-
for (const sym of this.chunkOrder) {
|
|
2728
|
-
const data = this.chunkData.get(sym);
|
|
2729
|
-
if (!data) continue;
|
|
2730
|
-
let localCount = 0;
|
|
2731
|
-
for (const ref of data.refs) {
|
|
2732
|
-
if (ref.kind !== "footnote") continue;
|
|
2733
|
-
if (ref.label !== id) continue;
|
|
2734
|
-
localCount++;
|
|
2735
|
-
global2++;
|
|
2736
|
-
if (sym === chunkSym && localCount === localOccurrence) return global2;
|
|
2737
|
-
}
|
|
2738
|
-
}
|
|
2739
|
-
return null;
|
|
2842
|
+
const range = getIndex().occurrences.get(chunkSym)?.get(normalizeId(label));
|
|
2843
|
+
return range && Number.isInteger(localOccurrence) && localOccurrence > 0 && localOccurrence <= range.count ? range.start + localOccurrence - 1 : null;
|
|
2740
2844
|
},
|
|
2741
2845
|
_notify() {
|
|
2742
2846
|
this.version++;
|
|
@@ -2744,7 +2848,9 @@ function createRegistry(onEmpty) {
|
|
|
2744
2848
|
this._notifyScheduled = true;
|
|
2745
2849
|
queueMicrotask(() => {
|
|
2746
2850
|
this._notifyScheduled = false;
|
|
2851
|
+
const labelCallbacks = labels.collect();
|
|
2747
2852
|
for (const cb of [...this._subscribers]) cb();
|
|
2853
|
+
for (const cb of labelCallbacks) cb();
|
|
2748
2854
|
});
|
|
2749
2855
|
}
|
|
2750
2856
|
};
|
|
@@ -2801,7 +2907,7 @@ var ENGINE_PLACEHOLDER_TAGS = /* @__PURE__ */ new Set([
|
|
|
2801
2907
|
"cross-chunk-image"
|
|
2802
2908
|
]);
|
|
2803
2909
|
var ENGINE_PROVENANCE_PROPERTY = "engineProvenance";
|
|
2804
|
-
function walk(parent, provenance) {
|
|
2910
|
+
function walk(parent, provenance, ancestors) {
|
|
2805
2911
|
const children = parent.children;
|
|
2806
2912
|
let i = 0;
|
|
2807
2913
|
while (i < children.length) {
|
|
@@ -2812,21 +2918,32 @@ function walk(parent, provenance) {
|
|
|
2812
2918
|
const genuine = provenance !== "" && typeof stamped === "string" && stamped === provenance;
|
|
2813
2919
|
if (genuine) {
|
|
2814
2920
|
delete props[ENGINE_PROVENANCE_PROPERTY];
|
|
2815
|
-
|
|
2921
|
+
if (ancestors && (node.tagName === "cross-chunk-link" || node.tagName === "cross-chunk-image")) {
|
|
2922
|
+
(node.data ??= {}).referenceAncestors = ancestors.slice();
|
|
2923
|
+
}
|
|
2924
|
+
ancestors?.push(
|
|
2925
|
+
node.tagName === "cross-chunk-link" ? "a" : node.tagName === "cross-chunk-image" ? "img" : node.tagName
|
|
2926
|
+
);
|
|
2927
|
+
walk(node, provenance, ancestors);
|
|
2928
|
+
ancestors?.pop();
|
|
2816
2929
|
i += 1;
|
|
2817
2930
|
} else {
|
|
2818
2931
|
children.splice(i, 1, ...node.children);
|
|
2819
2932
|
}
|
|
2820
2933
|
continue;
|
|
2821
2934
|
}
|
|
2822
|
-
if (node.type === "element")
|
|
2935
|
+
if (node.type === "element") {
|
|
2936
|
+
ancestors?.push(node.tagName);
|
|
2937
|
+
walk(node, provenance, ancestors);
|
|
2938
|
+
ancestors?.pop();
|
|
2939
|
+
}
|
|
2823
2940
|
i += 1;
|
|
2824
2941
|
}
|
|
2825
2942
|
}
|
|
2826
2943
|
function rehypeVerifyEngineTags(options) {
|
|
2827
2944
|
const provenance = options?.provenance ?? "";
|
|
2828
2945
|
return function transformer(tree) {
|
|
2829
|
-
walk(tree, provenance);
|
|
2946
|
+
walk(tree, provenance, options?.referenceAncestors ? [] : void 0);
|
|
2830
2947
|
};
|
|
2831
2948
|
}
|
|
2832
2949
|
|
|
@@ -2847,16 +2964,18 @@ var import_remark_remove_comments = __toESM(require("remark-remove-comments"), 1
|
|
|
2847
2964
|
// src/components/rehypeRebaseHashLinks.ts
|
|
2848
2965
|
var import_unist_util_visit5 = require("unist-util-visit");
|
|
2849
2966
|
var DEFAULT_PREFIX = "user-content-";
|
|
2967
|
+
function rebaseHashHref(href, prefix) {
|
|
2968
|
+
const hashPrefix = "#" + prefix;
|
|
2969
|
+
return href.startsWith("#") && !href.startsWith(hashPrefix) ? hashPrefix + href.slice(1) : href;
|
|
2970
|
+
}
|
|
2850
2971
|
var rehypeRebaseHashLinks = (options) => {
|
|
2851
2972
|
const prefix = options?.prefix ?? DEFAULT_PREFIX;
|
|
2852
|
-
const hashPrefix = "#" + prefix;
|
|
2853
2973
|
return (tree) => {
|
|
2854
2974
|
(0, import_unist_util_visit5.visit)(tree, "element", (node) => {
|
|
2855
2975
|
if (node.tagName !== "a") return;
|
|
2856
2976
|
const href = node.properties?.href;
|
|
2857
2977
|
if (typeof href !== "string" || !href.startsWith("#")) return;
|
|
2858
|
-
|
|
2859
|
-
node.properties.href = hashPrefix + href.slice(1);
|
|
2978
|
+
node.properties.href = rebaseHashHref(href, prefix);
|
|
2860
2979
|
});
|
|
2861
2980
|
};
|
|
2862
2981
|
};
|
|
@@ -2942,7 +3061,15 @@ function buildCoreRehypePlugins(sanitizeSchema2, clobberPrefix, options) {
|
|
|
2942
3061
|
[import_rehype_raw.default, { passThrough: [] }],
|
|
2943
3062
|
// Unwrap forged engine placeholders BEFORE sanitize admits their tag
|
|
2944
3063
|
// names. Only when the caller holds a credential (see the option's doc).
|
|
2945
|
-
...options ? [
|
|
3064
|
+
...options ? [
|
|
3065
|
+
[
|
|
3066
|
+
rehypeVerifyEngineTags,
|
|
3067
|
+
{
|
|
3068
|
+
provenance: options.provenance,
|
|
3069
|
+
...sanitizeSchema2.ancestors?.a || sanitizeSchema2.ancestors?.img ? { referenceAncestors: true } : {}
|
|
3070
|
+
}
|
|
3071
|
+
]
|
|
3072
|
+
] : [],
|
|
2946
3073
|
// Sanitize HTML while allowing <mark> (highlight), KaTeX class names,
|
|
2947
3074
|
// and any extra protocols the caller permitted via the `sanitizeSchema`
|
|
2948
3075
|
// prop. Override `clobberPrefix` with the instance-scoped value — the
|
|
@@ -3016,11 +3143,9 @@ function buildCrossChunkHandlers() {
|
|
|
3016
3143
|
type: "element",
|
|
3017
3144
|
tagName: "cross-chunk-link",
|
|
3018
3145
|
properties: {
|
|
3019
|
-
//
|
|
3020
|
-
//
|
|
3021
|
-
|
|
3022
|
-
// which also preserves source case. Registry lookups normalize
|
|
3023
|
-
// internally, so cross-chunk case-insensitive matching still works.
|
|
3146
|
+
// Display labels decode escapes; registry identifiers must retain
|
|
3147
|
+
// those bytes. Never use the display label as the lookup key.
|
|
3148
|
+
identifier: node.identifier,
|
|
3024
3149
|
label: node.label ?? node.identifier,
|
|
3025
3150
|
referenceType: node.referenceType,
|
|
3026
3151
|
documentId: s.options.documentId,
|
|
@@ -3039,6 +3164,7 @@ function buildCrossChunkHandlers() {
|
|
|
3039
3164
|
type: "element",
|
|
3040
3165
|
tagName: "cross-chunk-image",
|
|
3041
3166
|
properties: {
|
|
3167
|
+
identifier: node.identifier,
|
|
3042
3168
|
label: node.label ?? node.identifier,
|
|
3043
3169
|
referenceType: node.referenceType,
|
|
3044
3170
|
alt: node.alt ?? "",
|
|
@@ -4301,8 +4427,8 @@ var sanitizeSchema = deepFreeze(
|
|
|
4301
4427
|
attributes: {
|
|
4302
4428
|
...import_rehype_sanitize2.defaultSchema.attributes,
|
|
4303
4429
|
code: mergeClassNameAllowlist(import_rehype_sanitize2.defaultSchema.attributes?.code, ["math-inline", "math-display"]),
|
|
4304
|
-
"cross-chunk-link": ["label", "referenceType", "documentId", "localUrl", "localTitle"],
|
|
4305
|
-
"cross-chunk-image": ["label", "referenceType", "documentId", "alt", "localUrl", "localTitle"],
|
|
4430
|
+
"cross-chunk-link": ["identifier", "label", "referenceType", "documentId", "localUrl", "localTitle"],
|
|
4431
|
+
"cross-chunk-image": ["identifier", "label", "referenceType", "documentId", "alt", "localUrl", "localTitle"],
|
|
4306
4432
|
"footnote-sup": ["label", "localOccurrence", "localNumber", "documentId"]
|
|
4307
4433
|
},
|
|
4308
4434
|
strip: [.../* @__PURE__ */ new Set([...import_rehype_sanitize2.defaultSchema.strip || [], ...STRIPPED_TAGS])]
|
|
@@ -4338,6 +4464,49 @@ function sanitizeCrossChunkUrl(rawUrl, key, tagName, urlTransform, schema) {
|
|
|
4338
4464
|
return String(transformed);
|
|
4339
4465
|
}
|
|
4340
4466
|
|
|
4467
|
+
// src/components/resolveCrossChunkReference.ts
|
|
4468
|
+
var import_rehype_sanitize3 = __toESM(require("rehype-sanitize"), 1);
|
|
4469
|
+
var import_micromark_util_sanitize_uri3 = require("micromark-util-sanitize-uri");
|
|
4470
|
+
function resolveCrossChunkReference(input, schema, urlTransform, clobberPrefix) {
|
|
4471
|
+
const key = input.tagName === "a" ? "href" : "src";
|
|
4472
|
+
const element = {
|
|
4473
|
+
type: "element",
|
|
4474
|
+
tagName: input.tagName,
|
|
4475
|
+
properties: {
|
|
4476
|
+
[key]: (0, import_micromark_util_sanitize_uri3.normalizeUri)(input.url),
|
|
4477
|
+
...input.tagName === "img" ? { alt: input.alt ?? "" } : {},
|
|
4478
|
+
...input.title !== void 0 ? { title: input.title } : {}
|
|
4479
|
+
},
|
|
4480
|
+
children: input.tagName === "a" ? [{ type: "text", value: "__reference_children__" }] : []
|
|
4481
|
+
};
|
|
4482
|
+
const requiredAncestors = schema.ancestors?.[input.tagName];
|
|
4483
|
+
const recordedAncestors = input.node?.data?.referenceAncestors;
|
|
4484
|
+
let finalSchema = schema;
|
|
4485
|
+
if (requiredAncestors && Array.isArray(recordedAncestors) && requiredAncestors.some((tag) => recordedAncestors.includes(tag))) {
|
|
4486
|
+
const ancestors = { ...schema.ancestors };
|
|
4487
|
+
delete ancestors[input.tagName];
|
|
4488
|
+
finalSchema = { ...schema, ancestors };
|
|
4489
|
+
}
|
|
4490
|
+
const root2 = (0, import_rehype_sanitize3.default)({ ...finalSchema, clobberPrefix })({ type: "root", children: [element] });
|
|
4491
|
+
const node = root2.children[0];
|
|
4492
|
+
if (node?.type !== "element") return { element: null, keepChildren: node?.type === "text" };
|
|
4493
|
+
if (node.tagName === "a" && typeof node.properties.href === "string") {
|
|
4494
|
+
node.properties.href = rebaseHashHref(node.properties.href, clobberPrefix);
|
|
4495
|
+
}
|
|
4496
|
+
node.children = input.node?.children ?? [];
|
|
4497
|
+
if (input.node?.position) node.position = input.node.position;
|
|
4498
|
+
buildTransform({
|
|
4499
|
+
allowedElements: void 0,
|
|
4500
|
+
disallowedElements: void 0,
|
|
4501
|
+
allowElement: void 0,
|
|
4502
|
+
skipHtml: void 0,
|
|
4503
|
+
unwrapDisallowed: void 0,
|
|
4504
|
+
urlTransform
|
|
4505
|
+
})(node, 0, root2);
|
|
4506
|
+
node.children = [];
|
|
4507
|
+
return { element: node, keepChildren: false };
|
|
4508
|
+
}
|
|
4509
|
+
|
|
4341
4510
|
// src/plugins/defs.ts
|
|
4342
4511
|
function getEnginePluginInternals(plugin) {
|
|
4343
4512
|
const candidate = plugin;
|
|
@@ -4542,6 +4711,8 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4542
4711
|
let source = "";
|
|
4543
4712
|
let visibleEnd = 0;
|
|
4544
4713
|
let pending = [];
|
|
4714
|
+
let pendingHead = 0;
|
|
4715
|
+
const pendingCount = () => pending.length - pendingHead;
|
|
4545
4716
|
let tentativeEnd = 0;
|
|
4546
4717
|
let finished = false;
|
|
4547
4718
|
let seam;
|
|
@@ -4586,7 +4757,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4586
4757
|
cancelFrame = void 0;
|
|
4587
4758
|
};
|
|
4588
4759
|
const ensureScheduled = () => {
|
|
4589
|
-
if (disposed || cancelFrame ||
|
|
4760
|
+
if (disposed || cancelFrame || pendingCount() === 0) return;
|
|
4590
4761
|
lastTickAt = now();
|
|
4591
4762
|
credit = 0;
|
|
4592
4763
|
cancelFrame = schedule(tick);
|
|
@@ -4600,31 +4771,38 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4600
4771
|
const params = resolveParams();
|
|
4601
4772
|
let rate;
|
|
4602
4773
|
if (finished && drainDeadlineAt !== void 0) {
|
|
4603
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4774
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, drainDeadlineAt - t));
|
|
4604
4775
|
} else if (gapWindow.length > 0 && lastArrivalAt !== void 0) {
|
|
4605
4776
|
const gaps = gapWindow.map((s) => s.gap).sort((a, b) => a - b);
|
|
4606
4777
|
const intervalQ = gaps[Math.min(gaps.length - 1, Math.floor(gaps.length * INTERVAL_QUANTILE))];
|
|
4607
4778
|
const horizon = Math.max(16, Math.min(params.bufferFactor * intervalQ + HORIZON_PAD_MS, params.maxLagMs));
|
|
4608
4779
|
const deadline = Math.max(lastArrivalAt + horizon, t + DEADLINE_FLOOR_MS);
|
|
4609
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4780
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, deadline - t));
|
|
4610
4781
|
} else {
|
|
4611
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4782
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, params.correctionTauMs));
|
|
4612
4783
|
}
|
|
4613
4784
|
credit += rate * dt / 1e3;
|
|
4614
|
-
const reveal = Math.min(Math.floor(credit),
|
|
4785
|
+
const reveal = Math.min(Math.floor(credit), pendingCount());
|
|
4615
4786
|
if (reveal > 0) {
|
|
4616
|
-
visibleEnd = pending[reveal - 1];
|
|
4617
|
-
|
|
4618
|
-
|
|
4787
|
+
visibleEnd = pending[pendingHead + reveal - 1];
|
|
4788
|
+
pendingHead += reveal;
|
|
4789
|
+
if (pendingHead === pending.length) {
|
|
4790
|
+
pending = [];
|
|
4791
|
+
pendingHead = 0;
|
|
4792
|
+
} else if (pendingHead >= 1024 && pendingHead * 2 >= pending.length) {
|
|
4793
|
+
pending = pending.slice(pendingHead);
|
|
4794
|
+
pendingHead = 0;
|
|
4795
|
+
}
|
|
4796
|
+
credit = pendingCount() > 0 ? credit - reveal : 0;
|
|
4619
4797
|
notify();
|
|
4620
4798
|
}
|
|
4621
|
-
if (!disposed && !cancelFrame &&
|
|
4799
|
+
if (!disposed && !cancelFrame && pendingCount() > 0) cancelFrame = schedule(tick);
|
|
4622
4800
|
};
|
|
4623
4801
|
const resegmentTail = () => {
|
|
4624
|
-
if (seam !== void 0 && seam < source.length && pending[pending.length - 1] === seam) {
|
|
4802
|
+
if (pendingCount() > 0 && seam !== void 0 && seam < source.length && pending[pending.length - 1] === seam) {
|
|
4625
4803
|
pending.pop();
|
|
4626
4804
|
}
|
|
4627
|
-
const from =
|
|
4805
|
+
const from = pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd;
|
|
4628
4806
|
let anchor = from;
|
|
4629
4807
|
if (seam !== void 0 && from <= seam) {
|
|
4630
4808
|
anchor = Math.max(0, from - RESUME_LOOKBACK);
|
|
@@ -4658,6 +4836,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4658
4836
|
visibleEnd = next.length;
|
|
4659
4837
|
tentativeEnd = next.length;
|
|
4660
4838
|
pending = [];
|
|
4839
|
+
pendingHead = 0;
|
|
4661
4840
|
seam = next.length;
|
|
4662
4841
|
credit = 0;
|
|
4663
4842
|
cancelScheduled();
|
|
@@ -4689,7 +4868,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4689
4868
|
if (finished) return;
|
|
4690
4869
|
finished = true;
|
|
4691
4870
|
lastArrivalAt = void 0;
|
|
4692
|
-
if (tentativeEnd > (
|
|
4871
|
+
if (tentativeEnd > (pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd)) {
|
|
4693
4872
|
pending.push(tentativeEnd);
|
|
4694
4873
|
}
|
|
4695
4874
|
const params = resolveParams();
|
|
@@ -4715,10 +4894,11 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4715
4894
|
snap,
|
|
4716
4895
|
flush() {
|
|
4717
4896
|
disposed = false;
|
|
4718
|
-
const target = finished ? source.length :
|
|
4897
|
+
const target = finished ? source.length : pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd;
|
|
4719
4898
|
if (target <= visibleEnd) return;
|
|
4720
4899
|
visibleEnd = target;
|
|
4721
4900
|
pending = [];
|
|
4901
|
+
pendingHead = 0;
|
|
4722
4902
|
credit = 0;
|
|
4723
4903
|
cancelScheduled();
|
|
4724
4904
|
notify();
|
|
@@ -5569,6 +5749,7 @@ function createRemendPreprocessor(options) {
|
|
|
5569
5749
|
rehypeRebaseHashLinks,
|
|
5570
5750
|
rehypeVerifyEngineTags,
|
|
5571
5751
|
removeComments,
|
|
5752
|
+
resolveCrossChunkReference,
|
|
5572
5753
|
sanitizeCrossChunkUrl,
|
|
5573
5754
|
sanitizeSchema,
|
|
5574
5755
|
shortenDocumentId,
|