@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.js
CHANGED
|
@@ -172,8 +172,51 @@ var defaultUrlTransform = (value) => {
|
|
|
172
172
|
return "";
|
|
173
173
|
};
|
|
174
174
|
|
|
175
|
-
// src/components/incrementalParse/
|
|
176
|
-
|
|
175
|
+
// src/components/incrementalParse/freezeScanState.ts
|
|
176
|
+
function freshCheckpoint(defListEnabled, mathFlow, referenceTaint) {
|
|
177
|
+
return {
|
|
178
|
+
defListEnabled,
|
|
179
|
+
mathFlow,
|
|
180
|
+
referenceTaint,
|
|
181
|
+
confirmedOffset: 0,
|
|
182
|
+
candidates: [],
|
|
183
|
+
defs: /* @__PURE__ */ new Map(),
|
|
184
|
+
footnoteDefs: /* @__PURE__ */ new Map(),
|
|
185
|
+
unresolvedRefs: [],
|
|
186
|
+
tagBalance: /* @__PURE__ */ new Map(),
|
|
187
|
+
openTotal: 0,
|
|
188
|
+
p5Tok: { kind: "data" },
|
|
189
|
+
formPointerMaybeSet: false,
|
|
190
|
+
openStack: [],
|
|
191
|
+
mdBlock: { kind: "none" },
|
|
192
|
+
blankRun: 0,
|
|
193
|
+
lastBlankStart: -1,
|
|
194
|
+
hazardVerdict: false,
|
|
195
|
+
prevLineBlank: true,
|
|
196
|
+
// doc start counts as a block start
|
|
197
|
+
prevLineWasText: false,
|
|
198
|
+
prevLineWasValidDef: false,
|
|
199
|
+
prevLineOpenContent: false,
|
|
200
|
+
tableMaybeOpen: false,
|
|
201
|
+
containerMaybeOpen: false,
|
|
202
|
+
paragraphHasUnpairedRun: false,
|
|
203
|
+
openBracket: null,
|
|
204
|
+
p5SealPending: false,
|
|
205
|
+
defBlockMaybeOpen: false,
|
|
206
|
+
fnDefResumable: false,
|
|
207
|
+
phasePoisonedAt: Infinity,
|
|
208
|
+
pendingTruncatedTags: [],
|
|
209
|
+
pendingTruncatedCloses: [],
|
|
210
|
+
pendingTag: null
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
function pendingFenceCloser(checkpoint) {
|
|
214
|
+
const cp = checkpoint;
|
|
215
|
+
if (cp.phasePoisonedAt !== Infinity) return "";
|
|
216
|
+
if (cp.mdBlock.kind === "fence" && cp.mdBlock.indent === 0) return cp.mdBlock.char.repeat(cp.mdBlock.len);
|
|
217
|
+
if (cp.mdBlock.kind === "math" && cp.mdBlock.indent === 0) return "$".repeat(cp.mdBlock.len);
|
|
218
|
+
return "";
|
|
219
|
+
}
|
|
177
220
|
|
|
178
221
|
// src/components/incrementalParse/mdLineText.ts
|
|
179
222
|
var MD_BLANK_RE = /^[ \t\r]*$/;
|
|
@@ -181,6 +224,9 @@ var isMdBlank = (text) => MD_BLANK_RE.test(text);
|
|
|
181
224
|
var mdTrim = (text) => text.replace(/^[ \t\r]+|[ \t\r]+$/g, "");
|
|
182
225
|
var mdTrimStart = (text) => text.replace(/^[ \t\r]+/, "");
|
|
183
226
|
|
|
227
|
+
// src/components/incrementalParse/freezeLineSyntax.ts
|
|
228
|
+
import { htmlBlockNames } from "micromark-util-html-tag-name";
|
|
229
|
+
|
|
184
230
|
// src/components/incrementalParse/referenceTaint.ts
|
|
185
231
|
import { normalizeIdentifier } from "micromark-util-normalize-identifier";
|
|
186
232
|
var FOOTNOTE_DEF_RE = /^ {0,3}\[\^[^\]]*\]:/;
|
|
@@ -366,7 +412,7 @@ function settleRefsAndEarliestUnresolved(cp) {
|
|
|
366
412
|
return earliestUnresolved;
|
|
367
413
|
}
|
|
368
414
|
|
|
369
|
-
// src/components/incrementalParse/
|
|
415
|
+
// src/components/incrementalParse/freezeLineSyntax.ts
|
|
370
416
|
var TYPE6_NAMES = new Set(htmlBlockNames);
|
|
371
417
|
var TABLE_PART_NAMES = /* @__PURE__ */ new Set(["td", "th", "tr", "tbody", "thead", "tfoot", "caption", "col", "colgroup"]);
|
|
372
418
|
var DOCUMENT_STRUCTURE_NAMES = /* @__PURE__ */ new Set(["html", "head", "body", "frameset"]);
|
|
@@ -618,43 +664,6 @@ function maskIntraLineCodeSpans(text, carryOpen) {
|
|
|
618
664
|
out += text.slice(cursor);
|
|
619
665
|
return { masked: out, unpaired: false };
|
|
620
666
|
}
|
|
621
|
-
function freshCheckpoint(defListEnabled, mathFlow, referenceTaint) {
|
|
622
|
-
return {
|
|
623
|
-
defListEnabled,
|
|
624
|
-
mathFlow,
|
|
625
|
-
referenceTaint,
|
|
626
|
-
confirmedOffset: 0,
|
|
627
|
-
candidates: [],
|
|
628
|
-
defs: /* @__PURE__ */ new Map(),
|
|
629
|
-
footnoteDefs: /* @__PURE__ */ new Map(),
|
|
630
|
-
unresolvedRefs: [],
|
|
631
|
-
tagBalance: /* @__PURE__ */ new Map(),
|
|
632
|
-
openTotal: 0,
|
|
633
|
-
p5Tok: { kind: "data" },
|
|
634
|
-
formPointerMaybeSet: false,
|
|
635
|
-
openStack: [],
|
|
636
|
-
mdBlock: { kind: "none" },
|
|
637
|
-
blankRun: 0,
|
|
638
|
-
lastBlankStart: -1,
|
|
639
|
-
hazardVerdict: false,
|
|
640
|
-
prevLineBlank: true,
|
|
641
|
-
// doc start counts as a block start
|
|
642
|
-
prevLineWasText: false,
|
|
643
|
-
prevLineWasValidDef: false,
|
|
644
|
-
prevLineOpenContent: false,
|
|
645
|
-
tableMaybeOpen: false,
|
|
646
|
-
containerMaybeOpen: false,
|
|
647
|
-
paragraphHasUnpairedRun: false,
|
|
648
|
-
openBracket: null,
|
|
649
|
-
p5SealPending: false,
|
|
650
|
-
defBlockMaybeOpen: false,
|
|
651
|
-
fnDefResumable: false,
|
|
652
|
-
phasePoisonedAt: Infinity,
|
|
653
|
-
pendingTruncatedTags: [],
|
|
654
|
-
pendingTruncatedCloses: [],
|
|
655
|
-
pendingTag: null
|
|
656
|
-
};
|
|
657
|
-
}
|
|
658
667
|
function classifyBlockStart(text, indent, defListEnabled) {
|
|
659
668
|
if (indent >= 4) return true;
|
|
660
669
|
if (LIST_MARKER_RE.test(text) || FOOTNOTE_DEF_RE.test(text)) return true;
|
|
@@ -662,71 +671,23 @@ function classifyBlockStart(text, indent, defListEnabled) {
|
|
|
662
671
|
if (indent === 0) return false;
|
|
663
672
|
return null;
|
|
664
673
|
}
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
textEnd = nl;
|
|
683
|
-
end = nl;
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
const confirmed = end < text.length && !(end === text.length - 1 && text.charCodeAt(end) === 13);
|
|
687
|
-
const lineText = text.slice(start, textEnd);
|
|
688
|
-
const ln = {
|
|
689
|
-
start,
|
|
690
|
-
end,
|
|
691
|
-
text: lineText,
|
|
692
|
-
blank: confirmed && isMdBlank(lineText),
|
|
693
|
-
indent: computeIndent(lineText)
|
|
694
|
-
};
|
|
695
|
-
if (!confirmed) {
|
|
696
|
-
tailLine = ln;
|
|
697
|
-
break;
|
|
698
|
-
}
|
|
699
|
-
processConfirmedLine(cp, ln, text);
|
|
700
|
-
cp.confirmedOffset = end + 1;
|
|
701
|
-
start = end + 1;
|
|
702
|
-
}
|
|
703
|
-
const earliestUnresolved = settleRefsAndEarliestUnresolved(cp);
|
|
704
|
-
const defListSettled = (c) => {
|
|
705
|
-
if (!options.defListEnabled || c.blankRun >= 2) return true;
|
|
706
|
-
if (c.defListSettled !== null) return c.defListSettled;
|
|
707
|
-
if (tailLine) return !canBecomeDdLine(tailLine.text, false);
|
|
708
|
-
return false;
|
|
709
|
-
};
|
|
710
|
-
const tailRetroactive = tailLine !== null && tailCarriesRetroactive(tailLine.text);
|
|
711
|
-
let boundary = 0;
|
|
712
|
-
for (let i = cp.candidates.length - 1; i >= 0 && !tailRetroactive; i--) {
|
|
713
|
-
const c = cp.candidates[i];
|
|
714
|
-
if (!c.htmlBalanced || c.hazard || c.seamRisk) continue;
|
|
715
|
-
if (c.offset > cp.phasePoisonedAt) continue;
|
|
716
|
-
if (c.offset > earliestUnresolved) continue;
|
|
717
|
-
if (!defListSettled(c)) continue;
|
|
718
|
-
boundary = c.offset;
|
|
719
|
-
break;
|
|
720
|
-
}
|
|
721
|
-
return { boundary, checkpoint: cp };
|
|
722
|
-
}
|
|
723
|
-
function pendingFenceCloser(checkpoint) {
|
|
724
|
-
const cp = checkpoint;
|
|
725
|
-
if (cp.phasePoisonedAt !== Infinity) return "";
|
|
726
|
-
if (cp.mdBlock.kind === "fence" && cp.mdBlock.indent === 0) return cp.mdBlock.char.repeat(cp.mdBlock.len);
|
|
727
|
-
if (cp.mdBlock.kind === "math" && cp.mdBlock.indent === 0) return "$".repeat(cp.mdBlock.len);
|
|
728
|
-
return "";
|
|
729
|
-
}
|
|
674
|
+
var SCANNER_NAME_LISTS = [
|
|
675
|
+
["type1", TYPE1_NAMES],
|
|
676
|
+
["rawText", RAW_TEXT_ELEMENTS],
|
|
677
|
+
["type6", TYPE6_NAMES],
|
|
678
|
+
["void", VOID_TAGS],
|
|
679
|
+
["documentStructure", DOCUMENT_STRUCTURE_NAMES],
|
|
680
|
+
// Added with F28, and it is the list that would have made F28 visible: the
|
|
681
|
+
// derived census alphabet partitions names by their membership across THIS
|
|
682
|
+
// table, so before it existed `frame` shared one 39-name class with `div`
|
|
683
|
+
// and could never be sampled apart from it.
|
|
684
|
+
["noElement", NO_ELEMENT_NAMES],
|
|
685
|
+
["tablePart", TABLE_PART_NAMES],
|
|
686
|
+
["scopeBarrier", SCOPE_BARRIER_NAMES],
|
|
687
|
+
["foreignRoot", new Set(FOREIGN_ROOT_NAMES)]
|
|
688
|
+
];
|
|
689
|
+
|
|
690
|
+
// src/components/incrementalParse/freezeLineTransition.ts
|
|
730
691
|
function floatingResidue(text, commentOpenAtStart) {
|
|
731
692
|
let out = "";
|
|
732
693
|
let open = commentOpenAtStart;
|
|
@@ -1376,24 +1337,66 @@ function processConfirmedLine(cp, ln, text) {
|
|
|
1376
1337
|
}
|
|
1377
1338
|
}
|
|
1378
1339
|
}
|
|
1379
|
-
var SCANNER_NAME_LISTS = [
|
|
1380
|
-
["type1", TYPE1_NAMES],
|
|
1381
|
-
["rawText", RAW_TEXT_ELEMENTS],
|
|
1382
|
-
["type6", TYPE6_NAMES],
|
|
1383
|
-
["void", VOID_TAGS],
|
|
1384
|
-
["documentStructure", DOCUMENT_STRUCTURE_NAMES],
|
|
1385
|
-
// Added with F28, and it is the list that would have made F28 visible: the
|
|
1386
|
-
// derived census alphabet partitions names by their membership across THIS
|
|
1387
|
-
// table, so before it existed `frame` shared one 39-name class with `div`
|
|
1388
|
-
// and could never be sampled apart from it.
|
|
1389
|
-
["noElement", NO_ELEMENT_NAMES],
|
|
1390
|
-
["tablePart", TABLE_PART_NAMES],
|
|
1391
|
-
["scopeBarrier", SCOPE_BARRIER_NAMES],
|
|
1392
|
-
["foreignRoot", new Set(FOREIGN_ROOT_NAMES)]
|
|
1393
|
-
];
|
|
1394
1340
|
|
|
1395
|
-
// src/components/incrementalParse/
|
|
1396
|
-
|
|
1341
|
+
// src/components/incrementalParse/computeFreezeBoundary.ts
|
|
1342
|
+
function computeFreezeBoundary(text, options, resume) {
|
|
1343
|
+
const mathFlow = options.mathFlow ?? true;
|
|
1344
|
+
const referenceTaint = options.referenceTaint ?? true;
|
|
1345
|
+
const prev = resume;
|
|
1346
|
+
const cp = prev && prev.defListEnabled === options.defListEnabled && prev.mathFlow === mathFlow && prev.referenceTaint === referenceTaint && prev.confirmedOffset <= text.length ? prev : freshCheckpoint(options.defListEnabled, mathFlow, referenceTaint);
|
|
1347
|
+
let start = cp.confirmedOffset;
|
|
1348
|
+
let tailLine = null;
|
|
1349
|
+
while (start < text.length) {
|
|
1350
|
+
let end = text.length;
|
|
1351
|
+
let textEnd = text.length;
|
|
1352
|
+
{
|
|
1353
|
+
const nl = text.indexOf("\n", start);
|
|
1354
|
+
const cr = text.indexOf("\r", start);
|
|
1355
|
+
if (cr !== -1 && (nl === -1 || cr < nl)) {
|
|
1356
|
+
textEnd = cr;
|
|
1357
|
+
end = text.charCodeAt(cr + 1) === 10 ? cr + 1 : cr;
|
|
1358
|
+
} else if (nl !== -1) {
|
|
1359
|
+
textEnd = nl;
|
|
1360
|
+
end = nl;
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
const confirmed = end < text.length && !(end === text.length - 1 && text.charCodeAt(end) === 13);
|
|
1364
|
+
const lineText = text.slice(start, textEnd);
|
|
1365
|
+
const ln = {
|
|
1366
|
+
start,
|
|
1367
|
+
end,
|
|
1368
|
+
text: lineText,
|
|
1369
|
+
blank: confirmed && isMdBlank(lineText),
|
|
1370
|
+
indent: computeIndent(lineText)
|
|
1371
|
+
};
|
|
1372
|
+
if (!confirmed) {
|
|
1373
|
+
tailLine = ln;
|
|
1374
|
+
break;
|
|
1375
|
+
}
|
|
1376
|
+
processConfirmedLine(cp, ln, text);
|
|
1377
|
+
cp.confirmedOffset = end + 1;
|
|
1378
|
+
start = end + 1;
|
|
1379
|
+
}
|
|
1380
|
+
const earliestUnresolved = settleRefsAndEarliestUnresolved(cp);
|
|
1381
|
+
const defListSettled = (c) => {
|
|
1382
|
+
if (!options.defListEnabled || c.blankRun >= 2) return true;
|
|
1383
|
+
if (c.defListSettled !== null) return c.defListSettled;
|
|
1384
|
+
if (tailLine) return !canBecomeDdLine(tailLine.text, false);
|
|
1385
|
+
return false;
|
|
1386
|
+
};
|
|
1387
|
+
const tailRetroactive = tailLine !== null && tailCarriesRetroactive(tailLine.text);
|
|
1388
|
+
let boundary = 0;
|
|
1389
|
+
for (let i = cp.candidates.length - 1; i >= 0 && !tailRetroactive; i--) {
|
|
1390
|
+
const c = cp.candidates[i];
|
|
1391
|
+
if (!c.htmlBalanced || c.hazard || c.seamRisk) continue;
|
|
1392
|
+
if (c.offset > cp.phasePoisonedAt) continue;
|
|
1393
|
+
if (c.offset > earliestUnresolved) continue;
|
|
1394
|
+
if (!defListSettled(c)) continue;
|
|
1395
|
+
boundary = c.offset;
|
|
1396
|
+
break;
|
|
1397
|
+
}
|
|
1398
|
+
return { boundary, checkpoint: cp };
|
|
1399
|
+
}
|
|
1397
1400
|
|
|
1398
1401
|
// src/components/hastPredicates.ts
|
|
1399
1402
|
function isFootnoteSection(node) {
|
|
@@ -1441,121 +1444,7 @@ function attributeHastChildren(mdast, hast, stopAt = Infinity) {
|
|
|
1441
1444
|
}
|
|
1442
1445
|
}
|
|
1443
1446
|
|
|
1444
|
-
// src/components/incrementalParse/
|
|
1445
|
-
function collectPrefixInjection(mdast, content, boundary, resume) {
|
|
1446
|
-
const resumeValid = resume != null && resume.boundary <= boundary;
|
|
1447
|
-
if (resumeValid && resume.uninjectable) return { events: resume.events, uninjectable: true };
|
|
1448
|
-
const resumeAt = resumeValid ? resume.boundary : 0;
|
|
1449
|
-
const events = resumeAt > 0 ? cloneEventsForAppend(resume.events) : [];
|
|
1450
|
-
let uninjectable = false;
|
|
1451
|
-
let cacheable = true;
|
|
1452
|
-
const pushRef = (token) => {
|
|
1453
|
-
const last = events[events.length - 1];
|
|
1454
|
-
if (last && last.kind === "refs") last.tokens.push(token);
|
|
1455
|
-
else events.push({ kind: "refs", tokens: [token] });
|
|
1456
|
-
};
|
|
1457
|
-
const visit7 = (node, nested) => {
|
|
1458
|
-
const type = node.type;
|
|
1459
|
-
if (type === "definition") {
|
|
1460
|
-
const start = node.position?.start?.offset;
|
|
1461
|
-
const end = node.position?.end?.offset;
|
|
1462
|
-
if (start !== void 0 && end !== void 0 && start < boundary) {
|
|
1463
|
-
const slice = content.slice(start, end);
|
|
1464
|
-
if (nested && slice.includes("\n")) uninjectable = true;
|
|
1465
|
-
else events.push({ kind: "def", source: slice });
|
|
1466
|
-
}
|
|
1467
|
-
return;
|
|
1468
|
-
}
|
|
1469
|
-
if (type === "footnoteDefinition") {
|
|
1470
|
-
const start = node.position?.start;
|
|
1471
|
-
const end = node.position?.end?.offset;
|
|
1472
|
-
if (start?.offset === void 0 || end === void 0 || start.offset >= boundary) return;
|
|
1473
|
-
if (nested) {
|
|
1474
|
-
uninjectable = true;
|
|
1475
|
-
return;
|
|
1476
|
-
}
|
|
1477
|
-
const lineStart = start.offset - (start.column - 1);
|
|
1478
|
-
events.push({
|
|
1479
|
-
kind: "footnoteDef",
|
|
1480
|
-
source: content.slice(lineStart, end),
|
|
1481
|
-
origStart: lineStart,
|
|
1482
|
-
origLine: start.line
|
|
1483
|
-
});
|
|
1484
|
-
return;
|
|
1485
|
-
}
|
|
1486
|
-
if (type === "footnoteReference") {
|
|
1487
|
-
const start = node.position?.start?.offset;
|
|
1488
|
-
const end = node.position?.end?.offset;
|
|
1489
|
-
if (start === void 0 || end === void 0) {
|
|
1490
|
-
uninjectable = true;
|
|
1491
|
-
return;
|
|
1492
|
-
}
|
|
1493
|
-
pushRef(content.slice(start, end));
|
|
1494
|
-
return;
|
|
1495
|
-
}
|
|
1496
|
-
const children = node.children;
|
|
1497
|
-
if (children) {
|
|
1498
|
-
for (const child of children) visit7(child, true);
|
|
1499
|
-
}
|
|
1500
|
-
};
|
|
1501
|
-
let lastStart = -1;
|
|
1502
|
-
for (const child of mdast.children) {
|
|
1503
|
-
const start = child.position?.start?.offset;
|
|
1504
|
-
if (start !== void 0) {
|
|
1505
|
-
if (start < lastStart) return { events: [], uninjectable: true, cacheable: false };
|
|
1506
|
-
lastStart = start;
|
|
1507
|
-
}
|
|
1508
|
-
if (start === void 0) {
|
|
1509
|
-
if (resumeAt > 0) return collectPrefixInjection(mdast, content, boundary, null);
|
|
1510
|
-
cacheable = false;
|
|
1511
|
-
visit7(child, false);
|
|
1512
|
-
continue;
|
|
1513
|
-
}
|
|
1514
|
-
if (start >= boundary || start < resumeAt) continue;
|
|
1515
|
-
visit7(child, false);
|
|
1516
|
-
}
|
|
1517
|
-
return { events, uninjectable, cacheable };
|
|
1518
|
-
}
|
|
1519
|
-
function cloneEventsForAppend(events) {
|
|
1520
|
-
const out = events.slice();
|
|
1521
|
-
const last = out[out.length - 1];
|
|
1522
|
-
if (last && last.kind === "refs") out[out.length - 1] = { kind: "refs", tokens: last.tokens.slice() };
|
|
1523
|
-
return out;
|
|
1524
|
-
}
|
|
1525
|
-
var TERMINATOR_LABEL = "__aimd_injection_terminator__";
|
|
1526
|
-
var INJECTION_TERMINATOR = `[${TERMINATOR_LABEL}]: __aimd_sentinel_link__`;
|
|
1527
|
-
function tailMentionsTerminator(tailSource) {
|
|
1528
|
-
return normalizeIdentifier2(tailSource).replace(/\[ /g, "[").includes(`[${normalizeIdentifier2(TERMINATOR_LABEL)}`);
|
|
1529
|
-
}
|
|
1530
|
-
function buildInjectionPrefix(events) {
|
|
1531
|
-
if (events.length === 0) return { text: "", segments: [] };
|
|
1532
|
-
let text = "";
|
|
1533
|
-
let line = 1;
|
|
1534
|
-
const segments = [];
|
|
1535
|
-
for (const event of events) {
|
|
1536
|
-
if (text.length > 0) {
|
|
1537
|
-
text += "\n\n";
|
|
1538
|
-
line += 2;
|
|
1539
|
-
}
|
|
1540
|
-
const injStart = text.length;
|
|
1541
|
-
const source = event.kind === "refs" ? event.tokens.join(" ") : event.source;
|
|
1542
|
-
if (event.kind === "footnoteDef") {
|
|
1543
|
-
segments.push({
|
|
1544
|
-
injStart,
|
|
1545
|
-
injEnd: injStart + source.length,
|
|
1546
|
-
offsetDelta: event.origStart - injStart,
|
|
1547
|
-
lineDelta: event.origLine - line
|
|
1548
|
-
});
|
|
1549
|
-
}
|
|
1550
|
-
text += source;
|
|
1551
|
-
line += countNewlines(source);
|
|
1552
|
-
}
|
|
1553
|
-
return { text: `${text}
|
|
1554
|
-
|
|
1555
|
-
${INJECTION_TERMINATOR}
|
|
1556
|
-
|
|
1557
|
-
`, segments };
|
|
1558
|
-
}
|
|
1447
|
+
// src/components/incrementalParse/spliceCoordinates.ts
|
|
1559
1448
|
function rebaseTree(node, offsetDelta, lineDelta) {
|
|
1560
1449
|
rebaseTreeDual(node, EMPTY_SEGMENTS, offsetDelta, lineDelta);
|
|
1561
1450
|
}
|
|
@@ -1584,6 +1473,23 @@ function rebaseDualWalk(node, segments, maxEnd, offsetDelta, lineDelta) {
|
|
|
1584
1473
|
for (const child of children) rebaseDualWalk(child, segments, maxEnd, offsetDelta, lineDelta);
|
|
1585
1474
|
}
|
|
1586
1475
|
}
|
|
1476
|
+
function rebasePoint(point, offsetDelta, lineDelta) {
|
|
1477
|
+
return {
|
|
1478
|
+
line: point.line + lineDelta,
|
|
1479
|
+
column: point.column,
|
|
1480
|
+
offset: point.offset !== void 0 ? point.offset + offsetDelta : void 0
|
|
1481
|
+
};
|
|
1482
|
+
}
|
|
1483
|
+
function countNewlines(text, end = text.length) {
|
|
1484
|
+
let count = 0;
|
|
1485
|
+
for (let i = text.indexOf("\n"); i !== -1 && i < end; i = text.indexOf("\n", i + 1)) count += 1;
|
|
1486
|
+
for (let i = text.indexOf("\r"); i !== -1 && i < end; i = text.indexOf("\r", i + 1)) {
|
|
1487
|
+
if (text.charCodeAt(i + 1) !== 10) count += 1;
|
|
1488
|
+
}
|
|
1489
|
+
return count;
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
// src/components/incrementalParse/spliceHtmlGuards.ts
|
|
1587
1493
|
var TABLE_PART_TAG_RE = /<(?:td|th|tr|tbody|thead|tfoot|caption|col|colgroup)\b/i;
|
|
1588
1494
|
var TABLE_TOKEN_RE = /<(\/?)(table|td|th|tr|tbody|thead|tfoot|caption|col|colgroup)\b/gi;
|
|
1589
1495
|
function hasStrayTablePart(values) {
|
|
@@ -1665,127 +1571,26 @@ function rawTextRegionCrossesOut(values) {
|
|
|
1665
1571
|
}
|
|
1666
1572
|
return false;
|
|
1667
1573
|
}
|
|
1668
|
-
function
|
|
1669
|
-
const
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
}
|
|
1680
|
-
const attrs = attributeHastChildren(prevMdast, prevHast, boundary);
|
|
1681
|
-
const cutRegion = [];
|
|
1682
|
-
for (let i = 0; i < prevHast.children.length; i++) {
|
|
1683
|
-
if (attrs[i] < boundary) {
|
|
1684
|
-
const node2 = prevHast.children[i];
|
|
1685
|
-
const end = node2.position?.end?.offset;
|
|
1686
|
-
if (end !== void 0 && end > boundary) return null;
|
|
1687
|
-
if (isTrailingLiteralText(node2)) {
|
|
1688
|
-
const prev = i > 0 ? prevHast.children[i - 1] : void 0;
|
|
1689
|
-
if (!prev || prev.type !== "element" || prev.position === void 0) return null;
|
|
1690
|
-
if (!ownsTrailingLiteral(prev, node2, prefixMdast))
|
|
1691
|
-
return null;
|
|
1692
|
-
}
|
|
1693
|
-
cutRegion.push(node2);
|
|
1694
|
-
continue;
|
|
1695
|
-
}
|
|
1696
|
-
const node = prevHast.children[i];
|
|
1697
|
-
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
|
|
1698
|
-
// raw literal can only trail an `html` mdast node. A position-less
|
|
1699
|
-
// text after a `<p>` is the NEXT block's remnant — a stray end tag
|
|
1700
|
-
// (`</t>\na`) parse5 dropped, whose text merged with the wrap
|
|
1701
|
-
// separator — owned by the tail, which re-parses it; freezing it
|
|
1702
|
-
// here duplicated it (v2.4.0 review P3). Falls through to the
|
|
1703
|
-
// remnant look-ahead below, which bails to a full parse. And the
|
|
1704
|
-
// literal must really be THAT block's trailing text: the block's raw
|
|
1705
|
-
// source ends with it. A dropped-tag block right after a frozen html
|
|
1706
|
-
// element (`</details>\n\n</t>\ntext`) puts its remnant in the same
|
|
1707
|
-
// position, and freezing it duplicated it (release soak of the fix).
|
|
1708
|
-
ownsTrailingLiteral(prevHast.children[i - 1], node, prefixMdast)) {
|
|
1709
|
-
cutRegion.push(node);
|
|
1710
|
-
break;
|
|
1711
|
-
}
|
|
1712
|
-
for (let j = i; j < prevHast.children.length; j++) {
|
|
1713
|
-
const look = prevHast.children[j];
|
|
1714
|
-
if (look.type === "element" || look.position !== void 0) break;
|
|
1715
|
-
if (isTrailingLiteralText(look)) return null;
|
|
1716
|
-
}
|
|
1717
|
-
break;
|
|
1718
|
-
}
|
|
1719
|
-
const tailMdastChildren = tailMdast.children.filter((child) => {
|
|
1720
|
-
const start = child.position?.start?.offset;
|
|
1721
|
-
return !(start !== void 0 && start < injectedLen);
|
|
1722
|
-
});
|
|
1723
|
-
const tailWrapVisible = tailMdastChildren.some((child) => !isWrapInvisible(child));
|
|
1724
|
-
const prefixHtmlValues = prefixMdast.flatMap((c) => c.type === "html" ? [c.value] : []);
|
|
1725
|
-
if (hasStrayTablePart(prefixHtmlValues)) return null;
|
|
1726
|
-
if (rawTextRegionCrossesOut(prefixHtmlValues)) return null;
|
|
1727
|
-
const leadingHtml = [];
|
|
1728
|
-
for (const child of tailMdastChildren) {
|
|
1729
|
-
if (isWrapInvisible(child)) continue;
|
|
1730
|
-
if (child.type !== "html") break;
|
|
1731
|
-
if (STRAY_SYNTHESIZED_END_TAG_RE.test(child.value) || TABLE_PART_TAG_RE.test(child.value)) return null;
|
|
1732
|
-
leadingHtml.push(child.value);
|
|
1574
|
+
function isSanitizeStrippedConstruct(value) {
|
|
1575
|
+
const v = value.trim();
|
|
1576
|
+
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(">");
|
|
1577
|
+
}
|
|
1578
|
+
function isExactSanitizeStrippedConstruct(value) {
|
|
1579
|
+
if (value.startsWith("<!--")) {
|
|
1580
|
+
if (value.length < 7 || !value.endsWith("-->")) return false;
|
|
1581
|
+
const close = value.indexOf("-->", 4);
|
|
1582
|
+
const bangClose = value.indexOf("--!>", 4);
|
|
1583
|
+
if (close !== value.length - 3) return false;
|
|
1584
|
+
return bangClose === -1 || bangClose > close;
|
|
1733
1585
|
}
|
|
1734
|
-
if (
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
const hastChildren = aligned.children;
|
|
1738
|
-
const interiorFinalLiteral = aligned.interiorFinalLiteral;
|
|
1739
|
-
const stripResult = stripInjectedHast(tailMdast, tailHast, injectedLen, tailWrapVisible);
|
|
1740
|
-
if (stripResult === null) return null;
|
|
1741
|
-
const strippedTailHast = stripResult.rest;
|
|
1742
|
-
for (const child of tailMdastChildren) rebaseTree(child, offsetDelta, lineDelta);
|
|
1743
|
-
for (const child of strippedTailHast) rebaseTreeDual(child, injectedSegments, offsetDelta, lineDelta);
|
|
1744
|
-
const mdastChildren = prefixMdast.concat(tailMdastChildren);
|
|
1745
|
-
const seamMergeVerdict = stripResult.remnantMerged ?? tailLeadingTextIsHoist(tailMdastChildren, strippedTailHast);
|
|
1746
|
-
if (seamMergeVerdict === null) return null;
|
|
1747
|
-
const seamMergeAllowed = seamMergeVerdict;
|
|
1748
|
-
let firstTailChild = true;
|
|
1749
|
-
for (const child of strippedTailHast) {
|
|
1750
|
-
const tailEnd = hastChildren[hastChildren.length - 1];
|
|
1751
|
-
if (firstTailChild && child.type === "text" && child.position !== void 0) {
|
|
1752
|
-
return null;
|
|
1753
|
-
}
|
|
1754
|
-
if (firstTailChild && tailEnd && tailEnd.type === "text" && child.type === "text" && child.position === void 0) {
|
|
1755
|
-
if (interiorFinalLiteral && tailEnd.value.trim() !== "") {
|
|
1756
|
-
if (seamMergeAllowed) return null;
|
|
1757
|
-
firstTailChild = false;
|
|
1758
|
-
hastChildren.push(child);
|
|
1759
|
-
continue;
|
|
1760
|
-
}
|
|
1761
|
-
const literalSeam = tailEnd.value.trim() !== "" && !tailWrapVisible;
|
|
1762
|
-
if (seamMergeAllowed || literalSeam) {
|
|
1763
|
-
hastChildren[hastChildren.length - 1] = { type: "text", value: tailEnd.value + child.value };
|
|
1764
|
-
firstTailChild = false;
|
|
1765
|
-
continue;
|
|
1766
|
-
}
|
|
1767
|
-
}
|
|
1768
|
-
firstTailChild = false;
|
|
1769
|
-
hastChildren.push(child);
|
|
1586
|
+
if (/^<!doctype/i.test(value)) return false;
|
|
1587
|
+
if (value.startsWith("<?") || /^<!(?:[A-Za-z]|\[CDATA\[)/.test(value)) {
|
|
1588
|
+
return value.indexOf(">") === value.length - 1;
|
|
1770
1589
|
}
|
|
1771
|
-
|
|
1772
|
-
const docStart = { line: 1, column: 1, offset: 0 };
|
|
1773
|
-
const mdastRootPosition = tailMdast.position ? { start: docStart, end: rebasePoint(tailMdast.position.end, offsetDelta, lineDelta) } : prevMdast.position;
|
|
1774
|
-
const hastRootPosition = mdastRootPosition;
|
|
1775
|
-
const mdast = { type: "root", children: mdastChildren };
|
|
1776
|
-
if (mdastRootPosition) mdast.position = mdastRootPosition;
|
|
1777
|
-
const hast = { type: "root", children: hastChildren };
|
|
1778
|
-
if (hastRootPosition) hast.position = hastRootPosition;
|
|
1779
|
-
if (prevHast.data !== void 0) hast.data = prevHast.data;
|
|
1780
|
-
return { mdast, hast };
|
|
1781
|
-
}
|
|
1782
|
-
function rebasePoint(point, offsetDelta, lineDelta) {
|
|
1783
|
-
return {
|
|
1784
|
-
line: point.line + lineDelta,
|
|
1785
|
-
column: point.column,
|
|
1786
|
-
offset: point.offset !== void 0 ? point.offset + offsetDelta : void 0
|
|
1787
|
-
};
|
|
1590
|
+
return false;
|
|
1788
1591
|
}
|
|
1592
|
+
|
|
1593
|
+
// src/components/incrementalParse/prefixAlignment.ts
|
|
1789
1594
|
function isWrapInvisible(node) {
|
|
1790
1595
|
return node.type === "definition" || node.type === "footnoteDefinition";
|
|
1791
1596
|
}
|
|
@@ -1927,96 +1732,303 @@ function stripInjectedHast(tailMdast, tailHast, injectedLen, tailWrapVisible) {
|
|
|
1927
1732
|
idx += 1;
|
|
1928
1733
|
continue;
|
|
1929
1734
|
}
|
|
1930
|
-
const start = node.position?.start?.offset;
|
|
1931
|
-
if (start === void 0 || start >= injectedLen) return null;
|
|
1932
|
-
consumed += 1;
|
|
1933
|
-
idx += 1;
|
|
1934
|
-
}
|
|
1935
|
-
if (consumed < injectedVisibleCount) return null;
|
|
1936
|
-
let remnant = "";
|
|
1937
|
-
let remnantMerged = null;
|
|
1938
|
-
if (tailWrapVisible) {
|
|
1939
|
-
const gap = children[idx];
|
|
1940
|
-
if (!gap || !isSeparatorText(gap)) return null;
|
|
1941
|
-
remnant = gap.value.slice(1);
|
|
1942
|
-
remnantMerged = remnant !== "";
|
|
1943
|
-
idx += 1;
|
|
1735
|
+
const start = node.position?.start?.offset;
|
|
1736
|
+
if (start === void 0 || start >= injectedLen) return null;
|
|
1737
|
+
consumed += 1;
|
|
1738
|
+
idx += 1;
|
|
1739
|
+
}
|
|
1740
|
+
if (consumed < injectedVisibleCount) return null;
|
|
1741
|
+
let remnant = "";
|
|
1742
|
+
let remnantMerged = null;
|
|
1743
|
+
if (tailWrapVisible) {
|
|
1744
|
+
const gap = children[idx];
|
|
1745
|
+
if (!gap || !isSeparatorText(gap)) return null;
|
|
1746
|
+
remnant = gap.value.slice(1);
|
|
1747
|
+
remnantMerged = remnant !== "";
|
|
1748
|
+
idx += 1;
|
|
1749
|
+
}
|
|
1750
|
+
const rest = children.slice(idx);
|
|
1751
|
+
if (remnant !== "") rest.unshift({ type: "text", value: remnant });
|
|
1752
|
+
return { rest, remnantMerged };
|
|
1753
|
+
}
|
|
1754
|
+
function tailLeadingTextIsHoist(tailMdastChildren, tailHastChildren) {
|
|
1755
|
+
const firstText = tailHastChildren[0];
|
|
1756
|
+
const firstVisible = tailMdastChildren.find((c) => !isWrapInvisible(c));
|
|
1757
|
+
if (firstVisible?.type === "html" && STRAY_SYNTHESIZED_END_TAG_RE.test(firstVisible.value)) return null;
|
|
1758
|
+
if (!firstText) return false;
|
|
1759
|
+
if (!isSeparatorText(firstText)) {
|
|
1760
|
+
if (firstText.type === "text" && firstText.position === void 0 && firstVisible?.type === "html") {
|
|
1761
|
+
if (/^\s*<\/[A-Za-z][A-Za-z0-9-]*\s*>/.test(firstVisible.value)) return true;
|
|
1762
|
+
if (isSanitizeStrippedConstruct(firstVisible.value)) return false;
|
|
1763
|
+
return null;
|
|
1764
|
+
}
|
|
1765
|
+
return false;
|
|
1766
|
+
}
|
|
1767
|
+
if (!firstVisible) return false;
|
|
1768
|
+
const firstContent = tailHastChildren.find((c) => !isSeparatorText(c));
|
|
1769
|
+
if (firstContent) {
|
|
1770
|
+
const start = firstContent.position?.start?.offset;
|
|
1771
|
+
const vStart = firstVisible.position?.start?.offset;
|
|
1772
|
+
const vEnd = firstVisible.position?.end?.offset;
|
|
1773
|
+
if (start !== void 0 && vStart !== void 0 && vEnd !== void 0) {
|
|
1774
|
+
if (start >= vStart && start < vEnd) return true;
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
if (firstVisible.type === "math") return false;
|
|
1778
|
+
if (firstVisible.type === "html" && isSanitizeStrippedConstruct(firstVisible.value)) return false;
|
|
1779
|
+
return null;
|
|
1780
|
+
}
|
|
1781
|
+
function isSeparatorText(node) {
|
|
1782
|
+
return node.type === "text" && node.position === void 0 && node.value.trim() === "";
|
|
1783
|
+
}
|
|
1784
|
+
function ownsTrailingLiteral(el, literal, prefixMdast) {
|
|
1785
|
+
const start = el.position?.start?.offset;
|
|
1786
|
+
if (start === void 0) return false;
|
|
1787
|
+
const owner = prefixMdast.find((c) => c.type === "html" && c.position?.start?.offset === start);
|
|
1788
|
+
if (!owner || owner.type !== "html") return false;
|
|
1789
|
+
const text = literal.value.trim();
|
|
1790
|
+
return text !== "" && owner.value.trimEnd().endsWith(text);
|
|
1791
|
+
}
|
|
1792
|
+
function isTrailingLiteralText(node) {
|
|
1793
|
+
return node.type === "text" && node.position === void 0 && node.value.trim() !== "";
|
|
1794
|
+
}
|
|
1795
|
+
function countTrailingNewlines(value) {
|
|
1796
|
+
let n = 0;
|
|
1797
|
+
for (let i = value.length - 1; i >= 0 && value[i] === "\n"; i--) n += 1;
|
|
1798
|
+
return n;
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
// src/components/incrementalParse/prefixInjection.ts
|
|
1802
|
+
import { normalizeIdentifier as normalizeIdentifier2 } from "micromark-util-normalize-identifier";
|
|
1803
|
+
function collectPrefixInjection(mdast, content, boundary, resume) {
|
|
1804
|
+
const resumeValid = resume != null && resume.boundary <= boundary;
|
|
1805
|
+
if (resumeValid && resume.uninjectable) return { events: resume.events, uninjectable: true };
|
|
1806
|
+
const resumeAt = resumeValid ? resume.boundary : 0;
|
|
1807
|
+
const events = resumeAt > 0 ? cloneEventsForAppend(resume.events) : [];
|
|
1808
|
+
let uninjectable = false;
|
|
1809
|
+
let cacheable = true;
|
|
1810
|
+
const pushRef = (token) => {
|
|
1811
|
+
const last = events[events.length - 1];
|
|
1812
|
+
if (last && last.kind === "refs") last.tokens.push(token);
|
|
1813
|
+
else events.push({ kind: "refs", tokens: [token] });
|
|
1814
|
+
};
|
|
1815
|
+
const visit7 = (node, nested) => {
|
|
1816
|
+
const type = node.type;
|
|
1817
|
+
if (type === "definition") {
|
|
1818
|
+
const start = node.position?.start?.offset;
|
|
1819
|
+
const end = node.position?.end?.offset;
|
|
1820
|
+
if (start !== void 0 && end !== void 0 && start < boundary) {
|
|
1821
|
+
const slice = content.slice(start, end);
|
|
1822
|
+
if (nested && slice.includes("\n")) uninjectable = true;
|
|
1823
|
+
else events.push({ kind: "def", source: slice });
|
|
1824
|
+
}
|
|
1825
|
+
return;
|
|
1826
|
+
}
|
|
1827
|
+
if (type === "footnoteDefinition") {
|
|
1828
|
+
const start = node.position?.start;
|
|
1829
|
+
const end = node.position?.end?.offset;
|
|
1830
|
+
if (start?.offset === void 0 || end === void 0 || start.offset >= boundary) return;
|
|
1831
|
+
if (nested) {
|
|
1832
|
+
uninjectable = true;
|
|
1833
|
+
return;
|
|
1834
|
+
}
|
|
1835
|
+
const lineStart = start.offset - (start.column - 1);
|
|
1836
|
+
events.push({
|
|
1837
|
+
kind: "footnoteDef",
|
|
1838
|
+
source: content.slice(lineStart, end),
|
|
1839
|
+
origStart: lineStart,
|
|
1840
|
+
origLine: start.line
|
|
1841
|
+
});
|
|
1842
|
+
return;
|
|
1843
|
+
}
|
|
1844
|
+
if (type === "footnoteReference") {
|
|
1845
|
+
const start = node.position?.start?.offset;
|
|
1846
|
+
const end = node.position?.end?.offset;
|
|
1847
|
+
if (start === void 0 || end === void 0) {
|
|
1848
|
+
uninjectable = true;
|
|
1849
|
+
return;
|
|
1850
|
+
}
|
|
1851
|
+
pushRef(content.slice(start, end));
|
|
1852
|
+
return;
|
|
1853
|
+
}
|
|
1854
|
+
const children = node.children;
|
|
1855
|
+
if (children) {
|
|
1856
|
+
for (const child of children) visit7(child, true);
|
|
1857
|
+
}
|
|
1858
|
+
};
|
|
1859
|
+
let lastStart = -1;
|
|
1860
|
+
for (const child of mdast.children) {
|
|
1861
|
+
const start = child.position?.start?.offset;
|
|
1862
|
+
if (start !== void 0) {
|
|
1863
|
+
if (start < lastStart) return { events: [], uninjectable: true, cacheable: false };
|
|
1864
|
+
lastStart = start;
|
|
1865
|
+
}
|
|
1866
|
+
if (start === void 0) {
|
|
1867
|
+
if (resumeAt > 0) return collectPrefixInjection(mdast, content, boundary, null);
|
|
1868
|
+
cacheable = false;
|
|
1869
|
+
visit7(child, false);
|
|
1870
|
+
continue;
|
|
1871
|
+
}
|
|
1872
|
+
if (start >= boundary || start < resumeAt) continue;
|
|
1873
|
+
visit7(child, false);
|
|
1944
1874
|
}
|
|
1945
|
-
|
|
1946
|
-
if (remnant !== "") rest.unshift({ type: "text", value: remnant });
|
|
1947
|
-
return { rest, remnantMerged };
|
|
1875
|
+
return { events, uninjectable, cacheable };
|
|
1948
1876
|
}
|
|
1949
|
-
function
|
|
1950
|
-
const
|
|
1951
|
-
const
|
|
1952
|
-
if (
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1877
|
+
function cloneEventsForAppend(events) {
|
|
1878
|
+
const out = events.slice();
|
|
1879
|
+
const last = out[out.length - 1];
|
|
1880
|
+
if (last && last.kind === "refs") out[out.length - 1] = { kind: "refs", tokens: last.tokens.slice() };
|
|
1881
|
+
return out;
|
|
1882
|
+
}
|
|
1883
|
+
var TERMINATOR_LABEL = "__aimd_injection_terminator__";
|
|
1884
|
+
var INJECTION_TERMINATOR = `[${TERMINATOR_LABEL}]: __aimd_sentinel_link__`;
|
|
1885
|
+
function tailMentionsTerminator(tailSource) {
|
|
1886
|
+
return normalizeIdentifier2(tailSource).replace(/\[ /g, "[").includes(`[${normalizeIdentifier2(TERMINATOR_LABEL)}`);
|
|
1887
|
+
}
|
|
1888
|
+
function buildInjectionPrefix(events) {
|
|
1889
|
+
if (events.length === 0) return { text: "", segments: [] };
|
|
1890
|
+
let text = "";
|
|
1891
|
+
let line = 1;
|
|
1892
|
+
const segments = [];
|
|
1893
|
+
for (const event of events) {
|
|
1894
|
+
if (text.length > 0) {
|
|
1895
|
+
text += "\n\n";
|
|
1896
|
+
line += 2;
|
|
1959
1897
|
}
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
if (start >= vStart && start < vEnd) return true;
|
|
1898
|
+
const injStart = text.length;
|
|
1899
|
+
const source = event.kind === "refs" ? event.tokens.join(" ") : event.source;
|
|
1900
|
+
if (event.kind === "footnoteDef") {
|
|
1901
|
+
segments.push({
|
|
1902
|
+
injStart,
|
|
1903
|
+
injEnd: injStart + source.length,
|
|
1904
|
+
offsetDelta: event.origStart - injStart,
|
|
1905
|
+
lineDelta: event.origLine - line
|
|
1906
|
+
});
|
|
1970
1907
|
}
|
|
1908
|
+
text += source;
|
|
1909
|
+
line += countNewlines(source);
|
|
1971
1910
|
}
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
const v = value.trim();
|
|
1978
|
-
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(">");
|
|
1911
|
+
return { text: `${text}
|
|
1912
|
+
|
|
1913
|
+
${INJECTION_TERMINATOR}
|
|
1914
|
+
|
|
1915
|
+
`, segments };
|
|
1979
1916
|
}
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1917
|
+
|
|
1918
|
+
// src/components/incrementalParse/spliceParse.ts
|
|
1919
|
+
function spliceTrees(input) {
|
|
1920
|
+
const { prevMdast, prevHast, tailMdast, tailHast, content, boundary, injectionPrefix, injectedSegments } = input;
|
|
1921
|
+
const injectedLen = injectionPrefix.length;
|
|
1922
|
+
const injectedLines = countNewlines(injectionPrefix);
|
|
1923
|
+
const prefixLines = countNewlines(content, boundary);
|
|
1924
|
+
const offsetDelta = boundary - injectedLen;
|
|
1925
|
+
const lineDelta = prefixLines - injectedLines;
|
|
1926
|
+
const prefixMdast = [];
|
|
1927
|
+
for (const child of prevMdast.children) {
|
|
1928
|
+
const start = child.position?.start?.offset;
|
|
1929
|
+
if (start !== void 0 && start < boundary) prefixMdast.push(child);
|
|
1987
1930
|
}
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1931
|
+
const attrs = attributeHastChildren(prevMdast, prevHast, boundary);
|
|
1932
|
+
const cutRegion = [];
|
|
1933
|
+
for (let i = 0; i < prevHast.children.length; i++) {
|
|
1934
|
+
if (attrs[i] < boundary) {
|
|
1935
|
+
const node2 = prevHast.children[i];
|
|
1936
|
+
const end = node2.position?.end?.offset;
|
|
1937
|
+
if (end !== void 0 && end > boundary) return null;
|
|
1938
|
+
if (isTrailingLiteralText(node2)) {
|
|
1939
|
+
const prev = i > 0 ? prevHast.children[i - 1] : void 0;
|
|
1940
|
+
if (!prev || prev.type !== "element" || prev.position === void 0) return null;
|
|
1941
|
+
if (!ownsTrailingLiteral(prev, node2, prefixMdast))
|
|
1942
|
+
return null;
|
|
1943
|
+
}
|
|
1944
|
+
cutRegion.push(node2);
|
|
1945
|
+
continue;
|
|
1946
|
+
}
|
|
1947
|
+
const node = prevHast.children[i];
|
|
1948
|
+
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
|
|
1949
|
+
// raw literal can only trail an `html` mdast node. A position-less
|
|
1950
|
+
// text after a `<p>` is the NEXT block's remnant — a stray end tag
|
|
1951
|
+
// (`</t>\na`) parse5 dropped, whose text merged with the wrap
|
|
1952
|
+
// separator — owned by the tail, which re-parses it; freezing it
|
|
1953
|
+
// here duplicated it (v2.4.0 review P3). Falls through to the
|
|
1954
|
+
// remnant look-ahead below, which bails to a full parse. And the
|
|
1955
|
+
// literal must really be THAT block's trailing text: the block's raw
|
|
1956
|
+
// source ends with it. A dropped-tag block right after a frozen html
|
|
1957
|
+
// element (`</details>\n\n</t>\ntext`) puts its remnant in the same
|
|
1958
|
+
// position, and freezing it duplicated it (release soak of the fix).
|
|
1959
|
+
ownsTrailingLiteral(prevHast.children[i - 1], node, prefixMdast)) {
|
|
1960
|
+
cutRegion.push(node);
|
|
1961
|
+
break;
|
|
1962
|
+
}
|
|
1963
|
+
for (let j = i; j < prevHast.children.length; j++) {
|
|
1964
|
+
const look = prevHast.children[j];
|
|
1965
|
+
if (look.type === "element" || look.position !== void 0) break;
|
|
1966
|
+
if (isTrailingLiteralText(look)) return null;
|
|
1967
|
+
}
|
|
1968
|
+
break;
|
|
1991
1969
|
}
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
if (
|
|
2000
|
-
const
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
return node.type === "text" && node.position === void 0 && node.value.trim() !== "";
|
|
2007
|
-
}
|
|
2008
|
-
function countTrailingNewlines(value) {
|
|
2009
|
-
let n = 0;
|
|
2010
|
-
for (let i = value.length - 1; i >= 0 && value[i] === "\n"; i--) n += 1;
|
|
2011
|
-
return n;
|
|
2012
|
-
}
|
|
2013
|
-
function countNewlines(text, end = text.length) {
|
|
2014
|
-
let count = 0;
|
|
2015
|
-
for (let i = text.indexOf("\n"); i !== -1 && i < end; i = text.indexOf("\n", i + 1)) count += 1;
|
|
2016
|
-
for (let i = text.indexOf("\r"); i !== -1 && i < end; i = text.indexOf("\r", i + 1)) {
|
|
2017
|
-
if (text.charCodeAt(i + 1) !== 10) count += 1;
|
|
1970
|
+
const tailMdastChildren = tailMdast.children.filter((child) => {
|
|
1971
|
+
const start = child.position?.start?.offset;
|
|
1972
|
+
return !(start !== void 0 && start < injectedLen);
|
|
1973
|
+
});
|
|
1974
|
+
const tailWrapVisible = tailMdastChildren.some((child) => !isWrapInvisible(child));
|
|
1975
|
+
const prefixHtmlValues = prefixMdast.flatMap((c) => c.type === "html" ? [c.value] : []);
|
|
1976
|
+
if (hasStrayTablePart(prefixHtmlValues)) return null;
|
|
1977
|
+
if (rawTextRegionCrossesOut(prefixHtmlValues)) return null;
|
|
1978
|
+
const leadingHtml = [];
|
|
1979
|
+
for (const child of tailMdastChildren) {
|
|
1980
|
+
if (isWrapInvisible(child)) continue;
|
|
1981
|
+
if (child.type !== "html") break;
|
|
1982
|
+
if (STRAY_SYNTHESIZED_END_TAG_RE.test(child.value) || TABLE_PART_TAG_RE.test(child.value)) return null;
|
|
1983
|
+
leadingHtml.push(child.value);
|
|
2018
1984
|
}
|
|
2019
|
-
return
|
|
1985
|
+
if (headRoutedCaptureUnclosed(leadingHtml)) return null;
|
|
1986
|
+
const aligned = alignPrefixCut(prefixMdast, cutRegion, tailWrapVisible);
|
|
1987
|
+
if (aligned === null) return null;
|
|
1988
|
+
const hastChildren = aligned.children;
|
|
1989
|
+
const interiorFinalLiteral = aligned.interiorFinalLiteral;
|
|
1990
|
+
const stripResult = stripInjectedHast(tailMdast, tailHast, injectedLen, tailWrapVisible);
|
|
1991
|
+
if (stripResult === null) return null;
|
|
1992
|
+
const strippedTailHast = stripResult.rest;
|
|
1993
|
+
for (const child of tailMdastChildren) rebaseTree(child, offsetDelta, lineDelta);
|
|
1994
|
+
for (const child of strippedTailHast) rebaseTreeDual(child, injectedSegments, offsetDelta, lineDelta);
|
|
1995
|
+
const mdastChildren = prefixMdast.concat(tailMdastChildren);
|
|
1996
|
+
const seamMergeVerdict = stripResult.remnantMerged ?? tailLeadingTextIsHoist(tailMdastChildren, strippedTailHast);
|
|
1997
|
+
if (seamMergeVerdict === null) return null;
|
|
1998
|
+
const seamMergeAllowed = seamMergeVerdict;
|
|
1999
|
+
let firstTailChild = true;
|
|
2000
|
+
for (const child of strippedTailHast) {
|
|
2001
|
+
const tailEnd = hastChildren[hastChildren.length - 1];
|
|
2002
|
+
if (firstTailChild && child.type === "text" && child.position !== void 0) {
|
|
2003
|
+
return null;
|
|
2004
|
+
}
|
|
2005
|
+
if (firstTailChild && tailEnd && tailEnd.type === "text" && child.type === "text" && child.position === void 0) {
|
|
2006
|
+
if (interiorFinalLiteral && tailEnd.value.trim() !== "") {
|
|
2007
|
+
if (seamMergeAllowed) return null;
|
|
2008
|
+
firstTailChild = false;
|
|
2009
|
+
hastChildren.push(child);
|
|
2010
|
+
continue;
|
|
2011
|
+
}
|
|
2012
|
+
const literalSeam = tailEnd.value.trim() !== "" && !tailWrapVisible;
|
|
2013
|
+
if (seamMergeAllowed || literalSeam) {
|
|
2014
|
+
hastChildren[hastChildren.length - 1] = { type: "text", value: tailEnd.value + child.value };
|
|
2015
|
+
firstTailChild = false;
|
|
2016
|
+
continue;
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
firstTailChild = false;
|
|
2020
|
+
hastChildren.push(child);
|
|
2021
|
+
}
|
|
2022
|
+
if (!hastChildren.some((child) => child.position !== void 0)) return null;
|
|
2023
|
+
const docStart = { line: 1, column: 1, offset: 0 };
|
|
2024
|
+
const mdastRootPosition = tailMdast.position ? { start: docStart, end: rebasePoint(tailMdast.position.end, offsetDelta, lineDelta) } : prevMdast.position;
|
|
2025
|
+
const hastRootPosition = mdastRootPosition;
|
|
2026
|
+
const mdast = { type: "root", children: mdastChildren };
|
|
2027
|
+
if (mdastRootPosition) mdast.position = mdastRootPosition;
|
|
2028
|
+
const hast = { type: "root", children: hastChildren };
|
|
2029
|
+
if (hastRootPosition) hast.position = hastRootPosition;
|
|
2030
|
+
if (prevHast.data !== void 0) hast.data = prevHast.data;
|
|
2031
|
+
return { mdast, hast };
|
|
2020
2032
|
}
|
|
2021
2033
|
|
|
2022
2034
|
// src/components/incrementalParse/advanceIncrementalParse.ts
|
|
@@ -2468,7 +2480,8 @@ function buildRegistryIndex(registry) {
|
|
|
2468
2480
|
links: /* @__PURE__ */ new Map(),
|
|
2469
2481
|
numbers: /* @__PURE__ */ new Map(),
|
|
2470
2482
|
counts: /* @__PURE__ */ new Map(),
|
|
2471
|
-
occurrences: /* @__PURE__ */ new Map()
|
|
2483
|
+
occurrences: /* @__PURE__ */ new Map(),
|
|
2484
|
+
labelOccurrences: /* @__PURE__ */ new Map()
|
|
2472
2485
|
};
|
|
2473
2486
|
for (const sym of registry.chunkOrder) {
|
|
2474
2487
|
const data = registry.chunkData.get(sym);
|
|
@@ -2485,12 +2498,78 @@ function buildRegistryIndex(registry) {
|
|
|
2485
2498
|
index.counts.set(label, total);
|
|
2486
2499
|
const prior = local.get(label);
|
|
2487
2500
|
if (prior) prior.count++;
|
|
2488
|
-
else
|
|
2501
|
+
else {
|
|
2502
|
+
const range = { start: total, count: 1 };
|
|
2503
|
+
local.set(label, range);
|
|
2504
|
+
let byChunk = index.labelOccurrences.get(label);
|
|
2505
|
+
if (!byChunk) index.labelOccurrences.set(label, byChunk = /* @__PURE__ */ new Map());
|
|
2506
|
+
byChunk.set(sym, range);
|
|
2507
|
+
}
|
|
2489
2508
|
}
|
|
2490
2509
|
}
|
|
2491
2510
|
return index;
|
|
2492
2511
|
}
|
|
2493
2512
|
|
|
2513
|
+
// src/components/registrySubscriptions.ts
|
|
2514
|
+
function equal(a, b) {
|
|
2515
|
+
if (a.owner !== b.owner || a.url !== b.url || a.title !== b.title || a.number !== b.number || a.count !== b.count)
|
|
2516
|
+
return false;
|
|
2517
|
+
if (a.occurrences?.size !== b.occurrences?.size) return false;
|
|
2518
|
+
if (a.occurrences) {
|
|
2519
|
+
for (const [chunk, range] of a.occurrences) {
|
|
2520
|
+
const next = b.occurrences?.get(chunk);
|
|
2521
|
+
if (!next || next.start !== range.start || next.count !== range.count) return false;
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
return true;
|
|
2525
|
+
}
|
|
2526
|
+
function createRegistrySubscriptions(read) {
|
|
2527
|
+
const groups = { link: /* @__PURE__ */ new Map(), footnote: /* @__PURE__ */ new Map() };
|
|
2528
|
+
const snapshot = (kind, label, { registry, index }) => {
|
|
2529
|
+
if (kind === "link") {
|
|
2530
|
+
const owner = index.links.get(label);
|
|
2531
|
+
const def = owner ? registry.chunkData.get(owner)?.linkDefs.get(label) : void 0;
|
|
2532
|
+
return { owner, url: def?.url, title: def?.title };
|
|
2533
|
+
}
|
|
2534
|
+
return {
|
|
2535
|
+
owner: index.footnotes.get(label),
|
|
2536
|
+
number: index.numbers.get(label),
|
|
2537
|
+
count: index.counts.get(label),
|
|
2538
|
+
occurrences: index.labelOccurrences.get(label)
|
|
2539
|
+
};
|
|
2540
|
+
};
|
|
2541
|
+
return {
|
|
2542
|
+
subscribe(kind, rawLabel, cb) {
|
|
2543
|
+
const label = normalizeId(rawLabel);
|
|
2544
|
+
const map = groups[kind];
|
|
2545
|
+
let group = map.get(label);
|
|
2546
|
+
if (!group) {
|
|
2547
|
+
group = { snapshot: snapshot(kind, label, read()), listeners: /* @__PURE__ */ new Set() };
|
|
2548
|
+
map.set(label, group);
|
|
2549
|
+
}
|
|
2550
|
+
const listener = () => cb();
|
|
2551
|
+
group.listeners.add(listener);
|
|
2552
|
+
return () => {
|
|
2553
|
+
group.listeners.delete(listener);
|
|
2554
|
+
if (group.listeners.size === 0 && map.get(label) === group) map.delete(label);
|
|
2555
|
+
};
|
|
2556
|
+
},
|
|
2557
|
+
collect() {
|
|
2558
|
+
if (groups.link.size === 0 && groups.footnote.size === 0) return [];
|
|
2559
|
+
const state = read();
|
|
2560
|
+
const callbacks = [];
|
|
2561
|
+
for (const kind of ["link", "footnote"]) {
|
|
2562
|
+
for (const [label, group] of groups[kind]) {
|
|
2563
|
+
const next = snapshot(kind, label, state);
|
|
2564
|
+
if (!equal(group.snapshot, next)) callbacks.push(...group.listeners);
|
|
2565
|
+
group.snapshot = next;
|
|
2566
|
+
}
|
|
2567
|
+
}
|
|
2568
|
+
return callbacks;
|
|
2569
|
+
}
|
|
2570
|
+
};
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2494
2573
|
// src/components/documentRegistry.ts
|
|
2495
2574
|
function createRegistry(onEmpty) {
|
|
2496
2575
|
let index;
|
|
@@ -2502,6 +2581,7 @@ function createRegistry(onEmpty) {
|
|
|
2502
2581
|
}
|
|
2503
2582
|
return index;
|
|
2504
2583
|
};
|
|
2584
|
+
const labels = createRegistrySubscriptions(() => ({ registry: reg, index: getIndex() }));
|
|
2505
2585
|
const reg = {
|
|
2506
2586
|
chunkOrder: [],
|
|
2507
2587
|
chunkData: /* @__PURE__ */ new Map(),
|
|
@@ -2652,6 +2732,9 @@ function createRegistry(onEmpty) {
|
|
|
2652
2732
|
this._subscribers.delete(cb);
|
|
2653
2733
|
};
|
|
2654
2734
|
},
|
|
2735
|
+
subscribeLabel(kind, label, cb) {
|
|
2736
|
+
return labels.subscribe(kind, label, cb);
|
|
2737
|
+
},
|
|
2655
2738
|
canonicalFootnoteFor(label) {
|
|
2656
2739
|
return getIndex().footnotes.get(normalizeId(label)) ?? null;
|
|
2657
2740
|
},
|
|
@@ -2679,7 +2762,9 @@ function createRegistry(onEmpty) {
|
|
|
2679
2762
|
this._notifyScheduled = true;
|
|
2680
2763
|
queueMicrotask(() => {
|
|
2681
2764
|
this._notifyScheduled = false;
|
|
2765
|
+
const labelCallbacks = labels.collect();
|
|
2682
2766
|
for (const cb of [...this._subscribers]) cb();
|
|
2767
|
+
for (const cb of labelCallbacks) cb();
|
|
2683
2768
|
});
|
|
2684
2769
|
}
|
|
2685
2770
|
};
|