@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.dev.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"]);
|
|
@@ -710,43 +757,6 @@ function maskIntraLineCodeSpans(text, carryOpen) {
|
|
|
710
757
|
out += text.slice(cursor);
|
|
711
758
|
return { masked: out, unpaired: false };
|
|
712
759
|
}
|
|
713
|
-
function freshCheckpoint(defListEnabled, mathFlow, referenceTaint) {
|
|
714
|
-
return {
|
|
715
|
-
defListEnabled,
|
|
716
|
-
mathFlow,
|
|
717
|
-
referenceTaint,
|
|
718
|
-
confirmedOffset: 0,
|
|
719
|
-
candidates: [],
|
|
720
|
-
defs: /* @__PURE__ */ new Map(),
|
|
721
|
-
footnoteDefs: /* @__PURE__ */ new Map(),
|
|
722
|
-
unresolvedRefs: [],
|
|
723
|
-
tagBalance: /* @__PURE__ */ new Map(),
|
|
724
|
-
openTotal: 0,
|
|
725
|
-
p5Tok: { kind: "data" },
|
|
726
|
-
formPointerMaybeSet: false,
|
|
727
|
-
openStack: [],
|
|
728
|
-
mdBlock: { kind: "none" },
|
|
729
|
-
blankRun: 0,
|
|
730
|
-
lastBlankStart: -1,
|
|
731
|
-
hazardVerdict: false,
|
|
732
|
-
prevLineBlank: true,
|
|
733
|
-
// doc start counts as a block start
|
|
734
|
-
prevLineWasText: false,
|
|
735
|
-
prevLineWasValidDef: false,
|
|
736
|
-
prevLineOpenContent: false,
|
|
737
|
-
tableMaybeOpen: false,
|
|
738
|
-
containerMaybeOpen: false,
|
|
739
|
-
paragraphHasUnpairedRun: false,
|
|
740
|
-
openBracket: null,
|
|
741
|
-
p5SealPending: false,
|
|
742
|
-
defBlockMaybeOpen: false,
|
|
743
|
-
fnDefResumable: false,
|
|
744
|
-
phasePoisonedAt: Infinity,
|
|
745
|
-
pendingTruncatedTags: [],
|
|
746
|
-
pendingTruncatedCloses: [],
|
|
747
|
-
pendingTag: null
|
|
748
|
-
};
|
|
749
|
-
}
|
|
750
760
|
function classifyBlockStart(text, indent, defListEnabled) {
|
|
751
761
|
if (indent >= 4) return true;
|
|
752
762
|
if (LIST_MARKER_RE.test(text) || FOOTNOTE_DEF_RE.test(text)) return true;
|
|
@@ -754,71 +764,23 @@ function classifyBlockStart(text, indent, defListEnabled) {
|
|
|
754
764
|
if (indent === 0) return false;
|
|
755
765
|
return null;
|
|
756
766
|
}
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
textEnd = nl;
|
|
775
|
-
end = nl;
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
const confirmed = end < text.length && !(end === text.length - 1 && text.charCodeAt(end) === 13);
|
|
779
|
-
const lineText = text.slice(start, textEnd);
|
|
780
|
-
const ln = {
|
|
781
|
-
start,
|
|
782
|
-
end,
|
|
783
|
-
text: lineText,
|
|
784
|
-
blank: confirmed && isMdBlank(lineText),
|
|
785
|
-
indent: computeIndent(lineText)
|
|
786
|
-
};
|
|
787
|
-
if (!confirmed) {
|
|
788
|
-
tailLine = ln;
|
|
789
|
-
break;
|
|
790
|
-
}
|
|
791
|
-
processConfirmedLine(cp, ln, text);
|
|
792
|
-
cp.confirmedOffset = end + 1;
|
|
793
|
-
start = end + 1;
|
|
794
|
-
}
|
|
795
|
-
const earliestUnresolved = settleRefsAndEarliestUnresolved(cp);
|
|
796
|
-
const defListSettled = (c) => {
|
|
797
|
-
if (!options.defListEnabled || c.blankRun >= 2) return true;
|
|
798
|
-
if (c.defListSettled !== null) return c.defListSettled;
|
|
799
|
-
if (tailLine) return !canBecomeDdLine(tailLine.text, false);
|
|
800
|
-
return false;
|
|
801
|
-
};
|
|
802
|
-
const tailRetroactive = tailLine !== null && tailCarriesRetroactive(tailLine.text);
|
|
803
|
-
let boundary = 0;
|
|
804
|
-
for (let i = cp.candidates.length - 1; i >= 0 && !tailRetroactive; i--) {
|
|
805
|
-
const c = cp.candidates[i];
|
|
806
|
-
if (!c.htmlBalanced || c.hazard || c.seamRisk) continue;
|
|
807
|
-
if (c.offset > cp.phasePoisonedAt) continue;
|
|
808
|
-
if (c.offset > earliestUnresolved) continue;
|
|
809
|
-
if (!defListSettled(c)) continue;
|
|
810
|
-
boundary = c.offset;
|
|
811
|
-
break;
|
|
812
|
-
}
|
|
813
|
-
return { boundary, checkpoint: cp };
|
|
814
|
-
}
|
|
815
|
-
function pendingFenceCloser(checkpoint) {
|
|
816
|
-
const cp = checkpoint;
|
|
817
|
-
if (cp.phasePoisonedAt !== Infinity) return "";
|
|
818
|
-
if (cp.mdBlock.kind === "fence" && cp.mdBlock.indent === 0) return cp.mdBlock.char.repeat(cp.mdBlock.len);
|
|
819
|
-
if (cp.mdBlock.kind === "math" && cp.mdBlock.indent === 0) return "$".repeat(cp.mdBlock.len);
|
|
820
|
-
return "";
|
|
821
|
-
}
|
|
767
|
+
var SCANNER_NAME_LISTS = [
|
|
768
|
+
["type1", TYPE1_NAMES],
|
|
769
|
+
["rawText", RAW_TEXT_ELEMENTS],
|
|
770
|
+
["type6", TYPE6_NAMES],
|
|
771
|
+
["void", VOID_TAGS],
|
|
772
|
+
["documentStructure", DOCUMENT_STRUCTURE_NAMES],
|
|
773
|
+
// Added with F28, and it is the list that would have made F28 visible: the
|
|
774
|
+
// derived census alphabet partitions names by their membership across THIS
|
|
775
|
+
// table, so before it existed `frame` shared one 39-name class with `div`
|
|
776
|
+
// and could never be sampled apart from it.
|
|
777
|
+
["noElement", NO_ELEMENT_NAMES],
|
|
778
|
+
["tablePart", TABLE_PART_NAMES],
|
|
779
|
+
["scopeBarrier", SCOPE_BARRIER_NAMES],
|
|
780
|
+
["foreignRoot", new Set(FOREIGN_ROOT_NAMES)]
|
|
781
|
+
];
|
|
782
|
+
|
|
783
|
+
// src/components/incrementalParse/freezeLineTransition.ts
|
|
822
784
|
function floatingResidue(text, commentOpenAtStart) {
|
|
823
785
|
let out = "";
|
|
824
786
|
let open = commentOpenAtStart;
|
|
@@ -1468,24 +1430,66 @@ function processConfirmedLine(cp, ln, text) {
|
|
|
1468
1430
|
}
|
|
1469
1431
|
}
|
|
1470
1432
|
}
|
|
1471
|
-
var SCANNER_NAME_LISTS = [
|
|
1472
|
-
["type1", TYPE1_NAMES],
|
|
1473
|
-
["rawText", RAW_TEXT_ELEMENTS],
|
|
1474
|
-
["type6", TYPE6_NAMES],
|
|
1475
|
-
["void", VOID_TAGS],
|
|
1476
|
-
["documentStructure", DOCUMENT_STRUCTURE_NAMES],
|
|
1477
|
-
// Added with F28, and it is the list that would have made F28 visible: the
|
|
1478
|
-
// derived census alphabet partitions names by their membership across THIS
|
|
1479
|
-
// table, so before it existed `frame` shared one 39-name class with `div`
|
|
1480
|
-
// and could never be sampled apart from it.
|
|
1481
|
-
["noElement", NO_ELEMENT_NAMES],
|
|
1482
|
-
["tablePart", TABLE_PART_NAMES],
|
|
1483
|
-
["scopeBarrier", SCOPE_BARRIER_NAMES],
|
|
1484
|
-
["foreignRoot", new Set(FOREIGN_ROOT_NAMES)]
|
|
1485
|
-
];
|
|
1486
1433
|
|
|
1487
|
-
// src/components/incrementalParse/
|
|
1488
|
-
|
|
1434
|
+
// src/components/incrementalParse/computeFreezeBoundary.ts
|
|
1435
|
+
function computeFreezeBoundary(text, options, resume) {
|
|
1436
|
+
const mathFlow = options.mathFlow ?? true;
|
|
1437
|
+
const referenceTaint = options.referenceTaint ?? true;
|
|
1438
|
+
const prev = resume;
|
|
1439
|
+
const cp = prev && prev.defListEnabled === options.defListEnabled && prev.mathFlow === mathFlow && prev.referenceTaint === referenceTaint && prev.confirmedOffset <= text.length ? prev : freshCheckpoint(options.defListEnabled, mathFlow, referenceTaint);
|
|
1440
|
+
let start = cp.confirmedOffset;
|
|
1441
|
+
let tailLine = null;
|
|
1442
|
+
while (start < text.length) {
|
|
1443
|
+
let end = text.length;
|
|
1444
|
+
let textEnd = text.length;
|
|
1445
|
+
{
|
|
1446
|
+
const nl = text.indexOf("\n", start);
|
|
1447
|
+
const cr = text.indexOf("\r", start);
|
|
1448
|
+
if (cr !== -1 && (nl === -1 || cr < nl)) {
|
|
1449
|
+
textEnd = cr;
|
|
1450
|
+
end = text.charCodeAt(cr + 1) === 10 ? cr + 1 : cr;
|
|
1451
|
+
} else if (nl !== -1) {
|
|
1452
|
+
textEnd = nl;
|
|
1453
|
+
end = nl;
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
const confirmed = end < text.length && !(end === text.length - 1 && text.charCodeAt(end) === 13);
|
|
1457
|
+
const lineText = text.slice(start, textEnd);
|
|
1458
|
+
const ln = {
|
|
1459
|
+
start,
|
|
1460
|
+
end,
|
|
1461
|
+
text: lineText,
|
|
1462
|
+
blank: confirmed && isMdBlank(lineText),
|
|
1463
|
+
indent: computeIndent(lineText)
|
|
1464
|
+
};
|
|
1465
|
+
if (!confirmed) {
|
|
1466
|
+
tailLine = ln;
|
|
1467
|
+
break;
|
|
1468
|
+
}
|
|
1469
|
+
processConfirmedLine(cp, ln, text);
|
|
1470
|
+
cp.confirmedOffset = end + 1;
|
|
1471
|
+
start = end + 1;
|
|
1472
|
+
}
|
|
1473
|
+
const earliestUnresolved = settleRefsAndEarliestUnresolved(cp);
|
|
1474
|
+
const defListSettled = (c) => {
|
|
1475
|
+
if (!options.defListEnabled || c.blankRun >= 2) return true;
|
|
1476
|
+
if (c.defListSettled !== null) return c.defListSettled;
|
|
1477
|
+
if (tailLine) return !canBecomeDdLine(tailLine.text, false);
|
|
1478
|
+
return false;
|
|
1479
|
+
};
|
|
1480
|
+
const tailRetroactive = tailLine !== null && tailCarriesRetroactive(tailLine.text);
|
|
1481
|
+
let boundary = 0;
|
|
1482
|
+
for (let i = cp.candidates.length - 1; i >= 0 && !tailRetroactive; i--) {
|
|
1483
|
+
const c = cp.candidates[i];
|
|
1484
|
+
if (!c.htmlBalanced || c.hazard || c.seamRisk) continue;
|
|
1485
|
+
if (c.offset > cp.phasePoisonedAt) continue;
|
|
1486
|
+
if (c.offset > earliestUnresolved) continue;
|
|
1487
|
+
if (!defListSettled(c)) continue;
|
|
1488
|
+
boundary = c.offset;
|
|
1489
|
+
break;
|
|
1490
|
+
}
|
|
1491
|
+
return { boundary, checkpoint: cp };
|
|
1492
|
+
}
|
|
1489
1493
|
|
|
1490
1494
|
// src/components/hastPredicates.ts
|
|
1491
1495
|
function isFootnoteSection(node) {
|
|
@@ -1533,121 +1537,7 @@ function attributeHastChildren(mdast, hast, stopAt = Infinity) {
|
|
|
1533
1537
|
}
|
|
1534
1538
|
}
|
|
1535
1539
|
|
|
1536
|
-
// src/components/incrementalParse/
|
|
1537
|
-
function collectPrefixInjection(mdast, content, boundary, resume) {
|
|
1538
|
-
const resumeValid = resume != null && resume.boundary <= boundary;
|
|
1539
|
-
if (resumeValid && resume.uninjectable) return { events: resume.events, uninjectable: true };
|
|
1540
|
-
const resumeAt = resumeValid ? resume.boundary : 0;
|
|
1541
|
-
const events = resumeAt > 0 ? cloneEventsForAppend(resume.events) : [];
|
|
1542
|
-
let uninjectable = false;
|
|
1543
|
-
let cacheable = true;
|
|
1544
|
-
const pushRef = (token) => {
|
|
1545
|
-
const last = events[events.length - 1];
|
|
1546
|
-
if (last && last.kind === "refs") last.tokens.push(token);
|
|
1547
|
-
else events.push({ kind: "refs", tokens: [token] });
|
|
1548
|
-
};
|
|
1549
|
-
const visit7 = (node, nested) => {
|
|
1550
|
-
const type = node.type;
|
|
1551
|
-
if (type === "definition") {
|
|
1552
|
-
const start = node.position?.start?.offset;
|
|
1553
|
-
const end = node.position?.end?.offset;
|
|
1554
|
-
if (start !== void 0 && end !== void 0 && start < boundary) {
|
|
1555
|
-
const slice = content.slice(start, end);
|
|
1556
|
-
if (nested && slice.includes("\n")) uninjectable = true;
|
|
1557
|
-
else events.push({ kind: "def", source: slice });
|
|
1558
|
-
}
|
|
1559
|
-
return;
|
|
1560
|
-
}
|
|
1561
|
-
if (type === "footnoteDefinition") {
|
|
1562
|
-
const start = node.position?.start;
|
|
1563
|
-
const end = node.position?.end?.offset;
|
|
1564
|
-
if (start?.offset === void 0 || end === void 0 || start.offset >= boundary) return;
|
|
1565
|
-
if (nested) {
|
|
1566
|
-
uninjectable = true;
|
|
1567
|
-
return;
|
|
1568
|
-
}
|
|
1569
|
-
const lineStart = start.offset - (start.column - 1);
|
|
1570
|
-
events.push({
|
|
1571
|
-
kind: "footnoteDef",
|
|
1572
|
-
source: content.slice(lineStart, end),
|
|
1573
|
-
origStart: lineStart,
|
|
1574
|
-
origLine: start.line
|
|
1575
|
-
});
|
|
1576
|
-
return;
|
|
1577
|
-
}
|
|
1578
|
-
if (type === "footnoteReference") {
|
|
1579
|
-
const start = node.position?.start?.offset;
|
|
1580
|
-
const end = node.position?.end?.offset;
|
|
1581
|
-
if (start === void 0 || end === void 0) {
|
|
1582
|
-
uninjectable = true;
|
|
1583
|
-
return;
|
|
1584
|
-
}
|
|
1585
|
-
pushRef(content.slice(start, end));
|
|
1586
|
-
return;
|
|
1587
|
-
}
|
|
1588
|
-
const children = node.children;
|
|
1589
|
-
if (children) {
|
|
1590
|
-
for (const child of children) visit7(child, true);
|
|
1591
|
-
}
|
|
1592
|
-
};
|
|
1593
|
-
let lastStart = -1;
|
|
1594
|
-
for (const child of mdast.children) {
|
|
1595
|
-
const start = child.position?.start?.offset;
|
|
1596
|
-
if (start !== void 0) {
|
|
1597
|
-
if (start < lastStart) return { events: [], uninjectable: true, cacheable: false };
|
|
1598
|
-
lastStart = start;
|
|
1599
|
-
}
|
|
1600
|
-
if (start === void 0) {
|
|
1601
|
-
if (resumeAt > 0) return collectPrefixInjection(mdast, content, boundary, null);
|
|
1602
|
-
cacheable = false;
|
|
1603
|
-
visit7(child, false);
|
|
1604
|
-
continue;
|
|
1605
|
-
}
|
|
1606
|
-
if (start >= boundary || start < resumeAt) continue;
|
|
1607
|
-
visit7(child, false);
|
|
1608
|
-
}
|
|
1609
|
-
return { events, uninjectable, cacheable };
|
|
1610
|
-
}
|
|
1611
|
-
function cloneEventsForAppend(events) {
|
|
1612
|
-
const out = events.slice();
|
|
1613
|
-
const last = out[out.length - 1];
|
|
1614
|
-
if (last && last.kind === "refs") out[out.length - 1] = { kind: "refs", tokens: last.tokens.slice() };
|
|
1615
|
-
return out;
|
|
1616
|
-
}
|
|
1617
|
-
var TERMINATOR_LABEL = "__aimd_injection_terminator__";
|
|
1618
|
-
var INJECTION_TERMINATOR = `[${TERMINATOR_LABEL}]: __aimd_sentinel_link__`;
|
|
1619
|
-
function tailMentionsTerminator(tailSource) {
|
|
1620
|
-
return (0, import_micromark_util_normalize_identifier2.normalizeIdentifier)(tailSource).replace(/\[ /g, "[").includes(`[${(0, import_micromark_util_normalize_identifier2.normalizeIdentifier)(TERMINATOR_LABEL)}`);
|
|
1621
|
-
}
|
|
1622
|
-
function buildInjectionPrefix(events) {
|
|
1623
|
-
if (events.length === 0) return { text: "", segments: [] };
|
|
1624
|
-
let text = "";
|
|
1625
|
-
let line = 1;
|
|
1626
|
-
const segments = [];
|
|
1627
|
-
for (const event of events) {
|
|
1628
|
-
if (text.length > 0) {
|
|
1629
|
-
text += "\n\n";
|
|
1630
|
-
line += 2;
|
|
1631
|
-
}
|
|
1632
|
-
const injStart = text.length;
|
|
1633
|
-
const source = event.kind === "refs" ? event.tokens.join(" ") : event.source;
|
|
1634
|
-
if (event.kind === "footnoteDef") {
|
|
1635
|
-
segments.push({
|
|
1636
|
-
injStart,
|
|
1637
|
-
injEnd: injStart + source.length,
|
|
1638
|
-
offsetDelta: event.origStart - injStart,
|
|
1639
|
-
lineDelta: event.origLine - line
|
|
1640
|
-
});
|
|
1641
|
-
}
|
|
1642
|
-
text += source;
|
|
1643
|
-
line += countNewlines(source);
|
|
1644
|
-
}
|
|
1645
|
-
return { text: `${text}
|
|
1646
|
-
|
|
1647
|
-
${INJECTION_TERMINATOR}
|
|
1648
|
-
|
|
1649
|
-
`, segments };
|
|
1650
|
-
}
|
|
1540
|
+
// src/components/incrementalParse/spliceCoordinates.ts
|
|
1651
1541
|
function rebaseTree(node, offsetDelta, lineDelta) {
|
|
1652
1542
|
rebaseTreeDual(node, EMPTY_SEGMENTS, offsetDelta, lineDelta);
|
|
1653
1543
|
}
|
|
@@ -1676,6 +1566,23 @@ function rebaseDualWalk(node, segments, maxEnd, offsetDelta, lineDelta) {
|
|
|
1676
1566
|
for (const child of children) rebaseDualWalk(child, segments, maxEnd, offsetDelta, lineDelta);
|
|
1677
1567
|
}
|
|
1678
1568
|
}
|
|
1569
|
+
function rebasePoint(point, offsetDelta, lineDelta) {
|
|
1570
|
+
return {
|
|
1571
|
+
line: point.line + lineDelta,
|
|
1572
|
+
column: point.column,
|
|
1573
|
+
offset: point.offset !== void 0 ? point.offset + offsetDelta : void 0
|
|
1574
|
+
};
|
|
1575
|
+
}
|
|
1576
|
+
function countNewlines(text, end = text.length) {
|
|
1577
|
+
let count = 0;
|
|
1578
|
+
for (let i = text.indexOf("\n"); i !== -1 && i < end; i = text.indexOf("\n", i + 1)) count += 1;
|
|
1579
|
+
for (let i = text.indexOf("\r"); i !== -1 && i < end; i = text.indexOf("\r", i + 1)) {
|
|
1580
|
+
if (text.charCodeAt(i + 1) !== 10) count += 1;
|
|
1581
|
+
}
|
|
1582
|
+
return count;
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
// src/components/incrementalParse/spliceHtmlGuards.ts
|
|
1679
1586
|
var TABLE_PART_TAG_RE = /<(?:td|th|tr|tbody|thead|tfoot|caption|col|colgroup)\b/i;
|
|
1680
1587
|
var TABLE_TOKEN_RE = /<(\/?)(table|td|th|tr|tbody|thead|tfoot|caption|col|colgroup)\b/gi;
|
|
1681
1588
|
function hasStrayTablePart(values) {
|
|
@@ -1757,127 +1664,26 @@ function rawTextRegionCrossesOut(values) {
|
|
|
1757
1664
|
}
|
|
1758
1665
|
return false;
|
|
1759
1666
|
}
|
|
1760
|
-
function
|
|
1761
|
-
const
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
}
|
|
1772
|
-
const attrs = attributeHastChildren(prevMdast, prevHast, boundary);
|
|
1773
|
-
const cutRegion = [];
|
|
1774
|
-
for (let i = 0; i < prevHast.children.length; i++) {
|
|
1775
|
-
if (attrs[i] < boundary) {
|
|
1776
|
-
const node2 = prevHast.children[i];
|
|
1777
|
-
const end = node2.position?.end?.offset;
|
|
1778
|
-
if (end !== void 0 && end > boundary) return null;
|
|
1779
|
-
if (isTrailingLiteralText(node2)) {
|
|
1780
|
-
const prev = i > 0 ? prevHast.children[i - 1] : void 0;
|
|
1781
|
-
if (!prev || prev.type !== "element" || prev.position === void 0) return null;
|
|
1782
|
-
if (!ownsTrailingLiteral(prev, node2, prefixMdast))
|
|
1783
|
-
return null;
|
|
1784
|
-
}
|
|
1785
|
-
cutRegion.push(node2);
|
|
1786
|
-
continue;
|
|
1787
|
-
}
|
|
1788
|
-
const node = prevHast.children[i];
|
|
1789
|
-
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
|
|
1790
|
-
// raw literal can only trail an `html` mdast node. A position-less
|
|
1791
|
-
// text after a `<p>` is the NEXT block's remnant — a stray end tag
|
|
1792
|
-
// (`</t>\na`) parse5 dropped, whose text merged with the wrap
|
|
1793
|
-
// separator — owned by the tail, which re-parses it; freezing it
|
|
1794
|
-
// here duplicated it (v2.4.0 review P3). Falls through to the
|
|
1795
|
-
// remnant look-ahead below, which bails to a full parse. And the
|
|
1796
|
-
// literal must really be THAT block's trailing text: the block's raw
|
|
1797
|
-
// source ends with it. A dropped-tag block right after a frozen html
|
|
1798
|
-
// element (`</details>\n\n</t>\ntext`) puts its remnant in the same
|
|
1799
|
-
// position, and freezing it duplicated it (release soak of the fix).
|
|
1800
|
-
ownsTrailingLiteral(prevHast.children[i - 1], node, prefixMdast)) {
|
|
1801
|
-
cutRegion.push(node);
|
|
1802
|
-
break;
|
|
1803
|
-
}
|
|
1804
|
-
for (let j = i; j < prevHast.children.length; j++) {
|
|
1805
|
-
const look = prevHast.children[j];
|
|
1806
|
-
if (look.type === "element" || look.position !== void 0) break;
|
|
1807
|
-
if (isTrailingLiteralText(look)) return null;
|
|
1808
|
-
}
|
|
1809
|
-
break;
|
|
1810
|
-
}
|
|
1811
|
-
const tailMdastChildren = tailMdast.children.filter((child) => {
|
|
1812
|
-
const start = child.position?.start?.offset;
|
|
1813
|
-
return !(start !== void 0 && start < injectedLen);
|
|
1814
|
-
});
|
|
1815
|
-
const tailWrapVisible = tailMdastChildren.some((child) => !isWrapInvisible(child));
|
|
1816
|
-
const prefixHtmlValues = prefixMdast.flatMap((c) => c.type === "html" ? [c.value] : []);
|
|
1817
|
-
if (hasStrayTablePart(prefixHtmlValues)) return null;
|
|
1818
|
-
if (rawTextRegionCrossesOut(prefixHtmlValues)) return null;
|
|
1819
|
-
const leadingHtml = [];
|
|
1820
|
-
for (const child of tailMdastChildren) {
|
|
1821
|
-
if (isWrapInvisible(child)) continue;
|
|
1822
|
-
if (child.type !== "html") break;
|
|
1823
|
-
if (STRAY_SYNTHESIZED_END_TAG_RE.test(child.value) || TABLE_PART_TAG_RE.test(child.value)) return null;
|
|
1824
|
-
leadingHtml.push(child.value);
|
|
1667
|
+
function isSanitizeStrippedConstruct(value) {
|
|
1668
|
+
const v = value.trim();
|
|
1669
|
+
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(">");
|
|
1670
|
+
}
|
|
1671
|
+
function isExactSanitizeStrippedConstruct(value) {
|
|
1672
|
+
if (value.startsWith("<!--")) {
|
|
1673
|
+
if (value.length < 7 || !value.endsWith("-->")) return false;
|
|
1674
|
+
const close = value.indexOf("-->", 4);
|
|
1675
|
+
const bangClose = value.indexOf("--!>", 4);
|
|
1676
|
+
if (close !== value.length - 3) return false;
|
|
1677
|
+
return bangClose === -1 || bangClose > close;
|
|
1825
1678
|
}
|
|
1826
|
-
if (
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
const hastChildren = aligned.children;
|
|
1830
|
-
const interiorFinalLiteral = aligned.interiorFinalLiteral;
|
|
1831
|
-
const stripResult = stripInjectedHast(tailMdast, tailHast, injectedLen, tailWrapVisible);
|
|
1832
|
-
if (stripResult === null) return null;
|
|
1833
|
-
const strippedTailHast = stripResult.rest;
|
|
1834
|
-
for (const child of tailMdastChildren) rebaseTree(child, offsetDelta, lineDelta);
|
|
1835
|
-
for (const child of strippedTailHast) rebaseTreeDual(child, injectedSegments, offsetDelta, lineDelta);
|
|
1836
|
-
const mdastChildren = prefixMdast.concat(tailMdastChildren);
|
|
1837
|
-
const seamMergeVerdict = stripResult.remnantMerged ?? tailLeadingTextIsHoist(tailMdastChildren, strippedTailHast);
|
|
1838
|
-
if (seamMergeVerdict === null) return null;
|
|
1839
|
-
const seamMergeAllowed = seamMergeVerdict;
|
|
1840
|
-
let firstTailChild = true;
|
|
1841
|
-
for (const child of strippedTailHast) {
|
|
1842
|
-
const tailEnd = hastChildren[hastChildren.length - 1];
|
|
1843
|
-
if (firstTailChild && child.type === "text" && child.position !== void 0) {
|
|
1844
|
-
return null;
|
|
1845
|
-
}
|
|
1846
|
-
if (firstTailChild && tailEnd && tailEnd.type === "text" && child.type === "text" && child.position === void 0) {
|
|
1847
|
-
if (interiorFinalLiteral && tailEnd.value.trim() !== "") {
|
|
1848
|
-
if (seamMergeAllowed) return null;
|
|
1849
|
-
firstTailChild = false;
|
|
1850
|
-
hastChildren.push(child);
|
|
1851
|
-
continue;
|
|
1852
|
-
}
|
|
1853
|
-
const literalSeam = tailEnd.value.trim() !== "" && !tailWrapVisible;
|
|
1854
|
-
if (seamMergeAllowed || literalSeam) {
|
|
1855
|
-
hastChildren[hastChildren.length - 1] = { type: "text", value: tailEnd.value + child.value };
|
|
1856
|
-
firstTailChild = false;
|
|
1857
|
-
continue;
|
|
1858
|
-
}
|
|
1859
|
-
}
|
|
1860
|
-
firstTailChild = false;
|
|
1861
|
-
hastChildren.push(child);
|
|
1679
|
+
if (/^<!doctype/i.test(value)) return false;
|
|
1680
|
+
if (value.startsWith("<?") || /^<!(?:[A-Za-z]|\[CDATA\[)/.test(value)) {
|
|
1681
|
+
return value.indexOf(">") === value.length - 1;
|
|
1862
1682
|
}
|
|
1863
|
-
|
|
1864
|
-
const docStart = { line: 1, column: 1, offset: 0 };
|
|
1865
|
-
const mdastRootPosition = tailMdast.position ? { start: docStart, end: rebasePoint(tailMdast.position.end, offsetDelta, lineDelta) } : prevMdast.position;
|
|
1866
|
-
const hastRootPosition = mdastRootPosition;
|
|
1867
|
-
const mdast = { type: "root", children: mdastChildren };
|
|
1868
|
-
if (mdastRootPosition) mdast.position = mdastRootPosition;
|
|
1869
|
-
const hast = { type: "root", children: hastChildren };
|
|
1870
|
-
if (hastRootPosition) hast.position = hastRootPosition;
|
|
1871
|
-
if (prevHast.data !== void 0) hast.data = prevHast.data;
|
|
1872
|
-
return { mdast, hast };
|
|
1873
|
-
}
|
|
1874
|
-
function rebasePoint(point, offsetDelta, lineDelta) {
|
|
1875
|
-
return {
|
|
1876
|
-
line: point.line + lineDelta,
|
|
1877
|
-
column: point.column,
|
|
1878
|
-
offset: point.offset !== void 0 ? point.offset + offsetDelta : void 0
|
|
1879
|
-
};
|
|
1683
|
+
return false;
|
|
1880
1684
|
}
|
|
1685
|
+
|
|
1686
|
+
// src/components/incrementalParse/prefixAlignment.ts
|
|
1881
1687
|
function isWrapInvisible(node) {
|
|
1882
1688
|
return node.type === "definition" || node.type === "footnoteDefinition";
|
|
1883
1689
|
}
|
|
@@ -2019,96 +1825,303 @@ function stripInjectedHast(tailMdast, tailHast, injectedLen, tailWrapVisible) {
|
|
|
2019
1825
|
idx += 1;
|
|
2020
1826
|
continue;
|
|
2021
1827
|
}
|
|
2022
|
-
const start = node.position?.start?.offset;
|
|
2023
|
-
if (start === void 0 || start >= injectedLen) return null;
|
|
2024
|
-
consumed += 1;
|
|
2025
|
-
idx += 1;
|
|
1828
|
+
const start = node.position?.start?.offset;
|
|
1829
|
+
if (start === void 0 || start >= injectedLen) return null;
|
|
1830
|
+
consumed += 1;
|
|
1831
|
+
idx += 1;
|
|
1832
|
+
}
|
|
1833
|
+
if (consumed < injectedVisibleCount) return null;
|
|
1834
|
+
let remnant = "";
|
|
1835
|
+
let remnantMerged = null;
|
|
1836
|
+
if (tailWrapVisible) {
|
|
1837
|
+
const gap = children[idx];
|
|
1838
|
+
if (!gap || !isSeparatorText(gap)) return null;
|
|
1839
|
+
remnant = gap.value.slice(1);
|
|
1840
|
+
remnantMerged = remnant !== "";
|
|
1841
|
+
idx += 1;
|
|
1842
|
+
}
|
|
1843
|
+
const rest = children.slice(idx);
|
|
1844
|
+
if (remnant !== "") rest.unshift({ type: "text", value: remnant });
|
|
1845
|
+
return { rest, remnantMerged };
|
|
1846
|
+
}
|
|
1847
|
+
function tailLeadingTextIsHoist(tailMdastChildren, tailHastChildren) {
|
|
1848
|
+
const firstText = tailHastChildren[0];
|
|
1849
|
+
const firstVisible = tailMdastChildren.find((c) => !isWrapInvisible(c));
|
|
1850
|
+
if (firstVisible?.type === "html" && STRAY_SYNTHESIZED_END_TAG_RE.test(firstVisible.value)) return null;
|
|
1851
|
+
if (!firstText) return false;
|
|
1852
|
+
if (!isSeparatorText(firstText)) {
|
|
1853
|
+
if (firstText.type === "text" && firstText.position === void 0 && firstVisible?.type === "html") {
|
|
1854
|
+
if (/^\s*<\/[A-Za-z][A-Za-z0-9-]*\s*>/.test(firstVisible.value)) return true;
|
|
1855
|
+
if (isSanitizeStrippedConstruct(firstVisible.value)) return false;
|
|
1856
|
+
return null;
|
|
1857
|
+
}
|
|
1858
|
+
return false;
|
|
1859
|
+
}
|
|
1860
|
+
if (!firstVisible) return false;
|
|
1861
|
+
const firstContent = tailHastChildren.find((c) => !isSeparatorText(c));
|
|
1862
|
+
if (firstContent) {
|
|
1863
|
+
const start = firstContent.position?.start?.offset;
|
|
1864
|
+
const vStart = firstVisible.position?.start?.offset;
|
|
1865
|
+
const vEnd = firstVisible.position?.end?.offset;
|
|
1866
|
+
if (start !== void 0 && vStart !== void 0 && vEnd !== void 0) {
|
|
1867
|
+
if (start >= vStart && start < vEnd) return true;
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
if (firstVisible.type === "math") return false;
|
|
1871
|
+
if (firstVisible.type === "html" && isSanitizeStrippedConstruct(firstVisible.value)) return false;
|
|
1872
|
+
return null;
|
|
1873
|
+
}
|
|
1874
|
+
function isSeparatorText(node) {
|
|
1875
|
+
return node.type === "text" && node.position === void 0 && node.value.trim() === "";
|
|
1876
|
+
}
|
|
1877
|
+
function ownsTrailingLiteral(el, literal, prefixMdast) {
|
|
1878
|
+
const start = el.position?.start?.offset;
|
|
1879
|
+
if (start === void 0) return false;
|
|
1880
|
+
const owner = prefixMdast.find((c) => c.type === "html" && c.position?.start?.offset === start);
|
|
1881
|
+
if (!owner || owner.type !== "html") return false;
|
|
1882
|
+
const text = literal.value.trim();
|
|
1883
|
+
return text !== "" && owner.value.trimEnd().endsWith(text);
|
|
1884
|
+
}
|
|
1885
|
+
function isTrailingLiteralText(node) {
|
|
1886
|
+
return node.type === "text" && node.position === void 0 && node.value.trim() !== "";
|
|
1887
|
+
}
|
|
1888
|
+
function countTrailingNewlines(value) {
|
|
1889
|
+
let n = 0;
|
|
1890
|
+
for (let i = value.length - 1; i >= 0 && value[i] === "\n"; i--) n += 1;
|
|
1891
|
+
return n;
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1894
|
+
// src/components/incrementalParse/prefixInjection.ts
|
|
1895
|
+
var import_micromark_util_normalize_identifier2 = require("micromark-util-normalize-identifier");
|
|
1896
|
+
function collectPrefixInjection(mdast, content, boundary, resume) {
|
|
1897
|
+
const resumeValid = resume != null && resume.boundary <= boundary;
|
|
1898
|
+
if (resumeValid && resume.uninjectable) return { events: resume.events, uninjectable: true };
|
|
1899
|
+
const resumeAt = resumeValid ? resume.boundary : 0;
|
|
1900
|
+
const events = resumeAt > 0 ? cloneEventsForAppend(resume.events) : [];
|
|
1901
|
+
let uninjectable = false;
|
|
1902
|
+
let cacheable = true;
|
|
1903
|
+
const pushRef = (token) => {
|
|
1904
|
+
const last = events[events.length - 1];
|
|
1905
|
+
if (last && last.kind === "refs") last.tokens.push(token);
|
|
1906
|
+
else events.push({ kind: "refs", tokens: [token] });
|
|
1907
|
+
};
|
|
1908
|
+
const visit7 = (node, nested) => {
|
|
1909
|
+
const type = node.type;
|
|
1910
|
+
if (type === "definition") {
|
|
1911
|
+
const start = node.position?.start?.offset;
|
|
1912
|
+
const end = node.position?.end?.offset;
|
|
1913
|
+
if (start !== void 0 && end !== void 0 && start < boundary) {
|
|
1914
|
+
const slice = content.slice(start, end);
|
|
1915
|
+
if (nested && slice.includes("\n")) uninjectable = true;
|
|
1916
|
+
else events.push({ kind: "def", source: slice });
|
|
1917
|
+
}
|
|
1918
|
+
return;
|
|
1919
|
+
}
|
|
1920
|
+
if (type === "footnoteDefinition") {
|
|
1921
|
+
const start = node.position?.start;
|
|
1922
|
+
const end = node.position?.end?.offset;
|
|
1923
|
+
if (start?.offset === void 0 || end === void 0 || start.offset >= boundary) return;
|
|
1924
|
+
if (nested) {
|
|
1925
|
+
uninjectable = true;
|
|
1926
|
+
return;
|
|
1927
|
+
}
|
|
1928
|
+
const lineStart = start.offset - (start.column - 1);
|
|
1929
|
+
events.push({
|
|
1930
|
+
kind: "footnoteDef",
|
|
1931
|
+
source: content.slice(lineStart, end),
|
|
1932
|
+
origStart: lineStart,
|
|
1933
|
+
origLine: start.line
|
|
1934
|
+
});
|
|
1935
|
+
return;
|
|
1936
|
+
}
|
|
1937
|
+
if (type === "footnoteReference") {
|
|
1938
|
+
const start = node.position?.start?.offset;
|
|
1939
|
+
const end = node.position?.end?.offset;
|
|
1940
|
+
if (start === void 0 || end === void 0) {
|
|
1941
|
+
uninjectable = true;
|
|
1942
|
+
return;
|
|
1943
|
+
}
|
|
1944
|
+
pushRef(content.slice(start, end));
|
|
1945
|
+
return;
|
|
1946
|
+
}
|
|
1947
|
+
const children = node.children;
|
|
1948
|
+
if (children) {
|
|
1949
|
+
for (const child of children) visit7(child, true);
|
|
1950
|
+
}
|
|
1951
|
+
};
|
|
1952
|
+
let lastStart = -1;
|
|
1953
|
+
for (const child of mdast.children) {
|
|
1954
|
+
const start = child.position?.start?.offset;
|
|
1955
|
+
if (start !== void 0) {
|
|
1956
|
+
if (start < lastStart) return { events: [], uninjectable: true, cacheable: false };
|
|
1957
|
+
lastStart = start;
|
|
1958
|
+
}
|
|
1959
|
+
if (start === void 0) {
|
|
1960
|
+
if (resumeAt > 0) return collectPrefixInjection(mdast, content, boundary, null);
|
|
1961
|
+
cacheable = false;
|
|
1962
|
+
visit7(child, false);
|
|
1963
|
+
continue;
|
|
1964
|
+
}
|
|
1965
|
+
if (start >= boundary || start < resumeAt) continue;
|
|
1966
|
+
visit7(child, false);
|
|
1967
|
+
}
|
|
1968
|
+
return { events, uninjectable, cacheable };
|
|
1969
|
+
}
|
|
1970
|
+
function cloneEventsForAppend(events) {
|
|
1971
|
+
const out = events.slice();
|
|
1972
|
+
const last = out[out.length - 1];
|
|
1973
|
+
if (last && last.kind === "refs") out[out.length - 1] = { kind: "refs", tokens: last.tokens.slice() };
|
|
1974
|
+
return out;
|
|
1975
|
+
}
|
|
1976
|
+
var TERMINATOR_LABEL = "__aimd_injection_terminator__";
|
|
1977
|
+
var INJECTION_TERMINATOR = `[${TERMINATOR_LABEL}]: __aimd_sentinel_link__`;
|
|
1978
|
+
function tailMentionsTerminator(tailSource) {
|
|
1979
|
+
return (0, import_micromark_util_normalize_identifier2.normalizeIdentifier)(tailSource).replace(/\[ /g, "[").includes(`[${(0, import_micromark_util_normalize_identifier2.normalizeIdentifier)(TERMINATOR_LABEL)}`);
|
|
1980
|
+
}
|
|
1981
|
+
function buildInjectionPrefix(events) {
|
|
1982
|
+
if (events.length === 0) return { text: "", segments: [] };
|
|
1983
|
+
let text = "";
|
|
1984
|
+
let line = 1;
|
|
1985
|
+
const segments = [];
|
|
1986
|
+
for (const event of events) {
|
|
1987
|
+
if (text.length > 0) {
|
|
1988
|
+
text += "\n\n";
|
|
1989
|
+
line += 2;
|
|
1990
|
+
}
|
|
1991
|
+
const injStart = text.length;
|
|
1992
|
+
const source = event.kind === "refs" ? event.tokens.join(" ") : event.source;
|
|
1993
|
+
if (event.kind === "footnoteDef") {
|
|
1994
|
+
segments.push({
|
|
1995
|
+
injStart,
|
|
1996
|
+
injEnd: injStart + source.length,
|
|
1997
|
+
offsetDelta: event.origStart - injStart,
|
|
1998
|
+
lineDelta: event.origLine - line
|
|
1999
|
+
});
|
|
2000
|
+
}
|
|
2001
|
+
text += source;
|
|
2002
|
+
line += countNewlines(source);
|
|
2003
|
+
}
|
|
2004
|
+
return { text: `${text}
|
|
2005
|
+
|
|
2006
|
+
${INJECTION_TERMINATOR}
|
|
2007
|
+
|
|
2008
|
+
`, segments };
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
// src/components/incrementalParse/spliceParse.ts
|
|
2012
|
+
function spliceTrees(input) {
|
|
2013
|
+
const { prevMdast, prevHast, tailMdast, tailHast, content, boundary, injectionPrefix, injectedSegments } = input;
|
|
2014
|
+
const injectedLen = injectionPrefix.length;
|
|
2015
|
+
const injectedLines = countNewlines(injectionPrefix);
|
|
2016
|
+
const prefixLines = countNewlines(content, boundary);
|
|
2017
|
+
const offsetDelta = boundary - injectedLen;
|
|
2018
|
+
const lineDelta = prefixLines - injectedLines;
|
|
2019
|
+
const prefixMdast = [];
|
|
2020
|
+
for (const child of prevMdast.children) {
|
|
2021
|
+
const start = child.position?.start?.offset;
|
|
2022
|
+
if (start !== void 0 && start < boundary) prefixMdast.push(child);
|
|
2023
|
+
}
|
|
2024
|
+
const attrs = attributeHastChildren(prevMdast, prevHast, boundary);
|
|
2025
|
+
const cutRegion = [];
|
|
2026
|
+
for (let i = 0; i < prevHast.children.length; i++) {
|
|
2027
|
+
if (attrs[i] < boundary) {
|
|
2028
|
+
const node2 = prevHast.children[i];
|
|
2029
|
+
const end = node2.position?.end?.offset;
|
|
2030
|
+
if (end !== void 0 && end > boundary) return null;
|
|
2031
|
+
if (isTrailingLiteralText(node2)) {
|
|
2032
|
+
const prev = i > 0 ? prevHast.children[i - 1] : void 0;
|
|
2033
|
+
if (!prev || prev.type !== "element" || prev.position === void 0) return null;
|
|
2034
|
+
if (!ownsTrailingLiteral(prev, node2, prefixMdast))
|
|
2035
|
+
return null;
|
|
2036
|
+
}
|
|
2037
|
+
cutRegion.push(node2);
|
|
2038
|
+
continue;
|
|
2039
|
+
}
|
|
2040
|
+
const node = prevHast.children[i];
|
|
2041
|
+
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
|
|
2042
|
+
// raw literal can only trail an `html` mdast node. A position-less
|
|
2043
|
+
// text after a `<p>` is the NEXT block's remnant — a stray end tag
|
|
2044
|
+
// (`</t>\na`) parse5 dropped, whose text merged with the wrap
|
|
2045
|
+
// separator — owned by the tail, which re-parses it; freezing it
|
|
2046
|
+
// here duplicated it (v2.4.0 review P3). Falls through to the
|
|
2047
|
+
// remnant look-ahead below, which bails to a full parse. And the
|
|
2048
|
+
// literal must really be THAT block's trailing text: the block's raw
|
|
2049
|
+
// source ends with it. A dropped-tag block right after a frozen html
|
|
2050
|
+
// element (`</details>\n\n</t>\ntext`) puts its remnant in the same
|
|
2051
|
+
// position, and freezing it duplicated it (release soak of the fix).
|
|
2052
|
+
ownsTrailingLiteral(prevHast.children[i - 1], node, prefixMdast)) {
|
|
2053
|
+
cutRegion.push(node);
|
|
2054
|
+
break;
|
|
2055
|
+
}
|
|
2056
|
+
for (let j = i; j < prevHast.children.length; j++) {
|
|
2057
|
+
const look = prevHast.children[j];
|
|
2058
|
+
if (look.type === "element" || look.position !== void 0) break;
|
|
2059
|
+
if (isTrailingLiteralText(look)) return null;
|
|
2060
|
+
}
|
|
2061
|
+
break;
|
|
2026
2062
|
}
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2063
|
+
const tailMdastChildren = tailMdast.children.filter((child) => {
|
|
2064
|
+
const start = child.position?.start?.offset;
|
|
2065
|
+
return !(start !== void 0 && start < injectedLen);
|
|
2066
|
+
});
|
|
2067
|
+
const tailWrapVisible = tailMdastChildren.some((child) => !isWrapInvisible(child));
|
|
2068
|
+
const prefixHtmlValues = prefixMdast.flatMap((c) => c.type === "html" ? [c.value] : []);
|
|
2069
|
+
if (hasStrayTablePart(prefixHtmlValues)) return null;
|
|
2070
|
+
if (rawTextRegionCrossesOut(prefixHtmlValues)) return null;
|
|
2071
|
+
const leadingHtml = [];
|
|
2072
|
+
for (const child of tailMdastChildren) {
|
|
2073
|
+
if (isWrapInvisible(child)) continue;
|
|
2074
|
+
if (child.type !== "html") break;
|
|
2075
|
+
if (STRAY_SYNTHESIZED_END_TAG_RE.test(child.value) || TABLE_PART_TAG_RE.test(child.value)) return null;
|
|
2076
|
+
leadingHtml.push(child.value);
|
|
2036
2077
|
}
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
const
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2078
|
+
if (headRoutedCaptureUnclosed(leadingHtml)) return null;
|
|
2079
|
+
const aligned = alignPrefixCut(prefixMdast, cutRegion, tailWrapVisible);
|
|
2080
|
+
if (aligned === null) return null;
|
|
2081
|
+
const hastChildren = aligned.children;
|
|
2082
|
+
const interiorFinalLiteral = aligned.interiorFinalLiteral;
|
|
2083
|
+
const stripResult = stripInjectedHast(tailMdast, tailHast, injectedLen, tailWrapVisible);
|
|
2084
|
+
if (stripResult === null) return null;
|
|
2085
|
+
const strippedTailHast = stripResult.rest;
|
|
2086
|
+
for (const child of tailMdastChildren) rebaseTree(child, offsetDelta, lineDelta);
|
|
2087
|
+
for (const child of strippedTailHast) rebaseTreeDual(child, injectedSegments, offsetDelta, lineDelta);
|
|
2088
|
+
const mdastChildren = prefixMdast.concat(tailMdastChildren);
|
|
2089
|
+
const seamMergeVerdict = stripResult.remnantMerged ?? tailLeadingTextIsHoist(tailMdastChildren, strippedTailHast);
|
|
2090
|
+
if (seamMergeVerdict === null) return null;
|
|
2091
|
+
const seamMergeAllowed = seamMergeVerdict;
|
|
2092
|
+
let firstTailChild = true;
|
|
2093
|
+
for (const child of strippedTailHast) {
|
|
2094
|
+
const tailEnd = hastChildren[hastChildren.length - 1];
|
|
2095
|
+
if (firstTailChild && child.type === "text" && child.position !== void 0) {
|
|
2050
2096
|
return null;
|
|
2051
2097
|
}
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2098
|
+
if (firstTailChild && tailEnd && tailEnd.type === "text" && child.type === "text" && child.position === void 0) {
|
|
2099
|
+
if (interiorFinalLiteral && tailEnd.value.trim() !== "") {
|
|
2100
|
+
if (seamMergeAllowed) return null;
|
|
2101
|
+
firstTailChild = false;
|
|
2102
|
+
hastChildren.push(child);
|
|
2103
|
+
continue;
|
|
2104
|
+
}
|
|
2105
|
+
const literalSeam = tailEnd.value.trim() !== "" && !tailWrapVisible;
|
|
2106
|
+
if (seamMergeAllowed || literalSeam) {
|
|
2107
|
+
hastChildren[hastChildren.length - 1] = { type: "text", value: tailEnd.value + child.value };
|
|
2108
|
+
firstTailChild = false;
|
|
2109
|
+
continue;
|
|
2110
|
+
}
|
|
2062
2111
|
}
|
|
2112
|
+
firstTailChild = false;
|
|
2113
|
+
hastChildren.push(child);
|
|
2063
2114
|
}
|
|
2064
|
-
if (
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
if (value.length < 7 || !value.endsWith("-->")) return false;
|
|
2075
|
-
const close = value.indexOf("-->", 4);
|
|
2076
|
-
const bangClose = value.indexOf("--!>", 4);
|
|
2077
|
-
if (close !== value.length - 3) return false;
|
|
2078
|
-
return bangClose === -1 || bangClose > close;
|
|
2079
|
-
}
|
|
2080
|
-
if (/^<!doctype/i.test(value)) return false;
|
|
2081
|
-
if (value.startsWith("<?") || /^<!(?:[A-Za-z]|\[CDATA\[)/.test(value)) {
|
|
2082
|
-
return value.indexOf(">") === value.length - 1;
|
|
2083
|
-
}
|
|
2084
|
-
return false;
|
|
2085
|
-
}
|
|
2086
|
-
function isSeparatorText(node) {
|
|
2087
|
-
return node.type === "text" && node.position === void 0 && node.value.trim() === "";
|
|
2088
|
-
}
|
|
2089
|
-
function ownsTrailingLiteral(el, literal, prefixMdast) {
|
|
2090
|
-
const start = el.position?.start?.offset;
|
|
2091
|
-
if (start === void 0) return false;
|
|
2092
|
-
const owner = prefixMdast.find((c) => c.type === "html" && c.position?.start?.offset === start);
|
|
2093
|
-
if (!owner || owner.type !== "html") return false;
|
|
2094
|
-
const text = literal.value.trim();
|
|
2095
|
-
return text !== "" && owner.value.trimEnd().endsWith(text);
|
|
2096
|
-
}
|
|
2097
|
-
function isTrailingLiteralText(node) {
|
|
2098
|
-
return node.type === "text" && node.position === void 0 && node.value.trim() !== "";
|
|
2099
|
-
}
|
|
2100
|
-
function countTrailingNewlines(value) {
|
|
2101
|
-
let n = 0;
|
|
2102
|
-
for (let i = value.length - 1; i >= 0 && value[i] === "\n"; i--) n += 1;
|
|
2103
|
-
return n;
|
|
2104
|
-
}
|
|
2105
|
-
function countNewlines(text, end = text.length) {
|
|
2106
|
-
let count = 0;
|
|
2107
|
-
for (let i = text.indexOf("\n"); i !== -1 && i < end; i = text.indexOf("\n", i + 1)) count += 1;
|
|
2108
|
-
for (let i = text.indexOf("\r"); i !== -1 && i < end; i = text.indexOf("\r", i + 1)) {
|
|
2109
|
-
if (text.charCodeAt(i + 1) !== 10) count += 1;
|
|
2110
|
-
}
|
|
2111
|
-
return count;
|
|
2115
|
+
if (!hastChildren.some((child) => child.position !== void 0)) return null;
|
|
2116
|
+
const docStart = { line: 1, column: 1, offset: 0 };
|
|
2117
|
+
const mdastRootPosition = tailMdast.position ? { start: docStart, end: rebasePoint(tailMdast.position.end, offsetDelta, lineDelta) } : prevMdast.position;
|
|
2118
|
+
const hastRootPosition = mdastRootPosition;
|
|
2119
|
+
const mdast = { type: "root", children: mdastChildren };
|
|
2120
|
+
if (mdastRootPosition) mdast.position = mdastRootPosition;
|
|
2121
|
+
const hast = { type: "root", children: hastChildren };
|
|
2122
|
+
if (hastRootPosition) hast.position = hastRootPosition;
|
|
2123
|
+
if (prevHast.data !== void 0) hast.data = prevHast.data;
|
|
2124
|
+
return { mdast, hast };
|
|
2112
2125
|
}
|
|
2113
2126
|
|
|
2114
2127
|
// src/components/incrementalParse/advanceIncrementalParse.ts
|
|
@@ -2230,6 +2243,38 @@ function normalizeForMatch(s) {
|
|
|
2230
2243
|
return (0, import_micromark_util_normalize_identifier3.normalizeIdentifier)(s);
|
|
2231
2244
|
}
|
|
2232
2245
|
|
|
2246
|
+
// src/components/blankLineScanner.ts
|
|
2247
|
+
function createBlankLineScanner() {
|
|
2248
|
+
let end = 0;
|
|
2249
|
+
let newline = false;
|
|
2250
|
+
let cr = false;
|
|
2251
|
+
return (source, from = 0) => {
|
|
2252
|
+
if (from === 0) {
|
|
2253
|
+
end = 0;
|
|
2254
|
+
newline = false;
|
|
2255
|
+
cr = false;
|
|
2256
|
+
}
|
|
2257
|
+
for (let i = from; i < source.length; i++) {
|
|
2258
|
+
const c = source[i];
|
|
2259
|
+
if (c === "\n") {
|
|
2260
|
+
if (newline) {
|
|
2261
|
+
end = i + 1;
|
|
2262
|
+
newline = false;
|
|
2263
|
+
} else newline = true;
|
|
2264
|
+
cr = false;
|
|
2265
|
+
} else if (newline) {
|
|
2266
|
+
if ((c === " " || c === " ") && !cr) continue;
|
|
2267
|
+
if (c === "\r" && !cr) cr = true;
|
|
2268
|
+
else {
|
|
2269
|
+
newline = false;
|
|
2270
|
+
cr = false;
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
}
|
|
2274
|
+
return end;
|
|
2275
|
+
};
|
|
2276
|
+
}
|
|
2277
|
+
|
|
2233
2278
|
// src/components/collectDefLabels.ts
|
|
2234
2279
|
var SCANNER_BOUNDARY_PROFILE = { defListEnabled: false, mathFlow: false, referenceTaint: false };
|
|
2235
2280
|
function buildProcessor() {
|
|
@@ -2261,19 +2306,12 @@ var setsEqual = (a, b) => {
|
|
|
2261
2306
|
for (const v of a) if (!b.has(v)) return false;
|
|
2262
2307
|
return true;
|
|
2263
2308
|
};
|
|
2264
|
-
var BLANK_LINE_RE = /\r?\n[ \t]*\r?\n/g;
|
|
2265
|
-
function lastRegionStart(source) {
|
|
2266
|
-
BLANK_LINE_RE.lastIndex = 0;
|
|
2267
|
-
let start = 0;
|
|
2268
|
-
for (let m = BLANK_LINE_RE.exec(source); m !== null; m = BLANK_LINE_RE.exec(source)) {
|
|
2269
|
-
start = m.index + m[0].length;
|
|
2270
|
-
}
|
|
2271
|
-
return start;
|
|
2272
|
-
}
|
|
2273
2309
|
var DEF_LINE_START_RE = /^[ \t>*+\d.)-]*\[(?:[^\]\\]|\\[\s\S])*\]:/m;
|
|
2274
2310
|
function createDefLabelScanner(parse = collectDefLabels) {
|
|
2275
2311
|
let prevSource = null;
|
|
2276
2312
|
let prevLabels = null;
|
|
2313
|
+
const scanBlankLines = createBlankLineScanner();
|
|
2314
|
+
let regionStart = 0;
|
|
2277
2315
|
let frozenEnd = 0;
|
|
2278
2316
|
let frozenFootnotes = /* @__PURE__ */ new Set();
|
|
2279
2317
|
let frozenLinks = /* @__PURE__ */ new Set();
|
|
@@ -2286,13 +2324,16 @@ function createDefLabelScanner(parse = collectDefLabels) {
|
|
|
2286
2324
|
};
|
|
2287
2325
|
return {
|
|
2288
2326
|
scan(source) {
|
|
2327
|
+
if (source === prevSource && prevLabels !== null) return prevLabels;
|
|
2328
|
+
const previousRegionStart = regionStart;
|
|
2329
|
+
const appended = prevSource !== null && source.startsWith(prevSource);
|
|
2330
|
+
regionStart = scanBlankLines(source, appended ? prevSource.length : 0);
|
|
2289
2331
|
let isAppend = false;
|
|
2290
2332
|
if (prevSource !== null && prevLabels !== null) {
|
|
2291
2333
|
if (source === prevSource) return prevLabels;
|
|
2292
2334
|
if (source.startsWith(prevSource)) {
|
|
2293
2335
|
isAppend = true;
|
|
2294
|
-
const
|
|
2295
|
-
const region = prevSource.slice(regionStart) + source.slice(prevSource.length);
|
|
2336
|
+
const region = source.slice(previousRegionStart);
|
|
2296
2337
|
if (!DEF_LINE_START_RE.test(region)) {
|
|
2297
2338
|
prevSource = source;
|
|
2298
2339
|
return prevLabels;
|
|
@@ -2525,8 +2566,115 @@ function* extractContributions(mdast, options = {}) {
|
|
|
2525
2566
|
for (const c of out) yield c;
|
|
2526
2567
|
}
|
|
2527
2568
|
|
|
2569
|
+
// src/components/registryIndex.ts
|
|
2570
|
+
function buildRegistryIndex(registry) {
|
|
2571
|
+
const index = {
|
|
2572
|
+
footnotes: /* @__PURE__ */ new Map(),
|
|
2573
|
+
links: /* @__PURE__ */ new Map(),
|
|
2574
|
+
numbers: /* @__PURE__ */ new Map(),
|
|
2575
|
+
counts: /* @__PURE__ */ new Map(),
|
|
2576
|
+
occurrences: /* @__PURE__ */ new Map(),
|
|
2577
|
+
labelOccurrences: /* @__PURE__ */ new Map()
|
|
2578
|
+
};
|
|
2579
|
+
for (const sym of registry.chunkOrder) {
|
|
2580
|
+
const data = registry.chunkData.get(sym);
|
|
2581
|
+
if (!data) continue;
|
|
2582
|
+
for (const label of data.defs.keys()) if (!index.footnotes.has(label)) index.footnotes.set(label, sym);
|
|
2583
|
+
for (const label of data.linkDefs.keys()) if (!index.links.has(label)) index.links.set(label, sym);
|
|
2584
|
+
const local = /* @__PURE__ */ new Map();
|
|
2585
|
+
index.occurrences.set(sym, local);
|
|
2586
|
+
for (const ref of data.refs) {
|
|
2587
|
+
if (ref.kind !== "footnote") continue;
|
|
2588
|
+
const label = ref.label;
|
|
2589
|
+
if (!index.numbers.has(label)) index.numbers.set(label, index.numbers.size + 1);
|
|
2590
|
+
const total = (index.counts.get(label) ?? 0) + 1;
|
|
2591
|
+
index.counts.set(label, total);
|
|
2592
|
+
const prior = local.get(label);
|
|
2593
|
+
if (prior) prior.count++;
|
|
2594
|
+
else {
|
|
2595
|
+
const range = { start: total, count: 1 };
|
|
2596
|
+
local.set(label, range);
|
|
2597
|
+
let byChunk = index.labelOccurrences.get(label);
|
|
2598
|
+
if (!byChunk) index.labelOccurrences.set(label, byChunk = /* @__PURE__ */ new Map());
|
|
2599
|
+
byChunk.set(sym, range);
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
return index;
|
|
2604
|
+
}
|
|
2605
|
+
|
|
2606
|
+
// src/components/registrySubscriptions.ts
|
|
2607
|
+
function equal(a, b) {
|
|
2608
|
+
if (a.owner !== b.owner || a.url !== b.url || a.title !== b.title || a.number !== b.number || a.count !== b.count)
|
|
2609
|
+
return false;
|
|
2610
|
+
if (a.occurrences?.size !== b.occurrences?.size) return false;
|
|
2611
|
+
if (a.occurrences) {
|
|
2612
|
+
for (const [chunk, range] of a.occurrences) {
|
|
2613
|
+
const next = b.occurrences?.get(chunk);
|
|
2614
|
+
if (!next || next.start !== range.start || next.count !== range.count) return false;
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
return true;
|
|
2618
|
+
}
|
|
2619
|
+
function createRegistrySubscriptions(read) {
|
|
2620
|
+
const groups = { link: /* @__PURE__ */ new Map(), footnote: /* @__PURE__ */ new Map() };
|
|
2621
|
+
const snapshot = (kind, label, { registry, index }) => {
|
|
2622
|
+
if (kind === "link") {
|
|
2623
|
+
const owner = index.links.get(label);
|
|
2624
|
+
const def = owner ? registry.chunkData.get(owner)?.linkDefs.get(label) : void 0;
|
|
2625
|
+
return { owner, url: def?.url, title: def?.title };
|
|
2626
|
+
}
|
|
2627
|
+
return {
|
|
2628
|
+
owner: index.footnotes.get(label),
|
|
2629
|
+
number: index.numbers.get(label),
|
|
2630
|
+
count: index.counts.get(label),
|
|
2631
|
+
occurrences: index.labelOccurrences.get(label)
|
|
2632
|
+
};
|
|
2633
|
+
};
|
|
2634
|
+
return {
|
|
2635
|
+
subscribe(kind, rawLabel, cb) {
|
|
2636
|
+
const label = normalizeId(rawLabel);
|
|
2637
|
+
const map = groups[kind];
|
|
2638
|
+
let group = map.get(label);
|
|
2639
|
+
if (!group) {
|
|
2640
|
+
group = { snapshot: snapshot(kind, label, read()), listeners: /* @__PURE__ */ new Set() };
|
|
2641
|
+
map.set(label, group);
|
|
2642
|
+
}
|
|
2643
|
+
const listener = () => cb();
|
|
2644
|
+
group.listeners.add(listener);
|
|
2645
|
+
return () => {
|
|
2646
|
+
group.listeners.delete(listener);
|
|
2647
|
+
if (group.listeners.size === 0 && map.get(label) === group) map.delete(label);
|
|
2648
|
+
};
|
|
2649
|
+
},
|
|
2650
|
+
collect() {
|
|
2651
|
+
if (groups.link.size === 0 && groups.footnote.size === 0) return [];
|
|
2652
|
+
const state = read();
|
|
2653
|
+
const callbacks = [];
|
|
2654
|
+
for (const kind of ["link", "footnote"]) {
|
|
2655
|
+
for (const [label, group] of groups[kind]) {
|
|
2656
|
+
const next = snapshot(kind, label, state);
|
|
2657
|
+
if (!equal(group.snapshot, next)) callbacks.push(...group.listeners);
|
|
2658
|
+
group.snapshot = next;
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
return callbacks;
|
|
2662
|
+
}
|
|
2663
|
+
};
|
|
2664
|
+
}
|
|
2665
|
+
|
|
2528
2666
|
// src/components/documentRegistry.ts
|
|
2529
2667
|
function createRegistry(onEmpty) {
|
|
2668
|
+
let index;
|
|
2669
|
+
let indexedVersion = -1;
|
|
2670
|
+
const getIndex = () => {
|
|
2671
|
+
if (!index || indexedVersion !== reg.version) {
|
|
2672
|
+
index = buildRegistryIndex(reg);
|
|
2673
|
+
indexedVersion = reg.version;
|
|
2674
|
+
}
|
|
2675
|
+
return index;
|
|
2676
|
+
};
|
|
2677
|
+
const labels = createRegistrySubscriptions(() => ({ registry: reg, index: getIndex() }));
|
|
2530
2678
|
const reg = {
|
|
2531
2679
|
chunkOrder: [],
|
|
2532
2680
|
chunkData: /* @__PURE__ */ new Map(),
|
|
@@ -2677,73 +2825,29 @@ function createRegistry(onEmpty) {
|
|
|
2677
2825
|
this._subscribers.delete(cb);
|
|
2678
2826
|
};
|
|
2679
2827
|
},
|
|
2828
|
+
subscribeLabel(kind, label, cb) {
|
|
2829
|
+
return labels.subscribe(kind, label, cb);
|
|
2830
|
+
},
|
|
2680
2831
|
canonicalFootnoteFor(label) {
|
|
2681
|
-
|
|
2682
|
-
for (const sym of this.chunkOrder) {
|
|
2683
|
-
const data = this.chunkData.get(sym);
|
|
2684
|
-
if (data?.defs.has(id)) return sym;
|
|
2685
|
-
}
|
|
2686
|
-
return null;
|
|
2832
|
+
return getIndex().footnotes.get(normalizeId(label)) ?? null;
|
|
2687
2833
|
},
|
|
2688
2834
|
canonicalLinkFor(label) {
|
|
2689
|
-
|
|
2690
|
-
for (const sym of this.chunkOrder) {
|
|
2691
|
-
const data = this.chunkData.get(sym);
|
|
2692
|
-
if (data?.linkDefs.has(id)) return sym;
|
|
2693
|
-
}
|
|
2694
|
-
return null;
|
|
2835
|
+
return getIndex().links.get(normalizeId(label)) ?? null;
|
|
2695
2836
|
},
|
|
2696
2837
|
globalNumber(label) {
|
|
2697
|
-
|
|
2698
|
-
let n = 0;
|
|
2699
|
-
const seen = /* @__PURE__ */ new Set();
|
|
2700
|
-
for (const sym of this.chunkOrder) {
|
|
2701
|
-
const data = this.chunkData.get(sym);
|
|
2702
|
-
if (!data) continue;
|
|
2703
|
-
for (const ref of data.refs) {
|
|
2704
|
-
if (ref.kind !== "footnote") continue;
|
|
2705
|
-
if (!seen.has(ref.label)) {
|
|
2706
|
-
seen.add(ref.label);
|
|
2707
|
-
n++;
|
|
2708
|
-
if (ref.label === id) return n;
|
|
2709
|
-
}
|
|
2710
|
-
}
|
|
2711
|
-
}
|
|
2712
|
-
return null;
|
|
2838
|
+
return getIndex().numbers.get(normalizeId(label)) ?? null;
|
|
2713
2839
|
},
|
|
2714
2840
|
resolveLinkDef(label) {
|
|
2715
|
-
const
|
|
2716
|
-
|
|
2717
|
-
return this.chunkData.get(sym)?.linkDefs.get(
|
|
2841
|
+
const id = normalizeId(label);
|
|
2842
|
+
const sym = getIndex().links.get(id);
|
|
2843
|
+
return sym ? this.chunkData.get(sym)?.linkDefs.get(id) ?? null : null;
|
|
2718
2844
|
},
|
|
2719
2845
|
getRefsForLabel(label) {
|
|
2720
|
-
|
|
2721
|
-
let n = 0;
|
|
2722
|
-
for (const sym of this.chunkOrder) {
|
|
2723
|
-
const data = this.chunkData.get(sym);
|
|
2724
|
-
if (!data) continue;
|
|
2725
|
-
for (const ref of data.refs) {
|
|
2726
|
-
if (ref.kind === "footnote" && ref.label === id) n++;
|
|
2727
|
-
}
|
|
2728
|
-
}
|
|
2729
|
-
return n;
|
|
2846
|
+
return getIndex().counts.get(normalizeId(label)) ?? 0;
|
|
2730
2847
|
},
|
|
2731
2848
|
globalOccurrenceForRef(chunkSym, label, localOccurrence) {
|
|
2732
|
-
const
|
|
2733
|
-
|
|
2734
|
-
for (const sym of this.chunkOrder) {
|
|
2735
|
-
const data = this.chunkData.get(sym);
|
|
2736
|
-
if (!data) continue;
|
|
2737
|
-
let localCount = 0;
|
|
2738
|
-
for (const ref of data.refs) {
|
|
2739
|
-
if (ref.kind !== "footnote") continue;
|
|
2740
|
-
if (ref.label !== id) continue;
|
|
2741
|
-
localCount++;
|
|
2742
|
-
global2++;
|
|
2743
|
-
if (sym === chunkSym && localCount === localOccurrence) return global2;
|
|
2744
|
-
}
|
|
2745
|
-
}
|
|
2746
|
-
return null;
|
|
2849
|
+
const range = getIndex().occurrences.get(chunkSym)?.get(normalizeId(label));
|
|
2850
|
+
return range && Number.isInteger(localOccurrence) && localOccurrence > 0 && localOccurrence <= range.count ? range.start + localOccurrence - 1 : null;
|
|
2747
2851
|
},
|
|
2748
2852
|
_notify() {
|
|
2749
2853
|
this.version++;
|
|
@@ -2751,7 +2855,9 @@ function createRegistry(onEmpty) {
|
|
|
2751
2855
|
this._notifyScheduled = true;
|
|
2752
2856
|
queueMicrotask(() => {
|
|
2753
2857
|
this._notifyScheduled = false;
|
|
2858
|
+
const labelCallbacks = labels.collect();
|
|
2754
2859
|
for (const cb of [...this._subscribers]) cb();
|
|
2860
|
+
for (const cb of labelCallbacks) cb();
|
|
2755
2861
|
});
|
|
2756
2862
|
}
|
|
2757
2863
|
};
|
|
@@ -2808,7 +2914,7 @@ var ENGINE_PLACEHOLDER_TAGS = /* @__PURE__ */ new Set([
|
|
|
2808
2914
|
"cross-chunk-image"
|
|
2809
2915
|
]);
|
|
2810
2916
|
var ENGINE_PROVENANCE_PROPERTY = "engineProvenance";
|
|
2811
|
-
function walk(parent, provenance) {
|
|
2917
|
+
function walk(parent, provenance, ancestors) {
|
|
2812
2918
|
const children = parent.children;
|
|
2813
2919
|
let i = 0;
|
|
2814
2920
|
while (i < children.length) {
|
|
@@ -2819,21 +2925,32 @@ function walk(parent, provenance) {
|
|
|
2819
2925
|
const genuine = provenance !== "" && typeof stamped === "string" && stamped === provenance;
|
|
2820
2926
|
if (genuine) {
|
|
2821
2927
|
delete props[ENGINE_PROVENANCE_PROPERTY];
|
|
2822
|
-
|
|
2928
|
+
if (ancestors && (node.tagName === "cross-chunk-link" || node.tagName === "cross-chunk-image")) {
|
|
2929
|
+
(node.data ??= {}).referenceAncestors = ancestors.slice();
|
|
2930
|
+
}
|
|
2931
|
+
ancestors?.push(
|
|
2932
|
+
node.tagName === "cross-chunk-link" ? "a" : node.tagName === "cross-chunk-image" ? "img" : node.tagName
|
|
2933
|
+
);
|
|
2934
|
+
walk(node, provenance, ancestors);
|
|
2935
|
+
ancestors?.pop();
|
|
2823
2936
|
i += 1;
|
|
2824
2937
|
} else {
|
|
2825
2938
|
children.splice(i, 1, ...node.children);
|
|
2826
2939
|
}
|
|
2827
2940
|
continue;
|
|
2828
2941
|
}
|
|
2829
|
-
if (node.type === "element")
|
|
2942
|
+
if (node.type === "element") {
|
|
2943
|
+
ancestors?.push(node.tagName);
|
|
2944
|
+
walk(node, provenance, ancestors);
|
|
2945
|
+
ancestors?.pop();
|
|
2946
|
+
}
|
|
2830
2947
|
i += 1;
|
|
2831
2948
|
}
|
|
2832
2949
|
}
|
|
2833
2950
|
function rehypeVerifyEngineTags(options) {
|
|
2834
2951
|
const provenance = options?.provenance ?? "";
|
|
2835
2952
|
return function transformer(tree) {
|
|
2836
|
-
walk(tree, provenance);
|
|
2953
|
+
walk(tree, provenance, options?.referenceAncestors ? [] : void 0);
|
|
2837
2954
|
};
|
|
2838
2955
|
}
|
|
2839
2956
|
|
|
@@ -2854,16 +2971,18 @@ var import_remark_remove_comments = __toESM(require("remark-remove-comments"), 1
|
|
|
2854
2971
|
// src/components/rehypeRebaseHashLinks.ts
|
|
2855
2972
|
var import_unist_util_visit5 = require("unist-util-visit");
|
|
2856
2973
|
var DEFAULT_PREFIX = "user-content-";
|
|
2974
|
+
function rebaseHashHref(href, prefix) {
|
|
2975
|
+
const hashPrefix = "#" + prefix;
|
|
2976
|
+
return href.startsWith("#") && !href.startsWith(hashPrefix) ? hashPrefix + href.slice(1) : href;
|
|
2977
|
+
}
|
|
2857
2978
|
var rehypeRebaseHashLinks = (options) => {
|
|
2858
2979
|
const prefix = options?.prefix ?? DEFAULT_PREFIX;
|
|
2859
|
-
const hashPrefix = "#" + prefix;
|
|
2860
2980
|
return (tree) => {
|
|
2861
2981
|
(0, import_unist_util_visit5.visit)(tree, "element", (node) => {
|
|
2862
2982
|
if (node.tagName !== "a") return;
|
|
2863
2983
|
const href = node.properties?.href;
|
|
2864
2984
|
if (typeof href !== "string" || !href.startsWith("#")) return;
|
|
2865
|
-
|
|
2866
|
-
node.properties.href = hashPrefix + href.slice(1);
|
|
2985
|
+
node.properties.href = rebaseHashHref(href, prefix);
|
|
2867
2986
|
});
|
|
2868
2987
|
};
|
|
2869
2988
|
};
|
|
@@ -2949,7 +3068,15 @@ function buildCoreRehypePlugins(sanitizeSchema2, clobberPrefix, options) {
|
|
|
2949
3068
|
[import_rehype_raw.default, { passThrough: [] }],
|
|
2950
3069
|
// Unwrap forged engine placeholders BEFORE sanitize admits their tag
|
|
2951
3070
|
// names. Only when the caller holds a credential (see the option's doc).
|
|
2952
|
-
...options ? [
|
|
3071
|
+
...options ? [
|
|
3072
|
+
[
|
|
3073
|
+
rehypeVerifyEngineTags,
|
|
3074
|
+
{
|
|
3075
|
+
provenance: options.provenance,
|
|
3076
|
+
...sanitizeSchema2.ancestors?.a || sanitizeSchema2.ancestors?.img ? { referenceAncestors: true } : {}
|
|
3077
|
+
}
|
|
3078
|
+
]
|
|
3079
|
+
] : [],
|
|
2953
3080
|
// Sanitize HTML while allowing <mark> (highlight), KaTeX class names,
|
|
2954
3081
|
// and any extra protocols the caller permitted via the `sanitizeSchema`
|
|
2955
3082
|
// prop. Override `clobberPrefix` with the instance-scoped value — the
|
|
@@ -3023,11 +3150,9 @@ function buildCrossChunkHandlers() {
|
|
|
3023
3150
|
type: "element",
|
|
3024
3151
|
tagName: "cross-chunk-link",
|
|
3025
3152
|
properties: {
|
|
3026
|
-
//
|
|
3027
|
-
//
|
|
3028
|
-
|
|
3029
|
-
// which also preserves source case. Registry lookups normalize
|
|
3030
|
-
// internally, so cross-chunk case-insensitive matching still works.
|
|
3153
|
+
// Display labels decode escapes; registry identifiers must retain
|
|
3154
|
+
// those bytes. Never use the display label as the lookup key.
|
|
3155
|
+
identifier: node.identifier,
|
|
3031
3156
|
label: node.label ?? node.identifier,
|
|
3032
3157
|
referenceType: node.referenceType,
|
|
3033
3158
|
documentId: s.options.documentId,
|
|
@@ -3046,6 +3171,7 @@ function buildCrossChunkHandlers() {
|
|
|
3046
3171
|
type: "element",
|
|
3047
3172
|
tagName: "cross-chunk-image",
|
|
3048
3173
|
properties: {
|
|
3174
|
+
identifier: node.identifier,
|
|
3049
3175
|
label: node.label ?? node.identifier,
|
|
3050
3176
|
referenceType: node.referenceType,
|
|
3051
3177
|
alt: node.alt ?? "",
|
|
@@ -4308,8 +4434,8 @@ var sanitizeSchema = deepFreeze(
|
|
|
4308
4434
|
attributes: {
|
|
4309
4435
|
...import_rehype_sanitize2.defaultSchema.attributes,
|
|
4310
4436
|
code: mergeClassNameAllowlist(import_rehype_sanitize2.defaultSchema.attributes?.code, ["math-inline", "math-display"]),
|
|
4311
|
-
"cross-chunk-link": ["label", "referenceType", "documentId", "localUrl", "localTitle"],
|
|
4312
|
-
"cross-chunk-image": ["label", "referenceType", "documentId", "alt", "localUrl", "localTitle"],
|
|
4437
|
+
"cross-chunk-link": ["identifier", "label", "referenceType", "documentId", "localUrl", "localTitle"],
|
|
4438
|
+
"cross-chunk-image": ["identifier", "label", "referenceType", "documentId", "alt", "localUrl", "localTitle"],
|
|
4313
4439
|
"footnote-sup": ["label", "localOccurrence", "localNumber", "documentId"]
|
|
4314
4440
|
},
|
|
4315
4441
|
strip: [.../* @__PURE__ */ new Set([...import_rehype_sanitize2.defaultSchema.strip || [], ...STRIPPED_TAGS])]
|
|
@@ -4345,6 +4471,49 @@ function sanitizeCrossChunkUrl(rawUrl, key, tagName, urlTransform, schema) {
|
|
|
4345
4471
|
return String(transformed);
|
|
4346
4472
|
}
|
|
4347
4473
|
|
|
4474
|
+
// src/components/resolveCrossChunkReference.ts
|
|
4475
|
+
var import_rehype_sanitize3 = __toESM(require("rehype-sanitize"), 1);
|
|
4476
|
+
var import_micromark_util_sanitize_uri3 = require("micromark-util-sanitize-uri");
|
|
4477
|
+
function resolveCrossChunkReference(input, schema, urlTransform, clobberPrefix) {
|
|
4478
|
+
const key = input.tagName === "a" ? "href" : "src";
|
|
4479
|
+
const element = {
|
|
4480
|
+
type: "element",
|
|
4481
|
+
tagName: input.tagName,
|
|
4482
|
+
properties: {
|
|
4483
|
+
[key]: (0, import_micromark_util_sanitize_uri3.normalizeUri)(input.url),
|
|
4484
|
+
...input.tagName === "img" ? { alt: input.alt ?? "" } : {},
|
|
4485
|
+
...input.title !== void 0 ? { title: input.title } : {}
|
|
4486
|
+
},
|
|
4487
|
+
children: input.tagName === "a" ? [{ type: "text", value: "__reference_children__" }] : []
|
|
4488
|
+
};
|
|
4489
|
+
const requiredAncestors = schema.ancestors?.[input.tagName];
|
|
4490
|
+
const recordedAncestors = input.node?.data?.referenceAncestors;
|
|
4491
|
+
let finalSchema = schema;
|
|
4492
|
+
if (requiredAncestors && Array.isArray(recordedAncestors) && requiredAncestors.some((tag) => recordedAncestors.includes(tag))) {
|
|
4493
|
+
const ancestors = { ...schema.ancestors };
|
|
4494
|
+
delete ancestors[input.tagName];
|
|
4495
|
+
finalSchema = { ...schema, ancestors };
|
|
4496
|
+
}
|
|
4497
|
+
const root2 = (0, import_rehype_sanitize3.default)({ ...finalSchema, clobberPrefix })({ type: "root", children: [element] });
|
|
4498
|
+
const node = root2.children[0];
|
|
4499
|
+
if (node?.type !== "element") return { element: null, keepChildren: node?.type === "text" };
|
|
4500
|
+
if (node.tagName === "a" && typeof node.properties.href === "string") {
|
|
4501
|
+
node.properties.href = rebaseHashHref(node.properties.href, clobberPrefix);
|
|
4502
|
+
}
|
|
4503
|
+
node.children = input.node?.children ?? [];
|
|
4504
|
+
if (input.node?.position) node.position = input.node.position;
|
|
4505
|
+
buildTransform({
|
|
4506
|
+
allowedElements: void 0,
|
|
4507
|
+
disallowedElements: void 0,
|
|
4508
|
+
allowElement: void 0,
|
|
4509
|
+
skipHtml: void 0,
|
|
4510
|
+
unwrapDisallowed: void 0,
|
|
4511
|
+
urlTransform
|
|
4512
|
+
})(node, 0, root2);
|
|
4513
|
+
node.children = [];
|
|
4514
|
+
return { element: node, keepChildren: false };
|
|
4515
|
+
}
|
|
4516
|
+
|
|
4348
4517
|
// src/plugins/defs.ts
|
|
4349
4518
|
function getEnginePluginInternals(plugin) {
|
|
4350
4519
|
const candidate = plugin;
|
|
@@ -4561,6 +4730,8 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4561
4730
|
let source = "";
|
|
4562
4731
|
let visibleEnd = 0;
|
|
4563
4732
|
let pending = [];
|
|
4733
|
+
let pendingHead = 0;
|
|
4734
|
+
const pendingCount = () => pending.length - pendingHead;
|
|
4564
4735
|
let tentativeEnd = 0;
|
|
4565
4736
|
let finished = false;
|
|
4566
4737
|
let seam;
|
|
@@ -4605,7 +4776,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4605
4776
|
cancelFrame = void 0;
|
|
4606
4777
|
};
|
|
4607
4778
|
const ensureScheduled = () => {
|
|
4608
|
-
if (disposed || cancelFrame ||
|
|
4779
|
+
if (disposed || cancelFrame || pendingCount() === 0) return;
|
|
4609
4780
|
lastTickAt = now();
|
|
4610
4781
|
credit = 0;
|
|
4611
4782
|
cancelFrame = schedule(tick);
|
|
@@ -4619,31 +4790,38 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4619
4790
|
const params = resolveParams();
|
|
4620
4791
|
let rate;
|
|
4621
4792
|
if (finished && drainDeadlineAt !== void 0) {
|
|
4622
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4793
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, drainDeadlineAt - t));
|
|
4623
4794
|
} else if (gapWindow.length > 0 && lastArrivalAt !== void 0) {
|
|
4624
4795
|
const gaps = gapWindow.map((s) => s.gap).sort((a, b) => a - b);
|
|
4625
4796
|
const intervalQ = gaps[Math.min(gaps.length - 1, Math.floor(gaps.length * INTERVAL_QUANTILE))];
|
|
4626
4797
|
const horizon = Math.max(16, Math.min(params.bufferFactor * intervalQ + HORIZON_PAD_MS, params.maxLagMs));
|
|
4627
4798
|
const deadline = Math.max(lastArrivalAt + horizon, t + DEADLINE_FLOOR_MS);
|
|
4628
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4799
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, deadline - t));
|
|
4629
4800
|
} else {
|
|
4630
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4801
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, params.correctionTauMs));
|
|
4631
4802
|
}
|
|
4632
4803
|
credit += rate * dt / 1e3;
|
|
4633
|
-
const reveal = Math.min(Math.floor(credit),
|
|
4804
|
+
const reveal = Math.min(Math.floor(credit), pendingCount());
|
|
4634
4805
|
if (reveal > 0) {
|
|
4635
|
-
visibleEnd = pending[reveal - 1];
|
|
4636
|
-
|
|
4637
|
-
|
|
4806
|
+
visibleEnd = pending[pendingHead + reveal - 1];
|
|
4807
|
+
pendingHead += reveal;
|
|
4808
|
+
if (pendingHead === pending.length) {
|
|
4809
|
+
pending = [];
|
|
4810
|
+
pendingHead = 0;
|
|
4811
|
+
} else if (pendingHead >= 1024 && pendingHead * 2 >= pending.length) {
|
|
4812
|
+
pending = pending.slice(pendingHead);
|
|
4813
|
+
pendingHead = 0;
|
|
4814
|
+
}
|
|
4815
|
+
credit = pendingCount() > 0 ? credit - reveal : 0;
|
|
4638
4816
|
notify();
|
|
4639
4817
|
}
|
|
4640
|
-
if (!disposed && !cancelFrame &&
|
|
4818
|
+
if (!disposed && !cancelFrame && pendingCount() > 0) cancelFrame = schedule(tick);
|
|
4641
4819
|
};
|
|
4642
4820
|
const resegmentTail = () => {
|
|
4643
|
-
if (seam !== void 0 && seam < source.length && pending[pending.length - 1] === seam) {
|
|
4821
|
+
if (pendingCount() > 0 && seam !== void 0 && seam < source.length && pending[pending.length - 1] === seam) {
|
|
4644
4822
|
pending.pop();
|
|
4645
4823
|
}
|
|
4646
|
-
const from =
|
|
4824
|
+
const from = pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd;
|
|
4647
4825
|
let anchor = from;
|
|
4648
4826
|
if (seam !== void 0 && from <= seam) {
|
|
4649
4827
|
anchor = Math.max(0, from - RESUME_LOOKBACK);
|
|
@@ -4677,6 +4855,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4677
4855
|
visibleEnd = next.length;
|
|
4678
4856
|
tentativeEnd = next.length;
|
|
4679
4857
|
pending = [];
|
|
4858
|
+
pendingHead = 0;
|
|
4680
4859
|
seam = next.length;
|
|
4681
4860
|
credit = 0;
|
|
4682
4861
|
cancelScheduled();
|
|
@@ -4708,7 +4887,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4708
4887
|
if (finished) return;
|
|
4709
4888
|
finished = true;
|
|
4710
4889
|
lastArrivalAt = void 0;
|
|
4711
|
-
if (tentativeEnd > (
|
|
4890
|
+
if (tentativeEnd > (pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd)) {
|
|
4712
4891
|
pending.push(tentativeEnd);
|
|
4713
4892
|
}
|
|
4714
4893
|
const params = resolveParams();
|
|
@@ -4734,10 +4913,11 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4734
4913
|
snap,
|
|
4735
4914
|
flush() {
|
|
4736
4915
|
disposed = false;
|
|
4737
|
-
const target = finished ? source.length :
|
|
4916
|
+
const target = finished ? source.length : pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd;
|
|
4738
4917
|
if (target <= visibleEnd) return;
|
|
4739
4918
|
visibleEnd = target;
|
|
4740
4919
|
pending = [];
|
|
4920
|
+
pendingHead = 0;
|
|
4741
4921
|
credit = 0;
|
|
4742
4922
|
cancelScheduled();
|
|
4743
4923
|
notify();
|
|
@@ -5588,6 +5768,7 @@ function createRemendPreprocessor(options) {
|
|
|
5588
5768
|
rehypeRebaseHashLinks,
|
|
5589
5769
|
rehypeVerifyEngineTags,
|
|
5590
5770
|
removeComments,
|
|
5771
|
+
resolveCrossChunkReference,
|
|
5591
5772
|
sanitizeCrossChunkUrl,
|
|
5592
5773
|
sanitizeSchema,
|
|
5593
5774
|
shortenDocumentId,
|