@ai-react-markdown/engine 2.12.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 +523 -438
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +53 -76
- package/dist/index.d.ts +53 -76
- package/dist/index.dev.cjs +523 -438
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +523 -438
- package/dist/index.dev.js.map +1 -1
- package/dist/index.js +523 -438
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -265,8 +265,51 @@ var defaultUrlTransform = (value) => {
|
|
|
265
265
|
return "";
|
|
266
266
|
};
|
|
267
267
|
|
|
268
|
-
// src/components/incrementalParse/
|
|
269
|
-
|
|
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
|
+
}
|
|
270
313
|
|
|
271
314
|
// src/components/incrementalParse/mdLineText.ts
|
|
272
315
|
var MD_BLANK_RE = /^[ \t\r]*$/;
|
|
@@ -274,6 +317,9 @@ var isMdBlank = (text) => MD_BLANK_RE.test(text);
|
|
|
274
317
|
var mdTrim = (text) => text.replace(/^[ \t\r]+|[ \t\r]+$/g, "");
|
|
275
318
|
var mdTrimStart = (text) => text.replace(/^[ \t\r]+/, "");
|
|
276
319
|
|
|
320
|
+
// src/components/incrementalParse/freezeLineSyntax.ts
|
|
321
|
+
var import_micromark_util_html_tag_name = require("micromark-util-html-tag-name");
|
|
322
|
+
|
|
277
323
|
// src/components/incrementalParse/referenceTaint.ts
|
|
278
324
|
var import_micromark_util_normalize_identifier = require("micromark-util-normalize-identifier");
|
|
279
325
|
var FOOTNOTE_DEF_RE = /^ {0,3}\[\^[^\]]*\]:/;
|
|
@@ -459,7 +505,7 @@ function settleRefsAndEarliestUnresolved(cp) {
|
|
|
459
505
|
return earliestUnresolved;
|
|
460
506
|
}
|
|
461
507
|
|
|
462
|
-
// src/components/incrementalParse/
|
|
508
|
+
// src/components/incrementalParse/freezeLineSyntax.ts
|
|
463
509
|
var TYPE6_NAMES = new Set(import_micromark_util_html_tag_name.htmlBlockNames);
|
|
464
510
|
var TABLE_PART_NAMES = /* @__PURE__ */ new Set(["td", "th", "tr", "tbody", "thead", "tfoot", "caption", "col", "colgroup"]);
|
|
465
511
|
var DOCUMENT_STRUCTURE_NAMES = /* @__PURE__ */ new Set(["html", "head", "body", "frameset"]);
|
|
@@ -710,43 +756,6 @@ function maskIntraLineCodeSpans(text, carryOpen) {
|
|
|
710
756
|
out += text.slice(cursor);
|
|
711
757
|
return { masked: out, unpaired: false };
|
|
712
758
|
}
|
|
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
759
|
function classifyBlockStart(text, indent, defListEnabled) {
|
|
751
760
|
if (indent >= 4) return true;
|
|
752
761
|
if (LIST_MARKER_RE.test(text) || FOOTNOTE_DEF_RE.test(text)) return true;
|
|
@@ -754,71 +763,23 @@ function classifyBlockStart(text, indent, defListEnabled) {
|
|
|
754
763
|
if (indent === 0) return false;
|
|
755
764
|
return null;
|
|
756
765
|
}
|
|
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
|
-
}
|
|
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
|
|
822
783
|
function floatingResidue(text, commentOpenAtStart) {
|
|
823
784
|
let out = "";
|
|
824
785
|
let open = commentOpenAtStart;
|
|
@@ -1462,24 +1423,66 @@ function processConfirmedLine(cp, ln, text) {
|
|
|
1462
1423
|
}
|
|
1463
1424
|
}
|
|
1464
1425
|
}
|
|
1465
|
-
var SCANNER_NAME_LISTS = [
|
|
1466
|
-
["type1", TYPE1_NAMES],
|
|
1467
|
-
["rawText", RAW_TEXT_ELEMENTS],
|
|
1468
|
-
["type6", TYPE6_NAMES],
|
|
1469
|
-
["void", VOID_TAGS],
|
|
1470
|
-
["documentStructure", DOCUMENT_STRUCTURE_NAMES],
|
|
1471
|
-
// Added with F28, and it is the list that would have made F28 visible: the
|
|
1472
|
-
// derived census alphabet partitions names by their membership across THIS
|
|
1473
|
-
// table, so before it existed `frame` shared one 39-name class with `div`
|
|
1474
|
-
// and could never be sampled apart from it.
|
|
1475
|
-
["noElement", NO_ELEMENT_NAMES],
|
|
1476
|
-
["tablePart", TABLE_PART_NAMES],
|
|
1477
|
-
["scopeBarrier", SCOPE_BARRIER_NAMES],
|
|
1478
|
-
["foreignRoot", new Set(FOREIGN_ROOT_NAMES)]
|
|
1479
|
-
];
|
|
1480
1426
|
|
|
1481
|
-
// src/components/incrementalParse/
|
|
1482
|
-
|
|
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
|
+
}
|
|
1483
1486
|
|
|
1484
1487
|
// src/components/hastPredicates.ts
|
|
1485
1488
|
function isFootnoteSection(node) {
|
|
@@ -1527,121 +1530,7 @@ function attributeHastChildren(mdast, hast, stopAt = Infinity) {
|
|
|
1527
1530
|
}
|
|
1528
1531
|
}
|
|
1529
1532
|
|
|
1530
|
-
// src/components/incrementalParse/
|
|
1531
|
-
function collectPrefixInjection(mdast, content, boundary, resume) {
|
|
1532
|
-
const resumeValid = resume != null && resume.boundary <= boundary;
|
|
1533
|
-
if (resumeValid && resume.uninjectable) return { events: resume.events, uninjectable: true };
|
|
1534
|
-
const resumeAt = resumeValid ? resume.boundary : 0;
|
|
1535
|
-
const events = resumeAt > 0 ? cloneEventsForAppend(resume.events) : [];
|
|
1536
|
-
let uninjectable = false;
|
|
1537
|
-
let cacheable = true;
|
|
1538
|
-
const pushRef = (token) => {
|
|
1539
|
-
const last = events[events.length - 1];
|
|
1540
|
-
if (last && last.kind === "refs") last.tokens.push(token);
|
|
1541
|
-
else events.push({ kind: "refs", tokens: [token] });
|
|
1542
|
-
};
|
|
1543
|
-
const visit7 = (node, nested) => {
|
|
1544
|
-
const type = node.type;
|
|
1545
|
-
if (type === "definition") {
|
|
1546
|
-
const start = node.position?.start?.offset;
|
|
1547
|
-
const end = node.position?.end?.offset;
|
|
1548
|
-
if (start !== void 0 && end !== void 0 && start < boundary) {
|
|
1549
|
-
const slice = content.slice(start, end);
|
|
1550
|
-
if (nested && slice.includes("\n")) uninjectable = true;
|
|
1551
|
-
else events.push({ kind: "def", source: slice });
|
|
1552
|
-
}
|
|
1553
|
-
return;
|
|
1554
|
-
}
|
|
1555
|
-
if (type === "footnoteDefinition") {
|
|
1556
|
-
const start = node.position?.start;
|
|
1557
|
-
const end = node.position?.end?.offset;
|
|
1558
|
-
if (start?.offset === void 0 || end === void 0 || start.offset >= boundary) return;
|
|
1559
|
-
if (nested) {
|
|
1560
|
-
uninjectable = true;
|
|
1561
|
-
return;
|
|
1562
|
-
}
|
|
1563
|
-
const lineStart = start.offset - (start.column - 1);
|
|
1564
|
-
events.push({
|
|
1565
|
-
kind: "footnoteDef",
|
|
1566
|
-
source: content.slice(lineStart, end),
|
|
1567
|
-
origStart: lineStart,
|
|
1568
|
-
origLine: start.line
|
|
1569
|
-
});
|
|
1570
|
-
return;
|
|
1571
|
-
}
|
|
1572
|
-
if (type === "footnoteReference") {
|
|
1573
|
-
const start = node.position?.start?.offset;
|
|
1574
|
-
const end = node.position?.end?.offset;
|
|
1575
|
-
if (start === void 0 || end === void 0) {
|
|
1576
|
-
uninjectable = true;
|
|
1577
|
-
return;
|
|
1578
|
-
}
|
|
1579
|
-
pushRef(content.slice(start, end));
|
|
1580
|
-
return;
|
|
1581
|
-
}
|
|
1582
|
-
const children = node.children;
|
|
1583
|
-
if (children) {
|
|
1584
|
-
for (const child of children) visit7(child, true);
|
|
1585
|
-
}
|
|
1586
|
-
};
|
|
1587
|
-
let lastStart = -1;
|
|
1588
|
-
for (const child of mdast.children) {
|
|
1589
|
-
const start = child.position?.start?.offset;
|
|
1590
|
-
if (start !== void 0) {
|
|
1591
|
-
if (start < lastStart) return { events: [], uninjectable: true, cacheable: false };
|
|
1592
|
-
lastStart = start;
|
|
1593
|
-
}
|
|
1594
|
-
if (start === void 0) {
|
|
1595
|
-
if (resumeAt > 0) return collectPrefixInjection(mdast, content, boundary, null);
|
|
1596
|
-
cacheable = false;
|
|
1597
|
-
visit7(child, false);
|
|
1598
|
-
continue;
|
|
1599
|
-
}
|
|
1600
|
-
if (start >= boundary || start < resumeAt) continue;
|
|
1601
|
-
visit7(child, false);
|
|
1602
|
-
}
|
|
1603
|
-
return { events, uninjectable, cacheable };
|
|
1604
|
-
}
|
|
1605
|
-
function cloneEventsForAppend(events) {
|
|
1606
|
-
const out = events.slice();
|
|
1607
|
-
const last = out[out.length - 1];
|
|
1608
|
-
if (last && last.kind === "refs") out[out.length - 1] = { kind: "refs", tokens: last.tokens.slice() };
|
|
1609
|
-
return out;
|
|
1610
|
-
}
|
|
1611
|
-
var TERMINATOR_LABEL = "__aimd_injection_terminator__";
|
|
1612
|
-
var INJECTION_TERMINATOR = `[${TERMINATOR_LABEL}]: __aimd_sentinel_link__`;
|
|
1613
|
-
function tailMentionsTerminator(tailSource) {
|
|
1614
|
-
return (0, import_micromark_util_normalize_identifier2.normalizeIdentifier)(tailSource).replace(/\[ /g, "[").includes(`[${(0, import_micromark_util_normalize_identifier2.normalizeIdentifier)(TERMINATOR_LABEL)}`);
|
|
1615
|
-
}
|
|
1616
|
-
function buildInjectionPrefix(events) {
|
|
1617
|
-
if (events.length === 0) return { text: "", segments: [] };
|
|
1618
|
-
let text = "";
|
|
1619
|
-
let line = 1;
|
|
1620
|
-
const segments = [];
|
|
1621
|
-
for (const event of events) {
|
|
1622
|
-
if (text.length > 0) {
|
|
1623
|
-
text += "\n\n";
|
|
1624
|
-
line += 2;
|
|
1625
|
-
}
|
|
1626
|
-
const injStart = text.length;
|
|
1627
|
-
const source = event.kind === "refs" ? event.tokens.join(" ") : event.source;
|
|
1628
|
-
if (event.kind === "footnoteDef") {
|
|
1629
|
-
segments.push({
|
|
1630
|
-
injStart,
|
|
1631
|
-
injEnd: injStart + source.length,
|
|
1632
|
-
offsetDelta: event.origStart - injStart,
|
|
1633
|
-
lineDelta: event.origLine - line
|
|
1634
|
-
});
|
|
1635
|
-
}
|
|
1636
|
-
text += source;
|
|
1637
|
-
line += countNewlines(source);
|
|
1638
|
-
}
|
|
1639
|
-
return { text: `${text}
|
|
1640
|
-
|
|
1641
|
-
${INJECTION_TERMINATOR}
|
|
1642
|
-
|
|
1643
|
-
`, segments };
|
|
1644
|
-
}
|
|
1533
|
+
// src/components/incrementalParse/spliceCoordinates.ts
|
|
1645
1534
|
function rebaseTree(node, offsetDelta, lineDelta) {
|
|
1646
1535
|
rebaseTreeDual(node, EMPTY_SEGMENTS, offsetDelta, lineDelta);
|
|
1647
1536
|
}
|
|
@@ -1670,6 +1559,23 @@ function rebaseDualWalk(node, segments, maxEnd, offsetDelta, lineDelta) {
|
|
|
1670
1559
|
for (const child of children) rebaseDualWalk(child, segments, maxEnd, offsetDelta, lineDelta);
|
|
1671
1560
|
}
|
|
1672
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
|
|
1673
1579
|
var TABLE_PART_TAG_RE = /<(?:td|th|tr|tbody|thead|tfoot|caption|col|colgroup)\b/i;
|
|
1674
1580
|
var TABLE_TOKEN_RE = /<(\/?)(table|td|th|tr|tbody|thead|tfoot|caption|col|colgroup)\b/gi;
|
|
1675
1581
|
function hasStrayTablePart(values) {
|
|
@@ -1751,127 +1657,26 @@ function rawTextRegionCrossesOut(values) {
|
|
|
1751
1657
|
}
|
|
1752
1658
|
return false;
|
|
1753
1659
|
}
|
|
1754
|
-
function
|
|
1755
|
-
const
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
}
|
|
1766
|
-
const attrs = attributeHastChildren(prevMdast, prevHast, boundary);
|
|
1767
|
-
const cutRegion = [];
|
|
1768
|
-
for (let i = 0; i < prevHast.children.length; i++) {
|
|
1769
|
-
if (attrs[i] < boundary) {
|
|
1770
|
-
const node2 = prevHast.children[i];
|
|
1771
|
-
const end = node2.position?.end?.offset;
|
|
1772
|
-
if (end !== void 0 && end > boundary) return null;
|
|
1773
|
-
if (isTrailingLiteralText(node2)) {
|
|
1774
|
-
const prev = i > 0 ? prevHast.children[i - 1] : void 0;
|
|
1775
|
-
if (!prev || prev.type !== "element" || prev.position === void 0) return null;
|
|
1776
|
-
if (!ownsTrailingLiteral(prev, node2, prefixMdast))
|
|
1777
|
-
return null;
|
|
1778
|
-
}
|
|
1779
|
-
cutRegion.push(node2);
|
|
1780
|
-
continue;
|
|
1781
|
-
}
|
|
1782
|
-
const node = prevHast.children[i];
|
|
1783
|
-
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
|
|
1784
|
-
// raw literal can only trail an `html` mdast node. A position-less
|
|
1785
|
-
// text after a `<p>` is the NEXT block's remnant — a stray end tag
|
|
1786
|
-
// (`</t>\na`) parse5 dropped, whose text merged with the wrap
|
|
1787
|
-
// separator — owned by the tail, which re-parses it; freezing it
|
|
1788
|
-
// here duplicated it (v2.4.0 review P3). Falls through to the
|
|
1789
|
-
// remnant look-ahead below, which bails to a full parse. And the
|
|
1790
|
-
// literal must really be THAT block's trailing text: the block's raw
|
|
1791
|
-
// source ends with it. A dropped-tag block right after a frozen html
|
|
1792
|
-
// element (`</details>\n\n</t>\ntext`) puts its remnant in the same
|
|
1793
|
-
// position, and freezing it duplicated it (release soak of the fix).
|
|
1794
|
-
ownsTrailingLiteral(prevHast.children[i - 1], node, prefixMdast)) {
|
|
1795
|
-
cutRegion.push(node);
|
|
1796
|
-
break;
|
|
1797
|
-
}
|
|
1798
|
-
for (let j = i; j < prevHast.children.length; j++) {
|
|
1799
|
-
const look = prevHast.children[j];
|
|
1800
|
-
if (look.type === "element" || look.position !== void 0) break;
|
|
1801
|
-
if (isTrailingLiteralText(look)) return null;
|
|
1802
|
-
}
|
|
1803
|
-
break;
|
|
1804
|
-
}
|
|
1805
|
-
const tailMdastChildren = tailMdast.children.filter((child) => {
|
|
1806
|
-
const start = child.position?.start?.offset;
|
|
1807
|
-
return !(start !== void 0 && start < injectedLen);
|
|
1808
|
-
});
|
|
1809
|
-
const tailWrapVisible = tailMdastChildren.some((child) => !isWrapInvisible(child));
|
|
1810
|
-
const prefixHtmlValues = prefixMdast.flatMap((c) => c.type === "html" ? [c.value] : []);
|
|
1811
|
-
if (hasStrayTablePart(prefixHtmlValues)) return null;
|
|
1812
|
-
if (rawTextRegionCrossesOut(prefixHtmlValues)) return null;
|
|
1813
|
-
const leadingHtml = [];
|
|
1814
|
-
for (const child of tailMdastChildren) {
|
|
1815
|
-
if (isWrapInvisible(child)) continue;
|
|
1816
|
-
if (child.type !== "html") break;
|
|
1817
|
-
if (STRAY_SYNTHESIZED_END_TAG_RE.test(child.value) || TABLE_PART_TAG_RE.test(child.value)) return null;
|
|
1818
|
-
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;
|
|
1819
1671
|
}
|
|
1820
|
-
if (
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
const hastChildren = aligned.children;
|
|
1824
|
-
const interiorFinalLiteral = aligned.interiorFinalLiteral;
|
|
1825
|
-
const stripResult = stripInjectedHast(tailMdast, tailHast, injectedLen, tailWrapVisible);
|
|
1826
|
-
if (stripResult === null) return null;
|
|
1827
|
-
const strippedTailHast = stripResult.rest;
|
|
1828
|
-
for (const child of tailMdastChildren) rebaseTree(child, offsetDelta, lineDelta);
|
|
1829
|
-
for (const child of strippedTailHast) rebaseTreeDual(child, injectedSegments, offsetDelta, lineDelta);
|
|
1830
|
-
const mdastChildren = prefixMdast.concat(tailMdastChildren);
|
|
1831
|
-
const seamMergeVerdict = stripResult.remnantMerged ?? tailLeadingTextIsHoist(tailMdastChildren, strippedTailHast);
|
|
1832
|
-
if (seamMergeVerdict === null) return null;
|
|
1833
|
-
const seamMergeAllowed = seamMergeVerdict;
|
|
1834
|
-
let firstTailChild = true;
|
|
1835
|
-
for (const child of strippedTailHast) {
|
|
1836
|
-
const tailEnd = hastChildren[hastChildren.length - 1];
|
|
1837
|
-
if (firstTailChild && child.type === "text" && child.position !== void 0) {
|
|
1838
|
-
return null;
|
|
1839
|
-
}
|
|
1840
|
-
if (firstTailChild && tailEnd && tailEnd.type === "text" && child.type === "text" && child.position === void 0) {
|
|
1841
|
-
if (interiorFinalLiteral && tailEnd.value.trim() !== "") {
|
|
1842
|
-
if (seamMergeAllowed) return null;
|
|
1843
|
-
firstTailChild = false;
|
|
1844
|
-
hastChildren.push(child);
|
|
1845
|
-
continue;
|
|
1846
|
-
}
|
|
1847
|
-
const literalSeam = tailEnd.value.trim() !== "" && !tailWrapVisible;
|
|
1848
|
-
if (seamMergeAllowed || literalSeam) {
|
|
1849
|
-
hastChildren[hastChildren.length - 1] = { type: "text", value: tailEnd.value + child.value };
|
|
1850
|
-
firstTailChild = false;
|
|
1851
|
-
continue;
|
|
1852
|
-
}
|
|
1853
|
-
}
|
|
1854
|
-
firstTailChild = false;
|
|
1855
|
-
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;
|
|
1856
1675
|
}
|
|
1857
|
-
|
|
1858
|
-
const docStart = { line: 1, column: 1, offset: 0 };
|
|
1859
|
-
const mdastRootPosition = tailMdast.position ? { start: docStart, end: rebasePoint(tailMdast.position.end, offsetDelta, lineDelta) } : prevMdast.position;
|
|
1860
|
-
const hastRootPosition = mdastRootPosition;
|
|
1861
|
-
const mdast = { type: "root", children: mdastChildren };
|
|
1862
|
-
if (mdastRootPosition) mdast.position = mdastRootPosition;
|
|
1863
|
-
const hast = { type: "root", children: hastChildren };
|
|
1864
|
-
if (hastRootPosition) hast.position = hastRootPosition;
|
|
1865
|
-
if (prevHast.data !== void 0) hast.data = prevHast.data;
|
|
1866
|
-
return { mdast, hast };
|
|
1867
|
-
}
|
|
1868
|
-
function rebasePoint(point, offsetDelta, lineDelta) {
|
|
1869
|
-
return {
|
|
1870
|
-
line: point.line + lineDelta,
|
|
1871
|
-
column: point.column,
|
|
1872
|
-
offset: point.offset !== void 0 ? point.offset + offsetDelta : void 0
|
|
1873
|
-
};
|
|
1676
|
+
return false;
|
|
1874
1677
|
}
|
|
1678
|
+
|
|
1679
|
+
// src/components/incrementalParse/prefixAlignment.ts
|
|
1875
1680
|
function isWrapInvisible(node) {
|
|
1876
1681
|
return node.type === "definition" || node.type === "footnoteDefinition";
|
|
1877
1682
|
}
|
|
@@ -2013,96 +1818,303 @@ function stripInjectedHast(tailMdast, tailHast, injectedLen, tailWrapVisible) {
|
|
|
2013
1818
|
idx += 1;
|
|
2014
1819
|
continue;
|
|
2015
1820
|
}
|
|
2016
|
-
const start = node.position?.start?.offset;
|
|
2017
|
-
if (start === void 0 || start >= injectedLen) return null;
|
|
2018
|
-
consumed += 1;
|
|
2019
|
-
idx += 1;
|
|
2020
|
-
}
|
|
2021
|
-
if (consumed < injectedVisibleCount) return null;
|
|
2022
|
-
let remnant = "";
|
|
2023
|
-
let remnantMerged = null;
|
|
2024
|
-
if (tailWrapVisible) {
|
|
2025
|
-
const gap = children[idx];
|
|
2026
|
-
if (!gap || !isSeparatorText(gap)) return null;
|
|
2027
|
-
remnant = gap.value.slice(1);
|
|
2028
|
-
remnantMerged = remnant !== "";
|
|
2029
|
-
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);
|
|
2030
1960
|
}
|
|
2031
|
-
|
|
2032
|
-
if (remnant !== "") rest.unshift({ type: "text", value: remnant });
|
|
2033
|
-
return { rest, remnantMerged };
|
|
1961
|
+
return { events, uninjectable, cacheable };
|
|
2034
1962
|
}
|
|
2035
|
-
function
|
|
2036
|
-
const
|
|
2037
|
-
const
|
|
2038
|
-
if (
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
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;
|
|
2045
1983
|
}
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
if (start >= vStart && start < vEnd) return true;
|
|
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
|
+
});
|
|
2056
1993
|
}
|
|
1994
|
+
text += source;
|
|
1995
|
+
line += countNewlines(source);
|
|
2057
1996
|
}
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
const v = value.trim();
|
|
2064
|
-
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(">");
|
|
1997
|
+
return { text: `${text}
|
|
1998
|
+
|
|
1999
|
+
${INJECTION_TERMINATOR}
|
|
2000
|
+
|
|
2001
|
+
`, segments };
|
|
2065
2002
|
}
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
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);
|
|
2073
2016
|
}
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
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;
|
|
2077
2055
|
}
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
if (
|
|
2086
|
-
const
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
return node.type === "text" && node.position === void 0 && node.value.trim() !== "";
|
|
2093
|
-
}
|
|
2094
|
-
function countTrailingNewlines(value) {
|
|
2095
|
-
let n = 0;
|
|
2096
|
-
for (let i = value.length - 1; i >= 0 && value[i] === "\n"; i--) n += 1;
|
|
2097
|
-
return n;
|
|
2098
|
-
}
|
|
2099
|
-
function countNewlines(text, end = text.length) {
|
|
2100
|
-
let count = 0;
|
|
2101
|
-
for (let i = text.indexOf("\n"); i !== -1 && i < end; i = text.indexOf("\n", i + 1)) count += 1;
|
|
2102
|
-
for (let i = text.indexOf("\r"); i !== -1 && i < end; i = text.indexOf("\r", i + 1)) {
|
|
2103
|
-
if (text.charCodeAt(i + 1) !== 10) count += 1;
|
|
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);
|
|
2104
2070
|
}
|
|
2105
|
-
return
|
|
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) {
|
|
2089
|
+
return null;
|
|
2090
|
+
}
|
|
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
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
firstTailChild = false;
|
|
2106
|
+
hastChildren.push(child);
|
|
2107
|
+
}
|
|
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 };
|
|
2106
2118
|
}
|
|
2107
2119
|
|
|
2108
2120
|
// src/components/incrementalParse/advanceIncrementalParse.ts
|
|
@@ -2554,7 +2566,8 @@ function buildRegistryIndex(registry) {
|
|
|
2554
2566
|
links: /* @__PURE__ */ new Map(),
|
|
2555
2567
|
numbers: /* @__PURE__ */ new Map(),
|
|
2556
2568
|
counts: /* @__PURE__ */ new Map(),
|
|
2557
|
-
occurrences: /* @__PURE__ */ new Map()
|
|
2569
|
+
occurrences: /* @__PURE__ */ new Map(),
|
|
2570
|
+
labelOccurrences: /* @__PURE__ */ new Map()
|
|
2558
2571
|
};
|
|
2559
2572
|
for (const sym of registry.chunkOrder) {
|
|
2560
2573
|
const data = registry.chunkData.get(sym);
|
|
@@ -2571,12 +2584,78 @@ function buildRegistryIndex(registry) {
|
|
|
2571
2584
|
index.counts.set(label, total);
|
|
2572
2585
|
const prior = local.get(label);
|
|
2573
2586
|
if (prior) prior.count++;
|
|
2574
|
-
else
|
|
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
|
+
}
|
|
2575
2594
|
}
|
|
2576
2595
|
}
|
|
2577
2596
|
return index;
|
|
2578
2597
|
}
|
|
2579
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
|
+
|
|
2580
2659
|
// src/components/documentRegistry.ts
|
|
2581
2660
|
function createRegistry(onEmpty) {
|
|
2582
2661
|
let index;
|
|
@@ -2588,6 +2667,7 @@ function createRegistry(onEmpty) {
|
|
|
2588
2667
|
}
|
|
2589
2668
|
return index;
|
|
2590
2669
|
};
|
|
2670
|
+
const labels = createRegistrySubscriptions(() => ({ registry: reg, index: getIndex() }));
|
|
2591
2671
|
const reg = {
|
|
2592
2672
|
chunkOrder: [],
|
|
2593
2673
|
chunkData: /* @__PURE__ */ new Map(),
|
|
@@ -2738,6 +2818,9 @@ function createRegistry(onEmpty) {
|
|
|
2738
2818
|
this._subscribers.delete(cb);
|
|
2739
2819
|
};
|
|
2740
2820
|
},
|
|
2821
|
+
subscribeLabel(kind, label, cb) {
|
|
2822
|
+
return labels.subscribe(kind, label, cb);
|
|
2823
|
+
},
|
|
2741
2824
|
canonicalFootnoteFor(label) {
|
|
2742
2825
|
return getIndex().footnotes.get(normalizeId(label)) ?? null;
|
|
2743
2826
|
},
|
|
@@ -2765,7 +2848,9 @@ function createRegistry(onEmpty) {
|
|
|
2765
2848
|
this._notifyScheduled = true;
|
|
2766
2849
|
queueMicrotask(() => {
|
|
2767
2850
|
this._notifyScheduled = false;
|
|
2851
|
+
const labelCallbacks = labels.collect();
|
|
2768
2852
|
for (const cb of [...this._subscribers]) cb();
|
|
2853
|
+
for (const cb of labelCallbacks) cb();
|
|
2769
2854
|
});
|
|
2770
2855
|
}
|
|
2771
2856
|
};
|