@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.dev.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"]);
|
|
@@ -711,43 +757,6 @@ function maskIntraLineCodeSpans(text, carryOpen) {
|
|
|
711
757
|
out += text.slice(cursor);
|
|
712
758
|
return { masked: out, unpaired: false };
|
|
713
759
|
}
|
|
714
|
-
function freshCheckpoint(defListEnabled, mathFlow, referenceTaint) {
|
|
715
|
-
return {
|
|
716
|
-
defListEnabled,
|
|
717
|
-
mathFlow,
|
|
718
|
-
referenceTaint,
|
|
719
|
-
confirmedOffset: 0,
|
|
720
|
-
candidates: [],
|
|
721
|
-
defs: /* @__PURE__ */ new Map(),
|
|
722
|
-
footnoteDefs: /* @__PURE__ */ new Map(),
|
|
723
|
-
unresolvedRefs: [],
|
|
724
|
-
tagBalance: /* @__PURE__ */ new Map(),
|
|
725
|
-
openTotal: 0,
|
|
726
|
-
p5Tok: { kind: "data" },
|
|
727
|
-
formPointerMaybeSet: false,
|
|
728
|
-
openStack: [],
|
|
729
|
-
mdBlock: { kind: "none" },
|
|
730
|
-
blankRun: 0,
|
|
731
|
-
lastBlankStart: -1,
|
|
732
|
-
hazardVerdict: false,
|
|
733
|
-
prevLineBlank: true,
|
|
734
|
-
// doc start counts as a block start
|
|
735
|
-
prevLineWasText: false,
|
|
736
|
-
prevLineWasValidDef: false,
|
|
737
|
-
prevLineOpenContent: false,
|
|
738
|
-
tableMaybeOpen: false,
|
|
739
|
-
containerMaybeOpen: false,
|
|
740
|
-
paragraphHasUnpairedRun: false,
|
|
741
|
-
openBracket: null,
|
|
742
|
-
p5SealPending: false,
|
|
743
|
-
defBlockMaybeOpen: false,
|
|
744
|
-
fnDefResumable: false,
|
|
745
|
-
phasePoisonedAt: Infinity,
|
|
746
|
-
pendingTruncatedTags: [],
|
|
747
|
-
pendingTruncatedCloses: [],
|
|
748
|
-
pendingTag: null
|
|
749
|
-
};
|
|
750
|
-
}
|
|
751
760
|
function classifyBlockStart(text, indent, defListEnabled) {
|
|
752
761
|
if (indent >= 4) return true;
|
|
753
762
|
if (LIST_MARKER_RE.test(text) || FOOTNOTE_DEF_RE.test(text)) return true;
|
|
@@ -755,71 +764,23 @@ function classifyBlockStart(text, indent, defListEnabled) {
|
|
|
755
764
|
if (indent === 0) return false;
|
|
756
765
|
return null;
|
|
757
766
|
}
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
textEnd = nl;
|
|
776
|
-
end = nl;
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
const confirmed = end < text.length && !(end === text.length - 1 && text.charCodeAt(end) === 13);
|
|
780
|
-
const lineText = text.slice(start, textEnd);
|
|
781
|
-
const ln = {
|
|
782
|
-
start,
|
|
783
|
-
end,
|
|
784
|
-
text: lineText,
|
|
785
|
-
blank: confirmed && isMdBlank(lineText),
|
|
786
|
-
indent: computeIndent(lineText)
|
|
787
|
-
};
|
|
788
|
-
if (!confirmed) {
|
|
789
|
-
tailLine = ln;
|
|
790
|
-
break;
|
|
791
|
-
}
|
|
792
|
-
processConfirmedLine(cp, ln, text);
|
|
793
|
-
cp.confirmedOffset = end + 1;
|
|
794
|
-
start = end + 1;
|
|
795
|
-
}
|
|
796
|
-
const earliestUnresolved = settleRefsAndEarliestUnresolved(cp);
|
|
797
|
-
const defListSettled = (c) => {
|
|
798
|
-
if (!options.defListEnabled || c.blankRun >= 2) return true;
|
|
799
|
-
if (c.defListSettled !== null) return c.defListSettled;
|
|
800
|
-
if (tailLine) return !canBecomeDdLine(tailLine.text, false);
|
|
801
|
-
return false;
|
|
802
|
-
};
|
|
803
|
-
const tailRetroactive = tailLine !== null && tailCarriesRetroactive(tailLine.text);
|
|
804
|
-
let boundary = 0;
|
|
805
|
-
for (let i = cp.candidates.length - 1; i >= 0 && !tailRetroactive; i--) {
|
|
806
|
-
const c = cp.candidates[i];
|
|
807
|
-
if (!c.htmlBalanced || c.hazard || c.seamRisk) continue;
|
|
808
|
-
if (c.offset > cp.phasePoisonedAt) continue;
|
|
809
|
-
if (c.offset > earliestUnresolved) continue;
|
|
810
|
-
if (!defListSettled(c)) continue;
|
|
811
|
-
boundary = c.offset;
|
|
812
|
-
break;
|
|
813
|
-
}
|
|
814
|
-
return { boundary, checkpoint: cp };
|
|
815
|
-
}
|
|
816
|
-
function pendingFenceCloser(checkpoint) {
|
|
817
|
-
const cp = checkpoint;
|
|
818
|
-
if (cp.phasePoisonedAt !== Infinity) return "";
|
|
819
|
-
if (cp.mdBlock.kind === "fence" && cp.mdBlock.indent === 0) return cp.mdBlock.char.repeat(cp.mdBlock.len);
|
|
820
|
-
if (cp.mdBlock.kind === "math" && cp.mdBlock.indent === 0) return "$".repeat(cp.mdBlock.len);
|
|
821
|
-
return "";
|
|
822
|
-
}
|
|
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
|
|
823
784
|
function floatingResidue(text, commentOpenAtStart) {
|
|
824
785
|
let out = "";
|
|
825
786
|
let open = commentOpenAtStart;
|
|
@@ -1469,24 +1430,66 @@ function processConfirmedLine(cp, ln, text) {
|
|
|
1469
1430
|
}
|
|
1470
1431
|
}
|
|
1471
1432
|
}
|
|
1472
|
-
var SCANNER_NAME_LISTS = [
|
|
1473
|
-
["type1", TYPE1_NAMES],
|
|
1474
|
-
["rawText", RAW_TEXT_ELEMENTS],
|
|
1475
|
-
["type6", TYPE6_NAMES],
|
|
1476
|
-
["void", VOID_TAGS],
|
|
1477
|
-
["documentStructure", DOCUMENT_STRUCTURE_NAMES],
|
|
1478
|
-
// Added with F28, and it is the list that would have made F28 visible: the
|
|
1479
|
-
// derived census alphabet partitions names by their membership across THIS
|
|
1480
|
-
// table, so before it existed `frame` shared one 39-name class with `div`
|
|
1481
|
-
// and could never be sampled apart from it.
|
|
1482
|
-
["noElement", NO_ELEMENT_NAMES],
|
|
1483
|
-
["tablePart", TABLE_PART_NAMES],
|
|
1484
|
-
["scopeBarrier", SCOPE_BARRIER_NAMES],
|
|
1485
|
-
["foreignRoot", new Set(FOREIGN_ROOT_NAMES)]
|
|
1486
|
-
];
|
|
1487
1433
|
|
|
1488
|
-
// src/components/incrementalParse/
|
|
1489
|
-
|
|
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
|
+
}
|
|
1490
1493
|
|
|
1491
1494
|
// src/components/hastPredicates.ts
|
|
1492
1495
|
function isFootnoteSection(node) {
|
|
@@ -1534,121 +1537,7 @@ function attributeHastChildren(mdast, hast, stopAt = Infinity) {
|
|
|
1534
1537
|
}
|
|
1535
1538
|
}
|
|
1536
1539
|
|
|
1537
|
-
// src/components/incrementalParse/
|
|
1538
|
-
function collectPrefixInjection(mdast, content, boundary, resume) {
|
|
1539
|
-
const resumeValid = resume != null && resume.boundary <= boundary;
|
|
1540
|
-
if (resumeValid && resume.uninjectable) return { events: resume.events, uninjectable: true };
|
|
1541
|
-
const resumeAt = resumeValid ? resume.boundary : 0;
|
|
1542
|
-
const events = resumeAt > 0 ? cloneEventsForAppend(resume.events) : [];
|
|
1543
|
-
let uninjectable = false;
|
|
1544
|
-
let cacheable = true;
|
|
1545
|
-
const pushRef = (token) => {
|
|
1546
|
-
const last = events[events.length - 1];
|
|
1547
|
-
if (last && last.kind === "refs") last.tokens.push(token);
|
|
1548
|
-
else events.push({ kind: "refs", tokens: [token] });
|
|
1549
|
-
};
|
|
1550
|
-
const visit7 = (node, nested) => {
|
|
1551
|
-
const type = node.type;
|
|
1552
|
-
if (type === "definition") {
|
|
1553
|
-
const start = node.position?.start?.offset;
|
|
1554
|
-
const end = node.position?.end?.offset;
|
|
1555
|
-
if (start !== void 0 && end !== void 0 && start < boundary) {
|
|
1556
|
-
const slice = content.slice(start, end);
|
|
1557
|
-
if (nested && slice.includes("\n")) uninjectable = true;
|
|
1558
|
-
else events.push({ kind: "def", source: slice });
|
|
1559
|
-
}
|
|
1560
|
-
return;
|
|
1561
|
-
}
|
|
1562
|
-
if (type === "footnoteDefinition") {
|
|
1563
|
-
const start = node.position?.start;
|
|
1564
|
-
const end = node.position?.end?.offset;
|
|
1565
|
-
if (start?.offset === void 0 || end === void 0 || start.offset >= boundary) return;
|
|
1566
|
-
if (nested) {
|
|
1567
|
-
uninjectable = true;
|
|
1568
|
-
return;
|
|
1569
|
-
}
|
|
1570
|
-
const lineStart = start.offset - (start.column - 1);
|
|
1571
|
-
events.push({
|
|
1572
|
-
kind: "footnoteDef",
|
|
1573
|
-
source: content.slice(lineStart, end),
|
|
1574
|
-
origStart: lineStart,
|
|
1575
|
-
origLine: start.line
|
|
1576
|
-
});
|
|
1577
|
-
return;
|
|
1578
|
-
}
|
|
1579
|
-
if (type === "footnoteReference") {
|
|
1580
|
-
const start = node.position?.start?.offset;
|
|
1581
|
-
const end = node.position?.end?.offset;
|
|
1582
|
-
if (start === void 0 || end === void 0) {
|
|
1583
|
-
uninjectable = true;
|
|
1584
|
-
return;
|
|
1585
|
-
}
|
|
1586
|
-
pushRef(content.slice(start, end));
|
|
1587
|
-
return;
|
|
1588
|
-
}
|
|
1589
|
-
const children = node.children;
|
|
1590
|
-
if (children) {
|
|
1591
|
-
for (const child of children) visit7(child, true);
|
|
1592
|
-
}
|
|
1593
|
-
};
|
|
1594
|
-
let lastStart = -1;
|
|
1595
|
-
for (const child of mdast.children) {
|
|
1596
|
-
const start = child.position?.start?.offset;
|
|
1597
|
-
if (start !== void 0) {
|
|
1598
|
-
if (start < lastStart) return { events: [], uninjectable: true, cacheable: false };
|
|
1599
|
-
lastStart = start;
|
|
1600
|
-
}
|
|
1601
|
-
if (start === void 0) {
|
|
1602
|
-
if (resumeAt > 0) return collectPrefixInjection(mdast, content, boundary, null);
|
|
1603
|
-
cacheable = false;
|
|
1604
|
-
visit7(child, false);
|
|
1605
|
-
continue;
|
|
1606
|
-
}
|
|
1607
|
-
if (start >= boundary || start < resumeAt) continue;
|
|
1608
|
-
visit7(child, false);
|
|
1609
|
-
}
|
|
1610
|
-
return { events, uninjectable, cacheable };
|
|
1611
|
-
}
|
|
1612
|
-
function cloneEventsForAppend(events) {
|
|
1613
|
-
const out = events.slice();
|
|
1614
|
-
const last = out[out.length - 1];
|
|
1615
|
-
if (last && last.kind === "refs") out[out.length - 1] = { kind: "refs", tokens: last.tokens.slice() };
|
|
1616
|
-
return out;
|
|
1617
|
-
}
|
|
1618
|
-
var TERMINATOR_LABEL = "__aimd_injection_terminator__";
|
|
1619
|
-
var INJECTION_TERMINATOR = `[${TERMINATOR_LABEL}]: __aimd_sentinel_link__`;
|
|
1620
|
-
function tailMentionsTerminator(tailSource) {
|
|
1621
|
-
return (0, import_micromark_util_normalize_identifier2.normalizeIdentifier)(tailSource).replace(/\[ /g, "[").includes(`[${(0, import_micromark_util_normalize_identifier2.normalizeIdentifier)(TERMINATOR_LABEL)}`);
|
|
1622
|
-
}
|
|
1623
|
-
function buildInjectionPrefix(events) {
|
|
1624
|
-
if (events.length === 0) return { text: "", segments: [] };
|
|
1625
|
-
let text = "";
|
|
1626
|
-
let line = 1;
|
|
1627
|
-
const segments = [];
|
|
1628
|
-
for (const event of events) {
|
|
1629
|
-
if (text.length > 0) {
|
|
1630
|
-
text += "\n\n";
|
|
1631
|
-
line += 2;
|
|
1632
|
-
}
|
|
1633
|
-
const injStart = text.length;
|
|
1634
|
-
const source = event.kind === "refs" ? event.tokens.join(" ") : event.source;
|
|
1635
|
-
if (event.kind === "footnoteDef") {
|
|
1636
|
-
segments.push({
|
|
1637
|
-
injStart,
|
|
1638
|
-
injEnd: injStart + source.length,
|
|
1639
|
-
offsetDelta: event.origStart - injStart,
|
|
1640
|
-
lineDelta: event.origLine - line
|
|
1641
|
-
});
|
|
1642
|
-
}
|
|
1643
|
-
text += source;
|
|
1644
|
-
line += countNewlines(source);
|
|
1645
|
-
}
|
|
1646
|
-
return { text: `${text}
|
|
1647
|
-
|
|
1648
|
-
${INJECTION_TERMINATOR}
|
|
1649
|
-
|
|
1650
|
-
`, segments };
|
|
1651
|
-
}
|
|
1540
|
+
// src/components/incrementalParse/spliceCoordinates.ts
|
|
1652
1541
|
function rebaseTree(node, offsetDelta, lineDelta) {
|
|
1653
1542
|
rebaseTreeDual(node, EMPTY_SEGMENTS, offsetDelta, lineDelta);
|
|
1654
1543
|
}
|
|
@@ -1677,6 +1566,23 @@ function rebaseDualWalk(node, segments, maxEnd, offsetDelta, lineDelta) {
|
|
|
1677
1566
|
for (const child of children) rebaseDualWalk(child, segments, maxEnd, offsetDelta, lineDelta);
|
|
1678
1567
|
}
|
|
1679
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
|
|
1680
1586
|
var TABLE_PART_TAG_RE = /<(?:td|th|tr|tbody|thead|tfoot|caption|col|colgroup)\b/i;
|
|
1681
1587
|
var TABLE_TOKEN_RE = /<(\/?)(table|td|th|tr|tbody|thead|tfoot|caption|col|colgroup)\b/gi;
|
|
1682
1588
|
function hasStrayTablePart(values) {
|
|
@@ -1758,127 +1664,26 @@ function rawTextRegionCrossesOut(values) {
|
|
|
1758
1664
|
}
|
|
1759
1665
|
return false;
|
|
1760
1666
|
}
|
|
1761
|
-
function
|
|
1762
|
-
const
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
}
|
|
1773
|
-
const attrs = attributeHastChildren(prevMdast, prevHast, boundary);
|
|
1774
|
-
const cutRegion = [];
|
|
1775
|
-
for (let i = 0; i < prevHast.children.length; i++) {
|
|
1776
|
-
if (attrs[i] < boundary) {
|
|
1777
|
-
const node2 = prevHast.children[i];
|
|
1778
|
-
const end = node2.position?.end?.offset;
|
|
1779
|
-
if (end !== void 0 && end > boundary) return null;
|
|
1780
|
-
if (isTrailingLiteralText(node2)) {
|
|
1781
|
-
const prev = i > 0 ? prevHast.children[i - 1] : void 0;
|
|
1782
|
-
if (!prev || prev.type !== "element" || prev.position === void 0) return null;
|
|
1783
|
-
if (!ownsTrailingLiteral(prev, node2, prefixMdast))
|
|
1784
|
-
return null;
|
|
1785
|
-
}
|
|
1786
|
-
cutRegion.push(node2);
|
|
1787
|
-
continue;
|
|
1788
|
-
}
|
|
1789
|
-
const node = prevHast.children[i];
|
|
1790
|
-
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
|
|
1791
|
-
// raw literal can only trail an `html` mdast node. A position-less
|
|
1792
|
-
// text after a `<p>` is the NEXT block's remnant — a stray end tag
|
|
1793
|
-
// (`</t>\na`) parse5 dropped, whose text merged with the wrap
|
|
1794
|
-
// separator — owned by the tail, which re-parses it; freezing it
|
|
1795
|
-
// here duplicated it (v2.4.0 review P3). Falls through to the
|
|
1796
|
-
// remnant look-ahead below, which bails to a full parse. And the
|
|
1797
|
-
// literal must really be THAT block's trailing text: the block's raw
|
|
1798
|
-
// source ends with it. A dropped-tag block right after a frozen html
|
|
1799
|
-
// element (`</details>\n\n</t>\ntext`) puts its remnant in the same
|
|
1800
|
-
// position, and freezing it duplicated it (release soak of the fix).
|
|
1801
|
-
ownsTrailingLiteral(prevHast.children[i - 1], node, prefixMdast)) {
|
|
1802
|
-
cutRegion.push(node);
|
|
1803
|
-
break;
|
|
1804
|
-
}
|
|
1805
|
-
for (let j = i; j < prevHast.children.length; j++) {
|
|
1806
|
-
const look = prevHast.children[j];
|
|
1807
|
-
if (look.type === "element" || look.position !== void 0) break;
|
|
1808
|
-
if (isTrailingLiteralText(look)) return null;
|
|
1809
|
-
}
|
|
1810
|
-
break;
|
|
1811
|
-
}
|
|
1812
|
-
const tailMdastChildren = tailMdast.children.filter((child) => {
|
|
1813
|
-
const start = child.position?.start?.offset;
|
|
1814
|
-
return !(start !== void 0 && start < injectedLen);
|
|
1815
|
-
});
|
|
1816
|
-
const tailWrapVisible = tailMdastChildren.some((child) => !isWrapInvisible(child));
|
|
1817
|
-
const prefixHtmlValues = prefixMdast.flatMap((c) => c.type === "html" ? [c.value] : []);
|
|
1818
|
-
if (hasStrayTablePart(prefixHtmlValues)) return null;
|
|
1819
|
-
if (rawTextRegionCrossesOut(prefixHtmlValues)) return null;
|
|
1820
|
-
const leadingHtml = [];
|
|
1821
|
-
for (const child of tailMdastChildren) {
|
|
1822
|
-
if (isWrapInvisible(child)) continue;
|
|
1823
|
-
if (child.type !== "html") break;
|
|
1824
|
-
if (STRAY_SYNTHESIZED_END_TAG_RE.test(child.value) || TABLE_PART_TAG_RE.test(child.value)) return null;
|
|
1825
|
-
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;
|
|
1826
1678
|
}
|
|
1827
|
-
if (
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
const hastChildren = aligned.children;
|
|
1831
|
-
const interiorFinalLiteral = aligned.interiorFinalLiteral;
|
|
1832
|
-
const stripResult = stripInjectedHast(tailMdast, tailHast, injectedLen, tailWrapVisible);
|
|
1833
|
-
if (stripResult === null) return null;
|
|
1834
|
-
const strippedTailHast = stripResult.rest;
|
|
1835
|
-
for (const child of tailMdastChildren) rebaseTree(child, offsetDelta, lineDelta);
|
|
1836
|
-
for (const child of strippedTailHast) rebaseTreeDual(child, injectedSegments, offsetDelta, lineDelta);
|
|
1837
|
-
const mdastChildren = prefixMdast.concat(tailMdastChildren);
|
|
1838
|
-
const seamMergeVerdict = stripResult.remnantMerged ?? tailLeadingTextIsHoist(tailMdastChildren, strippedTailHast);
|
|
1839
|
-
if (seamMergeVerdict === null) return null;
|
|
1840
|
-
const seamMergeAllowed = seamMergeVerdict;
|
|
1841
|
-
let firstTailChild = true;
|
|
1842
|
-
for (const child of strippedTailHast) {
|
|
1843
|
-
const tailEnd = hastChildren[hastChildren.length - 1];
|
|
1844
|
-
if (firstTailChild && child.type === "text" && child.position !== void 0) {
|
|
1845
|
-
return null;
|
|
1846
|
-
}
|
|
1847
|
-
if (firstTailChild && tailEnd && tailEnd.type === "text" && child.type === "text" && child.position === void 0) {
|
|
1848
|
-
if (interiorFinalLiteral && tailEnd.value.trim() !== "") {
|
|
1849
|
-
if (seamMergeAllowed) return null;
|
|
1850
|
-
firstTailChild = false;
|
|
1851
|
-
hastChildren.push(child);
|
|
1852
|
-
continue;
|
|
1853
|
-
}
|
|
1854
|
-
const literalSeam = tailEnd.value.trim() !== "" && !tailWrapVisible;
|
|
1855
|
-
if (seamMergeAllowed || literalSeam) {
|
|
1856
|
-
hastChildren[hastChildren.length - 1] = { type: "text", value: tailEnd.value + child.value };
|
|
1857
|
-
firstTailChild = false;
|
|
1858
|
-
continue;
|
|
1859
|
-
}
|
|
1860
|
-
}
|
|
1861
|
-
firstTailChild = false;
|
|
1862
|
-
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;
|
|
1863
1682
|
}
|
|
1864
|
-
|
|
1865
|
-
const docStart = { line: 1, column: 1, offset: 0 };
|
|
1866
|
-
const mdastRootPosition = tailMdast.position ? { start: docStart, end: rebasePoint(tailMdast.position.end, offsetDelta, lineDelta) } : prevMdast.position;
|
|
1867
|
-
const hastRootPosition = mdastRootPosition;
|
|
1868
|
-
const mdast = { type: "root", children: mdastChildren };
|
|
1869
|
-
if (mdastRootPosition) mdast.position = mdastRootPosition;
|
|
1870
|
-
const hast = { type: "root", children: hastChildren };
|
|
1871
|
-
if (hastRootPosition) hast.position = hastRootPosition;
|
|
1872
|
-
if (prevHast.data !== void 0) hast.data = prevHast.data;
|
|
1873
|
-
return { mdast, hast };
|
|
1874
|
-
}
|
|
1875
|
-
function rebasePoint(point, offsetDelta, lineDelta) {
|
|
1876
|
-
return {
|
|
1877
|
-
line: point.line + lineDelta,
|
|
1878
|
-
column: point.column,
|
|
1879
|
-
offset: point.offset !== void 0 ? point.offset + offsetDelta : void 0
|
|
1880
|
-
};
|
|
1683
|
+
return false;
|
|
1881
1684
|
}
|
|
1685
|
+
|
|
1686
|
+
// src/components/incrementalParse/prefixAlignment.ts
|
|
1882
1687
|
function isWrapInvisible(node) {
|
|
1883
1688
|
return node.type === "definition" || node.type === "footnoteDefinition";
|
|
1884
1689
|
}
|
|
@@ -2020,96 +1825,303 @@ function stripInjectedHast(tailMdast, tailHast, injectedLen, tailWrapVisible) {
|
|
|
2020
1825
|
idx += 1;
|
|
2021
1826
|
continue;
|
|
2022
1827
|
}
|
|
2023
|
-
const start = node.position?.start?.offset;
|
|
2024
|
-
if (start === void 0 || start >= injectedLen) return null;
|
|
2025
|
-
consumed += 1;
|
|
2026
|
-
idx += 1;
|
|
2027
|
-
}
|
|
2028
|
-
if (consumed < injectedVisibleCount) return null;
|
|
2029
|
-
let remnant = "";
|
|
2030
|
-
let remnantMerged = null;
|
|
2031
|
-
if (tailWrapVisible) {
|
|
2032
|
-
const gap = children[idx];
|
|
2033
|
-
if (!gap || !isSeparatorText(gap)) return null;
|
|
2034
|
-
remnant = gap.value.slice(1);
|
|
2035
|
-
remnantMerged = remnant !== "";
|
|
2036
|
-
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);
|
|
2037
1967
|
}
|
|
2038
|
-
|
|
2039
|
-
if (remnant !== "") rest.unshift({ type: "text", value: remnant });
|
|
2040
|
-
return { rest, remnantMerged };
|
|
1968
|
+
return { events, uninjectable, cacheable };
|
|
2041
1969
|
}
|
|
2042
|
-
function
|
|
2043
|
-
const
|
|
2044
|
-
const
|
|
2045
|
-
if (
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
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;
|
|
2052
1990
|
}
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
if (start >= vStart && start < vEnd) return true;
|
|
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
|
+
});
|
|
2063
2000
|
}
|
|
2001
|
+
text += source;
|
|
2002
|
+
line += countNewlines(source);
|
|
2064
2003
|
}
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
const v = value.trim();
|
|
2071
|
-
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(">");
|
|
2004
|
+
return { text: `${text}
|
|
2005
|
+
|
|
2006
|
+
${INJECTION_TERMINATOR}
|
|
2007
|
+
|
|
2008
|
+
`, segments };
|
|
2072
2009
|
}
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
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);
|
|
2080
2023
|
}
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
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;
|
|
2084
2062
|
}
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
if (
|
|
2093
|
-
const
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
return node.type === "text" && node.position === void 0 && node.value.trim() !== "";
|
|
2100
|
-
}
|
|
2101
|
-
function countTrailingNewlines(value) {
|
|
2102
|
-
let n = 0;
|
|
2103
|
-
for (let i = value.length - 1; i >= 0 && value[i] === "\n"; i--) n += 1;
|
|
2104
|
-
return n;
|
|
2105
|
-
}
|
|
2106
|
-
function countNewlines(text, end = text.length) {
|
|
2107
|
-
let count = 0;
|
|
2108
|
-
for (let i = text.indexOf("\n"); i !== -1 && i < end; i = text.indexOf("\n", i + 1)) count += 1;
|
|
2109
|
-
for (let i = text.indexOf("\r"); i !== -1 && i < end; i = text.indexOf("\r", i + 1)) {
|
|
2110
|
-
if (text.charCodeAt(i + 1) !== 10) count += 1;
|
|
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);
|
|
2111
2077
|
}
|
|
2112
|
-
return
|
|
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) {
|
|
2096
|
+
return null;
|
|
2097
|
+
}
|
|
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
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
firstTailChild = false;
|
|
2113
|
+
hastChildren.push(child);
|
|
2114
|
+
}
|
|
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 };
|
|
2113
2125
|
}
|
|
2114
2126
|
|
|
2115
2127
|
// src/components/incrementalParse/advanceIncrementalParse.ts
|
|
@@ -2561,7 +2573,8 @@ function buildRegistryIndex(registry) {
|
|
|
2561
2573
|
links: /* @__PURE__ */ new Map(),
|
|
2562
2574
|
numbers: /* @__PURE__ */ new Map(),
|
|
2563
2575
|
counts: /* @__PURE__ */ new Map(),
|
|
2564
|
-
occurrences: /* @__PURE__ */ new Map()
|
|
2576
|
+
occurrences: /* @__PURE__ */ new Map(),
|
|
2577
|
+
labelOccurrences: /* @__PURE__ */ new Map()
|
|
2565
2578
|
};
|
|
2566
2579
|
for (const sym of registry.chunkOrder) {
|
|
2567
2580
|
const data = registry.chunkData.get(sym);
|
|
@@ -2578,12 +2591,78 @@ function buildRegistryIndex(registry) {
|
|
|
2578
2591
|
index.counts.set(label, total);
|
|
2579
2592
|
const prior = local.get(label);
|
|
2580
2593
|
if (prior) prior.count++;
|
|
2581
|
-
else
|
|
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
|
+
}
|
|
2582
2601
|
}
|
|
2583
2602
|
}
|
|
2584
2603
|
return index;
|
|
2585
2604
|
}
|
|
2586
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
|
+
|
|
2587
2666
|
// src/components/documentRegistry.ts
|
|
2588
2667
|
function createRegistry(onEmpty) {
|
|
2589
2668
|
let index;
|
|
@@ -2595,6 +2674,7 @@ function createRegistry(onEmpty) {
|
|
|
2595
2674
|
}
|
|
2596
2675
|
return index;
|
|
2597
2676
|
};
|
|
2677
|
+
const labels = createRegistrySubscriptions(() => ({ registry: reg, index: getIndex() }));
|
|
2598
2678
|
const reg = {
|
|
2599
2679
|
chunkOrder: [],
|
|
2600
2680
|
chunkData: /* @__PURE__ */ new Map(),
|
|
@@ -2745,6 +2825,9 @@ function createRegistry(onEmpty) {
|
|
|
2745
2825
|
this._subscribers.delete(cb);
|
|
2746
2826
|
};
|
|
2747
2827
|
},
|
|
2828
|
+
subscribeLabel(kind, label, cb) {
|
|
2829
|
+
return labels.subscribe(kind, label, cb);
|
|
2830
|
+
},
|
|
2748
2831
|
canonicalFootnoteFor(label) {
|
|
2749
2832
|
return getIndex().footnotes.get(normalizeId(label)) ?? null;
|
|
2750
2833
|
},
|
|
@@ -2772,7 +2855,9 @@ function createRegistry(onEmpty) {
|
|
|
2772
2855
|
this._notifyScheduled = true;
|
|
2773
2856
|
queueMicrotask(() => {
|
|
2774
2857
|
this._notifyScheduled = false;
|
|
2858
|
+
const labelCallbacks = labels.collect();
|
|
2775
2859
|
for (const cb of [...this._subscribers]) cb();
|
|
2860
|
+
for (const cb of labelCallbacks) cb();
|
|
2776
2861
|
});
|
|
2777
2862
|
}
|
|
2778
2863
|
};
|