@ai-react-markdown/engine 2.11.0 → 2.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +715 -534
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +72 -77
- package/dist/index.d.ts +72 -77
- package/dist/index.dev.cjs +715 -534
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +714 -534
- package/dist/index.dev.js.map +1 -1
- package/dist/index.js +714 -534
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.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"]);
|
|
@@ -617,43 +663,6 @@ function maskIntraLineCodeSpans(text, carryOpen) {
|
|
|
617
663
|
out += text.slice(cursor);
|
|
618
664
|
return { masked: out, unpaired: false };
|
|
619
665
|
}
|
|
620
|
-
function freshCheckpoint(defListEnabled, mathFlow, referenceTaint) {
|
|
621
|
-
return {
|
|
622
|
-
defListEnabled,
|
|
623
|
-
mathFlow,
|
|
624
|
-
referenceTaint,
|
|
625
|
-
confirmedOffset: 0,
|
|
626
|
-
candidates: [],
|
|
627
|
-
defs: /* @__PURE__ */ new Map(),
|
|
628
|
-
footnoteDefs: /* @__PURE__ */ new Map(),
|
|
629
|
-
unresolvedRefs: [],
|
|
630
|
-
tagBalance: /* @__PURE__ */ new Map(),
|
|
631
|
-
openTotal: 0,
|
|
632
|
-
p5Tok: { kind: "data" },
|
|
633
|
-
formPointerMaybeSet: false,
|
|
634
|
-
openStack: [],
|
|
635
|
-
mdBlock: { kind: "none" },
|
|
636
|
-
blankRun: 0,
|
|
637
|
-
lastBlankStart: -1,
|
|
638
|
-
hazardVerdict: false,
|
|
639
|
-
prevLineBlank: true,
|
|
640
|
-
// doc start counts as a block start
|
|
641
|
-
prevLineWasText: false,
|
|
642
|
-
prevLineWasValidDef: false,
|
|
643
|
-
prevLineOpenContent: false,
|
|
644
|
-
tableMaybeOpen: false,
|
|
645
|
-
containerMaybeOpen: false,
|
|
646
|
-
paragraphHasUnpairedRun: false,
|
|
647
|
-
openBracket: null,
|
|
648
|
-
p5SealPending: false,
|
|
649
|
-
defBlockMaybeOpen: false,
|
|
650
|
-
fnDefResumable: false,
|
|
651
|
-
phasePoisonedAt: Infinity,
|
|
652
|
-
pendingTruncatedTags: [],
|
|
653
|
-
pendingTruncatedCloses: [],
|
|
654
|
-
pendingTag: null
|
|
655
|
-
};
|
|
656
|
-
}
|
|
657
666
|
function classifyBlockStart(text, indent, defListEnabled) {
|
|
658
667
|
if (indent >= 4) return true;
|
|
659
668
|
if (LIST_MARKER_RE.test(text) || FOOTNOTE_DEF_RE.test(text)) return true;
|
|
@@ -661,71 +670,23 @@ function classifyBlockStart(text, indent, defListEnabled) {
|
|
|
661
670
|
if (indent === 0) return false;
|
|
662
671
|
return null;
|
|
663
672
|
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
textEnd = nl;
|
|
682
|
-
end = nl;
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
const confirmed = end < text.length && !(end === text.length - 1 && text.charCodeAt(end) === 13);
|
|
686
|
-
const lineText = text.slice(start, textEnd);
|
|
687
|
-
const ln = {
|
|
688
|
-
start,
|
|
689
|
-
end,
|
|
690
|
-
text: lineText,
|
|
691
|
-
blank: confirmed && isMdBlank(lineText),
|
|
692
|
-
indent: computeIndent(lineText)
|
|
693
|
-
};
|
|
694
|
-
if (!confirmed) {
|
|
695
|
-
tailLine = ln;
|
|
696
|
-
break;
|
|
697
|
-
}
|
|
698
|
-
processConfirmedLine(cp, ln, text);
|
|
699
|
-
cp.confirmedOffset = end + 1;
|
|
700
|
-
start = end + 1;
|
|
701
|
-
}
|
|
702
|
-
const earliestUnresolved = settleRefsAndEarliestUnresolved(cp);
|
|
703
|
-
const defListSettled = (c) => {
|
|
704
|
-
if (!options.defListEnabled || c.blankRun >= 2) return true;
|
|
705
|
-
if (c.defListSettled !== null) return c.defListSettled;
|
|
706
|
-
if (tailLine) return !canBecomeDdLine(tailLine.text, false);
|
|
707
|
-
return false;
|
|
708
|
-
};
|
|
709
|
-
const tailRetroactive = tailLine !== null && tailCarriesRetroactive(tailLine.text);
|
|
710
|
-
let boundary = 0;
|
|
711
|
-
for (let i = cp.candidates.length - 1; i >= 0 && !tailRetroactive; i--) {
|
|
712
|
-
const c = cp.candidates[i];
|
|
713
|
-
if (!c.htmlBalanced || c.hazard || c.seamRisk) continue;
|
|
714
|
-
if (c.offset > cp.phasePoisonedAt) continue;
|
|
715
|
-
if (c.offset > earliestUnresolved) continue;
|
|
716
|
-
if (!defListSettled(c)) continue;
|
|
717
|
-
boundary = c.offset;
|
|
718
|
-
break;
|
|
719
|
-
}
|
|
720
|
-
return { boundary, checkpoint: cp };
|
|
721
|
-
}
|
|
722
|
-
function pendingFenceCloser(checkpoint) {
|
|
723
|
-
const cp = checkpoint;
|
|
724
|
-
if (cp.phasePoisonedAt !== Infinity) return "";
|
|
725
|
-
if (cp.mdBlock.kind === "fence" && cp.mdBlock.indent === 0) return cp.mdBlock.char.repeat(cp.mdBlock.len);
|
|
726
|
-
if (cp.mdBlock.kind === "math" && cp.mdBlock.indent === 0) return "$".repeat(cp.mdBlock.len);
|
|
727
|
-
return "";
|
|
728
|
-
}
|
|
673
|
+
var SCANNER_NAME_LISTS = [
|
|
674
|
+
["type1", TYPE1_NAMES],
|
|
675
|
+
["rawText", RAW_TEXT_ELEMENTS],
|
|
676
|
+
["type6", TYPE6_NAMES],
|
|
677
|
+
["void", VOID_TAGS],
|
|
678
|
+
["documentStructure", DOCUMENT_STRUCTURE_NAMES],
|
|
679
|
+
// Added with F28, and it is the list that would have made F28 visible: the
|
|
680
|
+
// derived census alphabet partitions names by their membership across THIS
|
|
681
|
+
// table, so before it existed `frame` shared one 39-name class with `div`
|
|
682
|
+
// and could never be sampled apart from it.
|
|
683
|
+
["noElement", NO_ELEMENT_NAMES],
|
|
684
|
+
["tablePart", TABLE_PART_NAMES],
|
|
685
|
+
["scopeBarrier", SCOPE_BARRIER_NAMES],
|
|
686
|
+
["foreignRoot", new Set(FOREIGN_ROOT_NAMES)]
|
|
687
|
+
];
|
|
688
|
+
|
|
689
|
+
// src/components/incrementalParse/freezeLineTransition.ts
|
|
729
690
|
function floatingResidue(text, commentOpenAtStart) {
|
|
730
691
|
let out = "";
|
|
731
692
|
let open = commentOpenAtStart;
|
|
@@ -1369,24 +1330,66 @@ function processConfirmedLine(cp, ln, text) {
|
|
|
1369
1330
|
}
|
|
1370
1331
|
}
|
|
1371
1332
|
}
|
|
1372
|
-
var SCANNER_NAME_LISTS = [
|
|
1373
|
-
["type1", TYPE1_NAMES],
|
|
1374
|
-
["rawText", RAW_TEXT_ELEMENTS],
|
|
1375
|
-
["type6", TYPE6_NAMES],
|
|
1376
|
-
["void", VOID_TAGS],
|
|
1377
|
-
["documentStructure", DOCUMENT_STRUCTURE_NAMES],
|
|
1378
|
-
// Added with F28, and it is the list that would have made F28 visible: the
|
|
1379
|
-
// derived census alphabet partitions names by their membership across THIS
|
|
1380
|
-
// table, so before it existed `frame` shared one 39-name class with `div`
|
|
1381
|
-
// and could never be sampled apart from it.
|
|
1382
|
-
["noElement", NO_ELEMENT_NAMES],
|
|
1383
|
-
["tablePart", TABLE_PART_NAMES],
|
|
1384
|
-
["scopeBarrier", SCOPE_BARRIER_NAMES],
|
|
1385
|
-
["foreignRoot", new Set(FOREIGN_ROOT_NAMES)]
|
|
1386
|
-
];
|
|
1387
1333
|
|
|
1388
|
-
// src/components/incrementalParse/
|
|
1389
|
-
|
|
1334
|
+
// src/components/incrementalParse/computeFreezeBoundary.ts
|
|
1335
|
+
function computeFreezeBoundary(text, options, resume) {
|
|
1336
|
+
const mathFlow = options.mathFlow ?? true;
|
|
1337
|
+
const referenceTaint = options.referenceTaint ?? true;
|
|
1338
|
+
const prev = resume;
|
|
1339
|
+
const cp = prev && prev.defListEnabled === options.defListEnabled && prev.mathFlow === mathFlow && prev.referenceTaint === referenceTaint && prev.confirmedOffset <= text.length ? prev : freshCheckpoint(options.defListEnabled, mathFlow, referenceTaint);
|
|
1340
|
+
let start = cp.confirmedOffset;
|
|
1341
|
+
let tailLine = null;
|
|
1342
|
+
while (start < text.length) {
|
|
1343
|
+
let end = text.length;
|
|
1344
|
+
let textEnd = text.length;
|
|
1345
|
+
{
|
|
1346
|
+
const nl = text.indexOf("\n", start);
|
|
1347
|
+
const cr = text.indexOf("\r", start);
|
|
1348
|
+
if (cr !== -1 && (nl === -1 || cr < nl)) {
|
|
1349
|
+
textEnd = cr;
|
|
1350
|
+
end = text.charCodeAt(cr + 1) === 10 ? cr + 1 : cr;
|
|
1351
|
+
} else if (nl !== -1) {
|
|
1352
|
+
textEnd = nl;
|
|
1353
|
+
end = nl;
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
const confirmed = end < text.length && !(end === text.length - 1 && text.charCodeAt(end) === 13);
|
|
1357
|
+
const lineText = text.slice(start, textEnd);
|
|
1358
|
+
const ln = {
|
|
1359
|
+
start,
|
|
1360
|
+
end,
|
|
1361
|
+
text: lineText,
|
|
1362
|
+
blank: confirmed && isMdBlank(lineText),
|
|
1363
|
+
indent: computeIndent(lineText)
|
|
1364
|
+
};
|
|
1365
|
+
if (!confirmed) {
|
|
1366
|
+
tailLine = ln;
|
|
1367
|
+
break;
|
|
1368
|
+
}
|
|
1369
|
+
processConfirmedLine(cp, ln, text);
|
|
1370
|
+
cp.confirmedOffset = end + 1;
|
|
1371
|
+
start = end + 1;
|
|
1372
|
+
}
|
|
1373
|
+
const earliestUnresolved = settleRefsAndEarliestUnresolved(cp);
|
|
1374
|
+
const defListSettled = (c) => {
|
|
1375
|
+
if (!options.defListEnabled || c.blankRun >= 2) return true;
|
|
1376
|
+
if (c.defListSettled !== null) return c.defListSettled;
|
|
1377
|
+
if (tailLine) return !canBecomeDdLine(tailLine.text, false);
|
|
1378
|
+
return false;
|
|
1379
|
+
};
|
|
1380
|
+
const tailRetroactive = tailLine !== null && tailCarriesRetroactive(tailLine.text);
|
|
1381
|
+
let boundary = 0;
|
|
1382
|
+
for (let i = cp.candidates.length - 1; i >= 0 && !tailRetroactive; i--) {
|
|
1383
|
+
const c = cp.candidates[i];
|
|
1384
|
+
if (!c.htmlBalanced || c.hazard || c.seamRisk) continue;
|
|
1385
|
+
if (c.offset > cp.phasePoisonedAt) continue;
|
|
1386
|
+
if (c.offset > earliestUnresolved) continue;
|
|
1387
|
+
if (!defListSettled(c)) continue;
|
|
1388
|
+
boundary = c.offset;
|
|
1389
|
+
break;
|
|
1390
|
+
}
|
|
1391
|
+
return { boundary, checkpoint: cp };
|
|
1392
|
+
}
|
|
1390
1393
|
|
|
1391
1394
|
// src/components/hastPredicates.ts
|
|
1392
1395
|
function isFootnoteSection(node) {
|
|
@@ -1434,121 +1437,7 @@ function attributeHastChildren(mdast, hast, stopAt = Infinity) {
|
|
|
1434
1437
|
}
|
|
1435
1438
|
}
|
|
1436
1439
|
|
|
1437
|
-
// src/components/incrementalParse/
|
|
1438
|
-
function collectPrefixInjection(mdast, content, boundary, resume) {
|
|
1439
|
-
const resumeValid = resume != null && resume.boundary <= boundary;
|
|
1440
|
-
if (resumeValid && resume.uninjectable) return { events: resume.events, uninjectable: true };
|
|
1441
|
-
const resumeAt = resumeValid ? resume.boundary : 0;
|
|
1442
|
-
const events = resumeAt > 0 ? cloneEventsForAppend(resume.events) : [];
|
|
1443
|
-
let uninjectable = false;
|
|
1444
|
-
let cacheable = true;
|
|
1445
|
-
const pushRef = (token) => {
|
|
1446
|
-
const last = events[events.length - 1];
|
|
1447
|
-
if (last && last.kind === "refs") last.tokens.push(token);
|
|
1448
|
-
else events.push({ kind: "refs", tokens: [token] });
|
|
1449
|
-
};
|
|
1450
|
-
const visit7 = (node, nested) => {
|
|
1451
|
-
const type = node.type;
|
|
1452
|
-
if (type === "definition") {
|
|
1453
|
-
const start = node.position?.start?.offset;
|
|
1454
|
-
const end = node.position?.end?.offset;
|
|
1455
|
-
if (start !== void 0 && end !== void 0 && start < boundary) {
|
|
1456
|
-
const slice = content.slice(start, end);
|
|
1457
|
-
if (nested && slice.includes("\n")) uninjectable = true;
|
|
1458
|
-
else events.push({ kind: "def", source: slice });
|
|
1459
|
-
}
|
|
1460
|
-
return;
|
|
1461
|
-
}
|
|
1462
|
-
if (type === "footnoteDefinition") {
|
|
1463
|
-
const start = node.position?.start;
|
|
1464
|
-
const end = node.position?.end?.offset;
|
|
1465
|
-
if (start?.offset === void 0 || end === void 0 || start.offset >= boundary) return;
|
|
1466
|
-
if (nested) {
|
|
1467
|
-
uninjectable = true;
|
|
1468
|
-
return;
|
|
1469
|
-
}
|
|
1470
|
-
const lineStart = start.offset - (start.column - 1);
|
|
1471
|
-
events.push({
|
|
1472
|
-
kind: "footnoteDef",
|
|
1473
|
-
source: content.slice(lineStart, end),
|
|
1474
|
-
origStart: lineStart,
|
|
1475
|
-
origLine: start.line
|
|
1476
|
-
});
|
|
1477
|
-
return;
|
|
1478
|
-
}
|
|
1479
|
-
if (type === "footnoteReference") {
|
|
1480
|
-
const start = node.position?.start?.offset;
|
|
1481
|
-
const end = node.position?.end?.offset;
|
|
1482
|
-
if (start === void 0 || end === void 0) {
|
|
1483
|
-
uninjectable = true;
|
|
1484
|
-
return;
|
|
1485
|
-
}
|
|
1486
|
-
pushRef(content.slice(start, end));
|
|
1487
|
-
return;
|
|
1488
|
-
}
|
|
1489
|
-
const children = node.children;
|
|
1490
|
-
if (children) {
|
|
1491
|
-
for (const child of children) visit7(child, true);
|
|
1492
|
-
}
|
|
1493
|
-
};
|
|
1494
|
-
let lastStart = -1;
|
|
1495
|
-
for (const child of mdast.children) {
|
|
1496
|
-
const start = child.position?.start?.offset;
|
|
1497
|
-
if (start !== void 0) {
|
|
1498
|
-
if (start < lastStart) return { events: [], uninjectable: true, cacheable: false };
|
|
1499
|
-
lastStart = start;
|
|
1500
|
-
}
|
|
1501
|
-
if (start === void 0) {
|
|
1502
|
-
if (resumeAt > 0) return collectPrefixInjection(mdast, content, boundary, null);
|
|
1503
|
-
cacheable = false;
|
|
1504
|
-
visit7(child, false);
|
|
1505
|
-
continue;
|
|
1506
|
-
}
|
|
1507
|
-
if (start >= boundary || start < resumeAt) continue;
|
|
1508
|
-
visit7(child, false);
|
|
1509
|
-
}
|
|
1510
|
-
return { events, uninjectable, cacheable };
|
|
1511
|
-
}
|
|
1512
|
-
function cloneEventsForAppend(events) {
|
|
1513
|
-
const out = events.slice();
|
|
1514
|
-
const last = out[out.length - 1];
|
|
1515
|
-
if (last && last.kind === "refs") out[out.length - 1] = { kind: "refs", tokens: last.tokens.slice() };
|
|
1516
|
-
return out;
|
|
1517
|
-
}
|
|
1518
|
-
var TERMINATOR_LABEL = "__aimd_injection_terminator__";
|
|
1519
|
-
var INJECTION_TERMINATOR = `[${TERMINATOR_LABEL}]: __aimd_sentinel_link__`;
|
|
1520
|
-
function tailMentionsTerminator(tailSource) {
|
|
1521
|
-
return normalizeIdentifier2(tailSource).replace(/\[ /g, "[").includes(`[${normalizeIdentifier2(TERMINATOR_LABEL)}`);
|
|
1522
|
-
}
|
|
1523
|
-
function buildInjectionPrefix(events) {
|
|
1524
|
-
if (events.length === 0) return { text: "", segments: [] };
|
|
1525
|
-
let text = "";
|
|
1526
|
-
let line = 1;
|
|
1527
|
-
const segments = [];
|
|
1528
|
-
for (const event of events) {
|
|
1529
|
-
if (text.length > 0) {
|
|
1530
|
-
text += "\n\n";
|
|
1531
|
-
line += 2;
|
|
1532
|
-
}
|
|
1533
|
-
const injStart = text.length;
|
|
1534
|
-
const source = event.kind === "refs" ? event.tokens.join(" ") : event.source;
|
|
1535
|
-
if (event.kind === "footnoteDef") {
|
|
1536
|
-
segments.push({
|
|
1537
|
-
injStart,
|
|
1538
|
-
injEnd: injStart + source.length,
|
|
1539
|
-
offsetDelta: event.origStart - injStart,
|
|
1540
|
-
lineDelta: event.origLine - line
|
|
1541
|
-
});
|
|
1542
|
-
}
|
|
1543
|
-
text += source;
|
|
1544
|
-
line += countNewlines(source);
|
|
1545
|
-
}
|
|
1546
|
-
return { text: `${text}
|
|
1547
|
-
|
|
1548
|
-
${INJECTION_TERMINATOR}
|
|
1549
|
-
|
|
1550
|
-
`, segments };
|
|
1551
|
-
}
|
|
1440
|
+
// src/components/incrementalParse/spliceCoordinates.ts
|
|
1552
1441
|
function rebaseTree(node, offsetDelta, lineDelta) {
|
|
1553
1442
|
rebaseTreeDual(node, EMPTY_SEGMENTS, offsetDelta, lineDelta);
|
|
1554
1443
|
}
|
|
@@ -1577,6 +1466,23 @@ function rebaseDualWalk(node, segments, maxEnd, offsetDelta, lineDelta) {
|
|
|
1577
1466
|
for (const child of children) rebaseDualWalk(child, segments, maxEnd, offsetDelta, lineDelta);
|
|
1578
1467
|
}
|
|
1579
1468
|
}
|
|
1469
|
+
function rebasePoint(point, offsetDelta, lineDelta) {
|
|
1470
|
+
return {
|
|
1471
|
+
line: point.line + lineDelta,
|
|
1472
|
+
column: point.column,
|
|
1473
|
+
offset: point.offset !== void 0 ? point.offset + offsetDelta : void 0
|
|
1474
|
+
};
|
|
1475
|
+
}
|
|
1476
|
+
function countNewlines(text, end = text.length) {
|
|
1477
|
+
let count = 0;
|
|
1478
|
+
for (let i = text.indexOf("\n"); i !== -1 && i < end; i = text.indexOf("\n", i + 1)) count += 1;
|
|
1479
|
+
for (let i = text.indexOf("\r"); i !== -1 && i < end; i = text.indexOf("\r", i + 1)) {
|
|
1480
|
+
if (text.charCodeAt(i + 1) !== 10) count += 1;
|
|
1481
|
+
}
|
|
1482
|
+
return count;
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
// src/components/incrementalParse/spliceHtmlGuards.ts
|
|
1580
1486
|
var TABLE_PART_TAG_RE = /<(?:td|th|tr|tbody|thead|tfoot|caption|col|colgroup)\b/i;
|
|
1581
1487
|
var TABLE_TOKEN_RE = /<(\/?)(table|td|th|tr|tbody|thead|tfoot|caption|col|colgroup)\b/gi;
|
|
1582
1488
|
function hasStrayTablePart(values) {
|
|
@@ -1658,127 +1564,26 @@ function rawTextRegionCrossesOut(values) {
|
|
|
1658
1564
|
}
|
|
1659
1565
|
return false;
|
|
1660
1566
|
}
|
|
1661
|
-
function
|
|
1662
|
-
const
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
}
|
|
1673
|
-
const attrs = attributeHastChildren(prevMdast, prevHast, boundary);
|
|
1674
|
-
const cutRegion = [];
|
|
1675
|
-
for (let i = 0; i < prevHast.children.length; i++) {
|
|
1676
|
-
if (attrs[i] < boundary) {
|
|
1677
|
-
const node2 = prevHast.children[i];
|
|
1678
|
-
const end = node2.position?.end?.offset;
|
|
1679
|
-
if (end !== void 0 && end > boundary) return null;
|
|
1680
|
-
if (isTrailingLiteralText(node2)) {
|
|
1681
|
-
const prev = i > 0 ? prevHast.children[i - 1] : void 0;
|
|
1682
|
-
if (!prev || prev.type !== "element" || prev.position === void 0) return null;
|
|
1683
|
-
if (!ownsTrailingLiteral(prev, node2, prefixMdast))
|
|
1684
|
-
return null;
|
|
1685
|
-
}
|
|
1686
|
-
cutRegion.push(node2);
|
|
1687
|
-
continue;
|
|
1688
|
-
}
|
|
1689
|
-
const node = prevHast.children[i];
|
|
1690
|
-
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
|
|
1691
|
-
// raw literal can only trail an `html` mdast node. A position-less
|
|
1692
|
-
// text after a `<p>` is the NEXT block's remnant — a stray end tag
|
|
1693
|
-
// (`</t>\na`) parse5 dropped, whose text merged with the wrap
|
|
1694
|
-
// separator — owned by the tail, which re-parses it; freezing it
|
|
1695
|
-
// here duplicated it (v2.4.0 review P3). Falls through to the
|
|
1696
|
-
// remnant look-ahead below, which bails to a full parse. And the
|
|
1697
|
-
// literal must really be THAT block's trailing text: the block's raw
|
|
1698
|
-
// source ends with it. A dropped-tag block right after a frozen html
|
|
1699
|
-
// element (`</details>\n\n</t>\ntext`) puts its remnant in the same
|
|
1700
|
-
// position, and freezing it duplicated it (release soak of the fix).
|
|
1701
|
-
ownsTrailingLiteral(prevHast.children[i - 1], node, prefixMdast)) {
|
|
1702
|
-
cutRegion.push(node);
|
|
1703
|
-
break;
|
|
1704
|
-
}
|
|
1705
|
-
for (let j = i; j < prevHast.children.length; j++) {
|
|
1706
|
-
const look = prevHast.children[j];
|
|
1707
|
-
if (look.type === "element" || look.position !== void 0) break;
|
|
1708
|
-
if (isTrailingLiteralText(look)) return null;
|
|
1709
|
-
}
|
|
1710
|
-
break;
|
|
1711
|
-
}
|
|
1712
|
-
const tailMdastChildren = tailMdast.children.filter((child) => {
|
|
1713
|
-
const start = child.position?.start?.offset;
|
|
1714
|
-
return !(start !== void 0 && start < injectedLen);
|
|
1715
|
-
});
|
|
1716
|
-
const tailWrapVisible = tailMdastChildren.some((child) => !isWrapInvisible(child));
|
|
1717
|
-
const prefixHtmlValues = prefixMdast.flatMap((c) => c.type === "html" ? [c.value] : []);
|
|
1718
|
-
if (hasStrayTablePart(prefixHtmlValues)) return null;
|
|
1719
|
-
if (rawTextRegionCrossesOut(prefixHtmlValues)) return null;
|
|
1720
|
-
const leadingHtml = [];
|
|
1721
|
-
for (const child of tailMdastChildren) {
|
|
1722
|
-
if (isWrapInvisible(child)) continue;
|
|
1723
|
-
if (child.type !== "html") break;
|
|
1724
|
-
if (STRAY_SYNTHESIZED_END_TAG_RE.test(child.value) || TABLE_PART_TAG_RE.test(child.value)) return null;
|
|
1725
|
-
leadingHtml.push(child.value);
|
|
1567
|
+
function isSanitizeStrippedConstruct(value) {
|
|
1568
|
+
const v = value.trim();
|
|
1569
|
+
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(">");
|
|
1570
|
+
}
|
|
1571
|
+
function isExactSanitizeStrippedConstruct(value) {
|
|
1572
|
+
if (value.startsWith("<!--")) {
|
|
1573
|
+
if (value.length < 7 || !value.endsWith("-->")) return false;
|
|
1574
|
+
const close = value.indexOf("-->", 4);
|
|
1575
|
+
const bangClose = value.indexOf("--!>", 4);
|
|
1576
|
+
if (close !== value.length - 3) return false;
|
|
1577
|
+
return bangClose === -1 || bangClose > close;
|
|
1726
1578
|
}
|
|
1727
|
-
if (
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
const hastChildren = aligned.children;
|
|
1731
|
-
const interiorFinalLiteral = aligned.interiorFinalLiteral;
|
|
1732
|
-
const stripResult = stripInjectedHast(tailMdast, tailHast, injectedLen, tailWrapVisible);
|
|
1733
|
-
if (stripResult === null) return null;
|
|
1734
|
-
const strippedTailHast = stripResult.rest;
|
|
1735
|
-
for (const child of tailMdastChildren) rebaseTree(child, offsetDelta, lineDelta);
|
|
1736
|
-
for (const child of strippedTailHast) rebaseTreeDual(child, injectedSegments, offsetDelta, lineDelta);
|
|
1737
|
-
const mdastChildren = prefixMdast.concat(tailMdastChildren);
|
|
1738
|
-
const seamMergeVerdict = stripResult.remnantMerged ?? tailLeadingTextIsHoist(tailMdastChildren, strippedTailHast);
|
|
1739
|
-
if (seamMergeVerdict === null) return null;
|
|
1740
|
-
const seamMergeAllowed = seamMergeVerdict;
|
|
1741
|
-
let firstTailChild = true;
|
|
1742
|
-
for (const child of strippedTailHast) {
|
|
1743
|
-
const tailEnd = hastChildren[hastChildren.length - 1];
|
|
1744
|
-
if (firstTailChild && child.type === "text" && child.position !== void 0) {
|
|
1745
|
-
return null;
|
|
1746
|
-
}
|
|
1747
|
-
if (firstTailChild && tailEnd && tailEnd.type === "text" && child.type === "text" && child.position === void 0) {
|
|
1748
|
-
if (interiorFinalLiteral && tailEnd.value.trim() !== "") {
|
|
1749
|
-
if (seamMergeAllowed) return null;
|
|
1750
|
-
firstTailChild = false;
|
|
1751
|
-
hastChildren.push(child);
|
|
1752
|
-
continue;
|
|
1753
|
-
}
|
|
1754
|
-
const literalSeam = tailEnd.value.trim() !== "" && !tailWrapVisible;
|
|
1755
|
-
if (seamMergeAllowed || literalSeam) {
|
|
1756
|
-
hastChildren[hastChildren.length - 1] = { type: "text", value: tailEnd.value + child.value };
|
|
1757
|
-
firstTailChild = false;
|
|
1758
|
-
continue;
|
|
1759
|
-
}
|
|
1760
|
-
}
|
|
1761
|
-
firstTailChild = false;
|
|
1762
|
-
hastChildren.push(child);
|
|
1579
|
+
if (/^<!doctype/i.test(value)) return false;
|
|
1580
|
+
if (value.startsWith("<?") || /^<!(?:[A-Za-z]|\[CDATA\[)/.test(value)) {
|
|
1581
|
+
return value.indexOf(">") === value.length - 1;
|
|
1763
1582
|
}
|
|
1764
|
-
|
|
1765
|
-
const docStart = { line: 1, column: 1, offset: 0 };
|
|
1766
|
-
const mdastRootPosition = tailMdast.position ? { start: docStart, end: rebasePoint(tailMdast.position.end, offsetDelta, lineDelta) } : prevMdast.position;
|
|
1767
|
-
const hastRootPosition = mdastRootPosition;
|
|
1768
|
-
const mdast = { type: "root", children: mdastChildren };
|
|
1769
|
-
if (mdastRootPosition) mdast.position = mdastRootPosition;
|
|
1770
|
-
const hast = { type: "root", children: hastChildren };
|
|
1771
|
-
if (hastRootPosition) hast.position = hastRootPosition;
|
|
1772
|
-
if (prevHast.data !== void 0) hast.data = prevHast.data;
|
|
1773
|
-
return { mdast, hast };
|
|
1774
|
-
}
|
|
1775
|
-
function rebasePoint(point, offsetDelta, lineDelta) {
|
|
1776
|
-
return {
|
|
1777
|
-
line: point.line + lineDelta,
|
|
1778
|
-
column: point.column,
|
|
1779
|
-
offset: point.offset !== void 0 ? point.offset + offsetDelta : void 0
|
|
1780
|
-
};
|
|
1583
|
+
return false;
|
|
1781
1584
|
}
|
|
1585
|
+
|
|
1586
|
+
// src/components/incrementalParse/prefixAlignment.ts
|
|
1782
1587
|
function isWrapInvisible(node) {
|
|
1783
1588
|
return node.type === "definition" || node.type === "footnoteDefinition";
|
|
1784
1589
|
}
|
|
@@ -1920,96 +1725,303 @@ function stripInjectedHast(tailMdast, tailHast, injectedLen, tailWrapVisible) {
|
|
|
1920
1725
|
idx += 1;
|
|
1921
1726
|
continue;
|
|
1922
1727
|
}
|
|
1923
|
-
const start = node.position?.start?.offset;
|
|
1924
|
-
if (start === void 0 || start >= injectedLen) return null;
|
|
1925
|
-
consumed += 1;
|
|
1926
|
-
idx += 1;
|
|
1728
|
+
const start = node.position?.start?.offset;
|
|
1729
|
+
if (start === void 0 || start >= injectedLen) return null;
|
|
1730
|
+
consumed += 1;
|
|
1731
|
+
idx += 1;
|
|
1732
|
+
}
|
|
1733
|
+
if (consumed < injectedVisibleCount) return null;
|
|
1734
|
+
let remnant = "";
|
|
1735
|
+
let remnantMerged = null;
|
|
1736
|
+
if (tailWrapVisible) {
|
|
1737
|
+
const gap = children[idx];
|
|
1738
|
+
if (!gap || !isSeparatorText(gap)) return null;
|
|
1739
|
+
remnant = gap.value.slice(1);
|
|
1740
|
+
remnantMerged = remnant !== "";
|
|
1741
|
+
idx += 1;
|
|
1742
|
+
}
|
|
1743
|
+
const rest = children.slice(idx);
|
|
1744
|
+
if (remnant !== "") rest.unshift({ type: "text", value: remnant });
|
|
1745
|
+
return { rest, remnantMerged };
|
|
1746
|
+
}
|
|
1747
|
+
function tailLeadingTextIsHoist(tailMdastChildren, tailHastChildren) {
|
|
1748
|
+
const firstText = tailHastChildren[0];
|
|
1749
|
+
const firstVisible = tailMdastChildren.find((c) => !isWrapInvisible(c));
|
|
1750
|
+
if (firstVisible?.type === "html" && STRAY_SYNTHESIZED_END_TAG_RE.test(firstVisible.value)) return null;
|
|
1751
|
+
if (!firstText) return false;
|
|
1752
|
+
if (!isSeparatorText(firstText)) {
|
|
1753
|
+
if (firstText.type === "text" && firstText.position === void 0 && firstVisible?.type === "html") {
|
|
1754
|
+
if (/^\s*<\/[A-Za-z][A-Za-z0-9-]*\s*>/.test(firstVisible.value)) return true;
|
|
1755
|
+
if (isSanitizeStrippedConstruct(firstVisible.value)) return false;
|
|
1756
|
+
return null;
|
|
1757
|
+
}
|
|
1758
|
+
return false;
|
|
1759
|
+
}
|
|
1760
|
+
if (!firstVisible) return false;
|
|
1761
|
+
const firstContent = tailHastChildren.find((c) => !isSeparatorText(c));
|
|
1762
|
+
if (firstContent) {
|
|
1763
|
+
const start = firstContent.position?.start?.offset;
|
|
1764
|
+
const vStart = firstVisible.position?.start?.offset;
|
|
1765
|
+
const vEnd = firstVisible.position?.end?.offset;
|
|
1766
|
+
if (start !== void 0 && vStart !== void 0 && vEnd !== void 0) {
|
|
1767
|
+
if (start >= vStart && start < vEnd) return true;
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
if (firstVisible.type === "math") return false;
|
|
1771
|
+
if (firstVisible.type === "html" && isSanitizeStrippedConstruct(firstVisible.value)) return false;
|
|
1772
|
+
return null;
|
|
1773
|
+
}
|
|
1774
|
+
function isSeparatorText(node) {
|
|
1775
|
+
return node.type === "text" && node.position === void 0 && node.value.trim() === "";
|
|
1776
|
+
}
|
|
1777
|
+
function ownsTrailingLiteral(el, literal, prefixMdast) {
|
|
1778
|
+
const start = el.position?.start?.offset;
|
|
1779
|
+
if (start === void 0) return false;
|
|
1780
|
+
const owner = prefixMdast.find((c) => c.type === "html" && c.position?.start?.offset === start);
|
|
1781
|
+
if (!owner || owner.type !== "html") return false;
|
|
1782
|
+
const text = literal.value.trim();
|
|
1783
|
+
return text !== "" && owner.value.trimEnd().endsWith(text);
|
|
1784
|
+
}
|
|
1785
|
+
function isTrailingLiteralText(node) {
|
|
1786
|
+
return node.type === "text" && node.position === void 0 && node.value.trim() !== "";
|
|
1787
|
+
}
|
|
1788
|
+
function countTrailingNewlines(value) {
|
|
1789
|
+
let n = 0;
|
|
1790
|
+
for (let i = value.length - 1; i >= 0 && value[i] === "\n"; i--) n += 1;
|
|
1791
|
+
return n;
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
// src/components/incrementalParse/prefixInjection.ts
|
|
1795
|
+
import { normalizeIdentifier as normalizeIdentifier2 } from "micromark-util-normalize-identifier";
|
|
1796
|
+
function collectPrefixInjection(mdast, content, boundary, resume) {
|
|
1797
|
+
const resumeValid = resume != null && resume.boundary <= boundary;
|
|
1798
|
+
if (resumeValid && resume.uninjectable) return { events: resume.events, uninjectable: true };
|
|
1799
|
+
const resumeAt = resumeValid ? resume.boundary : 0;
|
|
1800
|
+
const events = resumeAt > 0 ? cloneEventsForAppend(resume.events) : [];
|
|
1801
|
+
let uninjectable = false;
|
|
1802
|
+
let cacheable = true;
|
|
1803
|
+
const pushRef = (token) => {
|
|
1804
|
+
const last = events[events.length - 1];
|
|
1805
|
+
if (last && last.kind === "refs") last.tokens.push(token);
|
|
1806
|
+
else events.push({ kind: "refs", tokens: [token] });
|
|
1807
|
+
};
|
|
1808
|
+
const visit7 = (node, nested) => {
|
|
1809
|
+
const type = node.type;
|
|
1810
|
+
if (type === "definition") {
|
|
1811
|
+
const start = node.position?.start?.offset;
|
|
1812
|
+
const end = node.position?.end?.offset;
|
|
1813
|
+
if (start !== void 0 && end !== void 0 && start < boundary) {
|
|
1814
|
+
const slice = content.slice(start, end);
|
|
1815
|
+
if (nested && slice.includes("\n")) uninjectable = true;
|
|
1816
|
+
else events.push({ kind: "def", source: slice });
|
|
1817
|
+
}
|
|
1818
|
+
return;
|
|
1819
|
+
}
|
|
1820
|
+
if (type === "footnoteDefinition") {
|
|
1821
|
+
const start = node.position?.start;
|
|
1822
|
+
const end = node.position?.end?.offset;
|
|
1823
|
+
if (start?.offset === void 0 || end === void 0 || start.offset >= boundary) return;
|
|
1824
|
+
if (nested) {
|
|
1825
|
+
uninjectable = true;
|
|
1826
|
+
return;
|
|
1827
|
+
}
|
|
1828
|
+
const lineStart = start.offset - (start.column - 1);
|
|
1829
|
+
events.push({
|
|
1830
|
+
kind: "footnoteDef",
|
|
1831
|
+
source: content.slice(lineStart, end),
|
|
1832
|
+
origStart: lineStart,
|
|
1833
|
+
origLine: start.line
|
|
1834
|
+
});
|
|
1835
|
+
return;
|
|
1836
|
+
}
|
|
1837
|
+
if (type === "footnoteReference") {
|
|
1838
|
+
const start = node.position?.start?.offset;
|
|
1839
|
+
const end = node.position?.end?.offset;
|
|
1840
|
+
if (start === void 0 || end === void 0) {
|
|
1841
|
+
uninjectable = true;
|
|
1842
|
+
return;
|
|
1843
|
+
}
|
|
1844
|
+
pushRef(content.slice(start, end));
|
|
1845
|
+
return;
|
|
1846
|
+
}
|
|
1847
|
+
const children = node.children;
|
|
1848
|
+
if (children) {
|
|
1849
|
+
for (const child of children) visit7(child, true);
|
|
1850
|
+
}
|
|
1851
|
+
};
|
|
1852
|
+
let lastStart = -1;
|
|
1853
|
+
for (const child of mdast.children) {
|
|
1854
|
+
const start = child.position?.start?.offset;
|
|
1855
|
+
if (start !== void 0) {
|
|
1856
|
+
if (start < lastStart) return { events: [], uninjectable: true, cacheable: false };
|
|
1857
|
+
lastStart = start;
|
|
1858
|
+
}
|
|
1859
|
+
if (start === void 0) {
|
|
1860
|
+
if (resumeAt > 0) return collectPrefixInjection(mdast, content, boundary, null);
|
|
1861
|
+
cacheable = false;
|
|
1862
|
+
visit7(child, false);
|
|
1863
|
+
continue;
|
|
1864
|
+
}
|
|
1865
|
+
if (start >= boundary || start < resumeAt) continue;
|
|
1866
|
+
visit7(child, false);
|
|
1867
|
+
}
|
|
1868
|
+
return { events, uninjectable, cacheable };
|
|
1869
|
+
}
|
|
1870
|
+
function cloneEventsForAppend(events) {
|
|
1871
|
+
const out = events.slice();
|
|
1872
|
+
const last = out[out.length - 1];
|
|
1873
|
+
if (last && last.kind === "refs") out[out.length - 1] = { kind: "refs", tokens: last.tokens.slice() };
|
|
1874
|
+
return out;
|
|
1875
|
+
}
|
|
1876
|
+
var TERMINATOR_LABEL = "__aimd_injection_terminator__";
|
|
1877
|
+
var INJECTION_TERMINATOR = `[${TERMINATOR_LABEL}]: __aimd_sentinel_link__`;
|
|
1878
|
+
function tailMentionsTerminator(tailSource) {
|
|
1879
|
+
return normalizeIdentifier2(tailSource).replace(/\[ /g, "[").includes(`[${normalizeIdentifier2(TERMINATOR_LABEL)}`);
|
|
1880
|
+
}
|
|
1881
|
+
function buildInjectionPrefix(events) {
|
|
1882
|
+
if (events.length === 0) return { text: "", segments: [] };
|
|
1883
|
+
let text = "";
|
|
1884
|
+
let line = 1;
|
|
1885
|
+
const segments = [];
|
|
1886
|
+
for (const event of events) {
|
|
1887
|
+
if (text.length > 0) {
|
|
1888
|
+
text += "\n\n";
|
|
1889
|
+
line += 2;
|
|
1890
|
+
}
|
|
1891
|
+
const injStart = text.length;
|
|
1892
|
+
const source = event.kind === "refs" ? event.tokens.join(" ") : event.source;
|
|
1893
|
+
if (event.kind === "footnoteDef") {
|
|
1894
|
+
segments.push({
|
|
1895
|
+
injStart,
|
|
1896
|
+
injEnd: injStart + source.length,
|
|
1897
|
+
offsetDelta: event.origStart - injStart,
|
|
1898
|
+
lineDelta: event.origLine - line
|
|
1899
|
+
});
|
|
1900
|
+
}
|
|
1901
|
+
text += source;
|
|
1902
|
+
line += countNewlines(source);
|
|
1903
|
+
}
|
|
1904
|
+
return { text: `${text}
|
|
1905
|
+
|
|
1906
|
+
${INJECTION_TERMINATOR}
|
|
1907
|
+
|
|
1908
|
+
`, segments };
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
// src/components/incrementalParse/spliceParse.ts
|
|
1912
|
+
function spliceTrees(input) {
|
|
1913
|
+
const { prevMdast, prevHast, tailMdast, tailHast, content, boundary, injectionPrefix, injectedSegments } = input;
|
|
1914
|
+
const injectedLen = injectionPrefix.length;
|
|
1915
|
+
const injectedLines = countNewlines(injectionPrefix);
|
|
1916
|
+
const prefixLines = countNewlines(content, boundary);
|
|
1917
|
+
const offsetDelta = boundary - injectedLen;
|
|
1918
|
+
const lineDelta = prefixLines - injectedLines;
|
|
1919
|
+
const prefixMdast = [];
|
|
1920
|
+
for (const child of prevMdast.children) {
|
|
1921
|
+
const start = child.position?.start?.offset;
|
|
1922
|
+
if (start !== void 0 && start < boundary) prefixMdast.push(child);
|
|
1923
|
+
}
|
|
1924
|
+
const attrs = attributeHastChildren(prevMdast, prevHast, boundary);
|
|
1925
|
+
const cutRegion = [];
|
|
1926
|
+
for (let i = 0; i < prevHast.children.length; i++) {
|
|
1927
|
+
if (attrs[i] < boundary) {
|
|
1928
|
+
const node2 = prevHast.children[i];
|
|
1929
|
+
const end = node2.position?.end?.offset;
|
|
1930
|
+
if (end !== void 0 && end > boundary) return null;
|
|
1931
|
+
if (isTrailingLiteralText(node2)) {
|
|
1932
|
+
const prev = i > 0 ? prevHast.children[i - 1] : void 0;
|
|
1933
|
+
if (!prev || prev.type !== "element" || prev.position === void 0) return null;
|
|
1934
|
+
if (!ownsTrailingLiteral(prev, node2, prefixMdast))
|
|
1935
|
+
return null;
|
|
1936
|
+
}
|
|
1937
|
+
cutRegion.push(node2);
|
|
1938
|
+
continue;
|
|
1939
|
+
}
|
|
1940
|
+
const node = prevHast.children[i];
|
|
1941
|
+
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
|
|
1942
|
+
// raw literal can only trail an `html` mdast node. A position-less
|
|
1943
|
+
// text after a `<p>` is the NEXT block's remnant — a stray end tag
|
|
1944
|
+
// (`</t>\na`) parse5 dropped, whose text merged with the wrap
|
|
1945
|
+
// separator — owned by the tail, which re-parses it; freezing it
|
|
1946
|
+
// here duplicated it (v2.4.0 review P3). Falls through to the
|
|
1947
|
+
// remnant look-ahead below, which bails to a full parse. And the
|
|
1948
|
+
// literal must really be THAT block's trailing text: the block's raw
|
|
1949
|
+
// source ends with it. A dropped-tag block right after a frozen html
|
|
1950
|
+
// element (`</details>\n\n</t>\ntext`) puts its remnant in the same
|
|
1951
|
+
// position, and freezing it duplicated it (release soak of the fix).
|
|
1952
|
+
ownsTrailingLiteral(prevHast.children[i - 1], node, prefixMdast)) {
|
|
1953
|
+
cutRegion.push(node);
|
|
1954
|
+
break;
|
|
1955
|
+
}
|
|
1956
|
+
for (let j = i; j < prevHast.children.length; j++) {
|
|
1957
|
+
const look = prevHast.children[j];
|
|
1958
|
+
if (look.type === "element" || look.position !== void 0) break;
|
|
1959
|
+
if (isTrailingLiteralText(look)) return null;
|
|
1960
|
+
}
|
|
1961
|
+
break;
|
|
1927
1962
|
}
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1963
|
+
const tailMdastChildren = tailMdast.children.filter((child) => {
|
|
1964
|
+
const start = child.position?.start?.offset;
|
|
1965
|
+
return !(start !== void 0 && start < injectedLen);
|
|
1966
|
+
});
|
|
1967
|
+
const tailWrapVisible = tailMdastChildren.some((child) => !isWrapInvisible(child));
|
|
1968
|
+
const prefixHtmlValues = prefixMdast.flatMap((c) => c.type === "html" ? [c.value] : []);
|
|
1969
|
+
if (hasStrayTablePart(prefixHtmlValues)) return null;
|
|
1970
|
+
if (rawTextRegionCrossesOut(prefixHtmlValues)) return null;
|
|
1971
|
+
const leadingHtml = [];
|
|
1972
|
+
for (const child of tailMdastChildren) {
|
|
1973
|
+
if (isWrapInvisible(child)) continue;
|
|
1974
|
+
if (child.type !== "html") break;
|
|
1975
|
+
if (STRAY_SYNTHESIZED_END_TAG_RE.test(child.value) || TABLE_PART_TAG_RE.test(child.value)) return null;
|
|
1976
|
+
leadingHtml.push(child.value);
|
|
1937
1977
|
}
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
const
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1978
|
+
if (headRoutedCaptureUnclosed(leadingHtml)) return null;
|
|
1979
|
+
const aligned = alignPrefixCut(prefixMdast, cutRegion, tailWrapVisible);
|
|
1980
|
+
if (aligned === null) return null;
|
|
1981
|
+
const hastChildren = aligned.children;
|
|
1982
|
+
const interiorFinalLiteral = aligned.interiorFinalLiteral;
|
|
1983
|
+
const stripResult = stripInjectedHast(tailMdast, tailHast, injectedLen, tailWrapVisible);
|
|
1984
|
+
if (stripResult === null) return null;
|
|
1985
|
+
const strippedTailHast = stripResult.rest;
|
|
1986
|
+
for (const child of tailMdastChildren) rebaseTree(child, offsetDelta, lineDelta);
|
|
1987
|
+
for (const child of strippedTailHast) rebaseTreeDual(child, injectedSegments, offsetDelta, lineDelta);
|
|
1988
|
+
const mdastChildren = prefixMdast.concat(tailMdastChildren);
|
|
1989
|
+
const seamMergeVerdict = stripResult.remnantMerged ?? tailLeadingTextIsHoist(tailMdastChildren, strippedTailHast);
|
|
1990
|
+
if (seamMergeVerdict === null) return null;
|
|
1991
|
+
const seamMergeAllowed = seamMergeVerdict;
|
|
1992
|
+
let firstTailChild = true;
|
|
1993
|
+
for (const child of strippedTailHast) {
|
|
1994
|
+
const tailEnd = hastChildren[hastChildren.length - 1];
|
|
1995
|
+
if (firstTailChild && child.type === "text" && child.position !== void 0) {
|
|
1951
1996
|
return null;
|
|
1952
1997
|
}
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1998
|
+
if (firstTailChild && tailEnd && tailEnd.type === "text" && child.type === "text" && child.position === void 0) {
|
|
1999
|
+
if (interiorFinalLiteral && tailEnd.value.trim() !== "") {
|
|
2000
|
+
if (seamMergeAllowed) return null;
|
|
2001
|
+
firstTailChild = false;
|
|
2002
|
+
hastChildren.push(child);
|
|
2003
|
+
continue;
|
|
2004
|
+
}
|
|
2005
|
+
const literalSeam = tailEnd.value.trim() !== "" && !tailWrapVisible;
|
|
2006
|
+
if (seamMergeAllowed || literalSeam) {
|
|
2007
|
+
hastChildren[hastChildren.length - 1] = { type: "text", value: tailEnd.value + child.value };
|
|
2008
|
+
firstTailChild = false;
|
|
2009
|
+
continue;
|
|
2010
|
+
}
|
|
1963
2011
|
}
|
|
2012
|
+
firstTailChild = false;
|
|
2013
|
+
hastChildren.push(child);
|
|
1964
2014
|
}
|
|
1965
|
-
if (
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
if (value.length < 7 || !value.endsWith("-->")) return false;
|
|
1976
|
-
const close = value.indexOf("-->", 4);
|
|
1977
|
-
const bangClose = value.indexOf("--!>", 4);
|
|
1978
|
-
if (close !== value.length - 3) return false;
|
|
1979
|
-
return bangClose === -1 || bangClose > close;
|
|
1980
|
-
}
|
|
1981
|
-
if (/^<!doctype/i.test(value)) return false;
|
|
1982
|
-
if (value.startsWith("<?") || /^<!(?:[A-Za-z]|\[CDATA\[)/.test(value)) {
|
|
1983
|
-
return value.indexOf(">") === value.length - 1;
|
|
1984
|
-
}
|
|
1985
|
-
return false;
|
|
1986
|
-
}
|
|
1987
|
-
function isSeparatorText(node) {
|
|
1988
|
-
return node.type === "text" && node.position === void 0 && node.value.trim() === "";
|
|
1989
|
-
}
|
|
1990
|
-
function ownsTrailingLiteral(el, literal, prefixMdast) {
|
|
1991
|
-
const start = el.position?.start?.offset;
|
|
1992
|
-
if (start === void 0) return false;
|
|
1993
|
-
const owner = prefixMdast.find((c) => c.type === "html" && c.position?.start?.offset === start);
|
|
1994
|
-
if (!owner || owner.type !== "html") return false;
|
|
1995
|
-
const text = literal.value.trim();
|
|
1996
|
-
return text !== "" && owner.value.trimEnd().endsWith(text);
|
|
1997
|
-
}
|
|
1998
|
-
function isTrailingLiteralText(node) {
|
|
1999
|
-
return node.type === "text" && node.position === void 0 && node.value.trim() !== "";
|
|
2000
|
-
}
|
|
2001
|
-
function countTrailingNewlines(value) {
|
|
2002
|
-
let n = 0;
|
|
2003
|
-
for (let i = value.length - 1; i >= 0 && value[i] === "\n"; i--) n += 1;
|
|
2004
|
-
return n;
|
|
2005
|
-
}
|
|
2006
|
-
function countNewlines(text, end = text.length) {
|
|
2007
|
-
let count = 0;
|
|
2008
|
-
for (let i = text.indexOf("\n"); i !== -1 && i < end; i = text.indexOf("\n", i + 1)) count += 1;
|
|
2009
|
-
for (let i = text.indexOf("\r"); i !== -1 && i < end; i = text.indexOf("\r", i + 1)) {
|
|
2010
|
-
if (text.charCodeAt(i + 1) !== 10) count += 1;
|
|
2011
|
-
}
|
|
2012
|
-
return count;
|
|
2015
|
+
if (!hastChildren.some((child) => child.position !== void 0)) return null;
|
|
2016
|
+
const docStart = { line: 1, column: 1, offset: 0 };
|
|
2017
|
+
const mdastRootPosition = tailMdast.position ? { start: docStart, end: rebasePoint(tailMdast.position.end, offsetDelta, lineDelta) } : prevMdast.position;
|
|
2018
|
+
const hastRootPosition = mdastRootPosition;
|
|
2019
|
+
const mdast = { type: "root", children: mdastChildren };
|
|
2020
|
+
if (mdastRootPosition) mdast.position = mdastRootPosition;
|
|
2021
|
+
const hast = { type: "root", children: hastChildren };
|
|
2022
|
+
if (hastRootPosition) hast.position = hastRootPosition;
|
|
2023
|
+
if (prevHast.data !== void 0) hast.data = prevHast.data;
|
|
2024
|
+
return { mdast, hast };
|
|
2013
2025
|
}
|
|
2014
2026
|
|
|
2015
2027
|
// src/components/incrementalParse/advanceIncrementalParse.ts
|
|
@@ -2131,6 +2143,38 @@ function normalizeForMatch(s) {
|
|
|
2131
2143
|
return normalizeIdentifier3(s);
|
|
2132
2144
|
}
|
|
2133
2145
|
|
|
2146
|
+
// src/components/blankLineScanner.ts
|
|
2147
|
+
function createBlankLineScanner() {
|
|
2148
|
+
let end = 0;
|
|
2149
|
+
let newline = false;
|
|
2150
|
+
let cr = false;
|
|
2151
|
+
return (source, from = 0) => {
|
|
2152
|
+
if (from === 0) {
|
|
2153
|
+
end = 0;
|
|
2154
|
+
newline = false;
|
|
2155
|
+
cr = false;
|
|
2156
|
+
}
|
|
2157
|
+
for (let i = from; i < source.length; i++) {
|
|
2158
|
+
const c = source[i];
|
|
2159
|
+
if (c === "\n") {
|
|
2160
|
+
if (newline) {
|
|
2161
|
+
end = i + 1;
|
|
2162
|
+
newline = false;
|
|
2163
|
+
} else newline = true;
|
|
2164
|
+
cr = false;
|
|
2165
|
+
} else if (newline) {
|
|
2166
|
+
if ((c === " " || c === " ") && !cr) continue;
|
|
2167
|
+
if (c === "\r" && !cr) cr = true;
|
|
2168
|
+
else {
|
|
2169
|
+
newline = false;
|
|
2170
|
+
cr = false;
|
|
2171
|
+
}
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
return end;
|
|
2175
|
+
};
|
|
2176
|
+
}
|
|
2177
|
+
|
|
2134
2178
|
// src/components/collectDefLabels.ts
|
|
2135
2179
|
var SCANNER_BOUNDARY_PROFILE = { defListEnabled: false, mathFlow: false, referenceTaint: false };
|
|
2136
2180
|
function buildProcessor() {
|
|
@@ -2162,19 +2206,12 @@ var setsEqual = (a, b) => {
|
|
|
2162
2206
|
for (const v of a) if (!b.has(v)) return false;
|
|
2163
2207
|
return true;
|
|
2164
2208
|
};
|
|
2165
|
-
var BLANK_LINE_RE = /\r?\n[ \t]*\r?\n/g;
|
|
2166
|
-
function lastRegionStart(source) {
|
|
2167
|
-
BLANK_LINE_RE.lastIndex = 0;
|
|
2168
|
-
let start = 0;
|
|
2169
|
-
for (let m = BLANK_LINE_RE.exec(source); m !== null; m = BLANK_LINE_RE.exec(source)) {
|
|
2170
|
-
start = m.index + m[0].length;
|
|
2171
|
-
}
|
|
2172
|
-
return start;
|
|
2173
|
-
}
|
|
2174
2209
|
var DEF_LINE_START_RE = /^[ \t>*+\d.)-]*\[(?:[^\]\\]|\\[\s\S])*\]:/m;
|
|
2175
2210
|
function createDefLabelScanner(parse = collectDefLabels) {
|
|
2176
2211
|
let prevSource = null;
|
|
2177
2212
|
let prevLabels = null;
|
|
2213
|
+
const scanBlankLines = createBlankLineScanner();
|
|
2214
|
+
let regionStart = 0;
|
|
2178
2215
|
let frozenEnd = 0;
|
|
2179
2216
|
let frozenFootnotes = /* @__PURE__ */ new Set();
|
|
2180
2217
|
let frozenLinks = /* @__PURE__ */ new Set();
|
|
@@ -2187,13 +2224,16 @@ function createDefLabelScanner(parse = collectDefLabels) {
|
|
|
2187
2224
|
};
|
|
2188
2225
|
return {
|
|
2189
2226
|
scan(source) {
|
|
2227
|
+
if (source === prevSource && prevLabels !== null) return prevLabels;
|
|
2228
|
+
const previousRegionStart = regionStart;
|
|
2229
|
+
const appended = prevSource !== null && source.startsWith(prevSource);
|
|
2230
|
+
regionStart = scanBlankLines(source, appended ? prevSource.length : 0);
|
|
2190
2231
|
let isAppend = false;
|
|
2191
2232
|
if (prevSource !== null && prevLabels !== null) {
|
|
2192
2233
|
if (source === prevSource) return prevLabels;
|
|
2193
2234
|
if (source.startsWith(prevSource)) {
|
|
2194
2235
|
isAppend = true;
|
|
2195
|
-
const
|
|
2196
|
-
const region = prevSource.slice(regionStart) + source.slice(prevSource.length);
|
|
2236
|
+
const region = source.slice(previousRegionStart);
|
|
2197
2237
|
if (!DEF_LINE_START_RE.test(region)) {
|
|
2198
2238
|
prevSource = source;
|
|
2199
2239
|
return prevLabels;
|
|
@@ -2426,8 +2466,115 @@ function* extractContributions(mdast, options = {}) {
|
|
|
2426
2466
|
for (const c of out) yield c;
|
|
2427
2467
|
}
|
|
2428
2468
|
|
|
2469
|
+
// src/components/registryIndex.ts
|
|
2470
|
+
function buildRegistryIndex(registry) {
|
|
2471
|
+
const index = {
|
|
2472
|
+
footnotes: /* @__PURE__ */ new Map(),
|
|
2473
|
+
links: /* @__PURE__ */ new Map(),
|
|
2474
|
+
numbers: /* @__PURE__ */ new Map(),
|
|
2475
|
+
counts: /* @__PURE__ */ new Map(),
|
|
2476
|
+
occurrences: /* @__PURE__ */ new Map(),
|
|
2477
|
+
labelOccurrences: /* @__PURE__ */ new Map()
|
|
2478
|
+
};
|
|
2479
|
+
for (const sym of registry.chunkOrder) {
|
|
2480
|
+
const data = registry.chunkData.get(sym);
|
|
2481
|
+
if (!data) continue;
|
|
2482
|
+
for (const label of data.defs.keys()) if (!index.footnotes.has(label)) index.footnotes.set(label, sym);
|
|
2483
|
+
for (const label of data.linkDefs.keys()) if (!index.links.has(label)) index.links.set(label, sym);
|
|
2484
|
+
const local = /* @__PURE__ */ new Map();
|
|
2485
|
+
index.occurrences.set(sym, local);
|
|
2486
|
+
for (const ref of data.refs) {
|
|
2487
|
+
if (ref.kind !== "footnote") continue;
|
|
2488
|
+
const label = ref.label;
|
|
2489
|
+
if (!index.numbers.has(label)) index.numbers.set(label, index.numbers.size + 1);
|
|
2490
|
+
const total = (index.counts.get(label) ?? 0) + 1;
|
|
2491
|
+
index.counts.set(label, total);
|
|
2492
|
+
const prior = local.get(label);
|
|
2493
|
+
if (prior) prior.count++;
|
|
2494
|
+
else {
|
|
2495
|
+
const range = { start: total, count: 1 };
|
|
2496
|
+
local.set(label, range);
|
|
2497
|
+
let byChunk = index.labelOccurrences.get(label);
|
|
2498
|
+
if (!byChunk) index.labelOccurrences.set(label, byChunk = /* @__PURE__ */ new Map());
|
|
2499
|
+
byChunk.set(sym, range);
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
return index;
|
|
2504
|
+
}
|
|
2505
|
+
|
|
2506
|
+
// src/components/registrySubscriptions.ts
|
|
2507
|
+
function equal(a, b) {
|
|
2508
|
+
if (a.owner !== b.owner || a.url !== b.url || a.title !== b.title || a.number !== b.number || a.count !== b.count)
|
|
2509
|
+
return false;
|
|
2510
|
+
if (a.occurrences?.size !== b.occurrences?.size) return false;
|
|
2511
|
+
if (a.occurrences) {
|
|
2512
|
+
for (const [chunk, range] of a.occurrences) {
|
|
2513
|
+
const next = b.occurrences?.get(chunk);
|
|
2514
|
+
if (!next || next.start !== range.start || next.count !== range.count) return false;
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
return true;
|
|
2518
|
+
}
|
|
2519
|
+
function createRegistrySubscriptions(read) {
|
|
2520
|
+
const groups = { link: /* @__PURE__ */ new Map(), footnote: /* @__PURE__ */ new Map() };
|
|
2521
|
+
const snapshot = (kind, label, { registry, index }) => {
|
|
2522
|
+
if (kind === "link") {
|
|
2523
|
+
const owner = index.links.get(label);
|
|
2524
|
+
const def = owner ? registry.chunkData.get(owner)?.linkDefs.get(label) : void 0;
|
|
2525
|
+
return { owner, url: def?.url, title: def?.title };
|
|
2526
|
+
}
|
|
2527
|
+
return {
|
|
2528
|
+
owner: index.footnotes.get(label),
|
|
2529
|
+
number: index.numbers.get(label),
|
|
2530
|
+
count: index.counts.get(label),
|
|
2531
|
+
occurrences: index.labelOccurrences.get(label)
|
|
2532
|
+
};
|
|
2533
|
+
};
|
|
2534
|
+
return {
|
|
2535
|
+
subscribe(kind, rawLabel, cb) {
|
|
2536
|
+
const label = normalizeId(rawLabel);
|
|
2537
|
+
const map = groups[kind];
|
|
2538
|
+
let group = map.get(label);
|
|
2539
|
+
if (!group) {
|
|
2540
|
+
group = { snapshot: snapshot(kind, label, read()), listeners: /* @__PURE__ */ new Set() };
|
|
2541
|
+
map.set(label, group);
|
|
2542
|
+
}
|
|
2543
|
+
const listener = () => cb();
|
|
2544
|
+
group.listeners.add(listener);
|
|
2545
|
+
return () => {
|
|
2546
|
+
group.listeners.delete(listener);
|
|
2547
|
+
if (group.listeners.size === 0 && map.get(label) === group) map.delete(label);
|
|
2548
|
+
};
|
|
2549
|
+
},
|
|
2550
|
+
collect() {
|
|
2551
|
+
if (groups.link.size === 0 && groups.footnote.size === 0) return [];
|
|
2552
|
+
const state = read();
|
|
2553
|
+
const callbacks = [];
|
|
2554
|
+
for (const kind of ["link", "footnote"]) {
|
|
2555
|
+
for (const [label, group] of groups[kind]) {
|
|
2556
|
+
const next = snapshot(kind, label, state);
|
|
2557
|
+
if (!equal(group.snapshot, next)) callbacks.push(...group.listeners);
|
|
2558
|
+
group.snapshot = next;
|
|
2559
|
+
}
|
|
2560
|
+
}
|
|
2561
|
+
return callbacks;
|
|
2562
|
+
}
|
|
2563
|
+
};
|
|
2564
|
+
}
|
|
2565
|
+
|
|
2429
2566
|
// src/components/documentRegistry.ts
|
|
2430
2567
|
function createRegistry(onEmpty) {
|
|
2568
|
+
let index;
|
|
2569
|
+
let indexedVersion = -1;
|
|
2570
|
+
const getIndex = () => {
|
|
2571
|
+
if (!index || indexedVersion !== reg.version) {
|
|
2572
|
+
index = buildRegistryIndex(reg);
|
|
2573
|
+
indexedVersion = reg.version;
|
|
2574
|
+
}
|
|
2575
|
+
return index;
|
|
2576
|
+
};
|
|
2577
|
+
const labels = createRegistrySubscriptions(() => ({ registry: reg, index: getIndex() }));
|
|
2431
2578
|
const reg = {
|
|
2432
2579
|
chunkOrder: [],
|
|
2433
2580
|
chunkData: /* @__PURE__ */ new Map(),
|
|
@@ -2578,73 +2725,29 @@ function createRegistry(onEmpty) {
|
|
|
2578
2725
|
this._subscribers.delete(cb);
|
|
2579
2726
|
};
|
|
2580
2727
|
},
|
|
2728
|
+
subscribeLabel(kind, label, cb) {
|
|
2729
|
+
return labels.subscribe(kind, label, cb);
|
|
2730
|
+
},
|
|
2581
2731
|
canonicalFootnoteFor(label) {
|
|
2582
|
-
|
|
2583
|
-
for (const sym of this.chunkOrder) {
|
|
2584
|
-
const data = this.chunkData.get(sym);
|
|
2585
|
-
if (data?.defs.has(id)) return sym;
|
|
2586
|
-
}
|
|
2587
|
-
return null;
|
|
2732
|
+
return getIndex().footnotes.get(normalizeId(label)) ?? null;
|
|
2588
2733
|
},
|
|
2589
2734
|
canonicalLinkFor(label) {
|
|
2590
|
-
|
|
2591
|
-
for (const sym of this.chunkOrder) {
|
|
2592
|
-
const data = this.chunkData.get(sym);
|
|
2593
|
-
if (data?.linkDefs.has(id)) return sym;
|
|
2594
|
-
}
|
|
2595
|
-
return null;
|
|
2735
|
+
return getIndex().links.get(normalizeId(label)) ?? null;
|
|
2596
2736
|
},
|
|
2597
2737
|
globalNumber(label) {
|
|
2598
|
-
|
|
2599
|
-
let n = 0;
|
|
2600
|
-
const seen = /* @__PURE__ */ new Set();
|
|
2601
|
-
for (const sym of this.chunkOrder) {
|
|
2602
|
-
const data = this.chunkData.get(sym);
|
|
2603
|
-
if (!data) continue;
|
|
2604
|
-
for (const ref of data.refs) {
|
|
2605
|
-
if (ref.kind !== "footnote") continue;
|
|
2606
|
-
if (!seen.has(ref.label)) {
|
|
2607
|
-
seen.add(ref.label);
|
|
2608
|
-
n++;
|
|
2609
|
-
if (ref.label === id) return n;
|
|
2610
|
-
}
|
|
2611
|
-
}
|
|
2612
|
-
}
|
|
2613
|
-
return null;
|
|
2738
|
+
return getIndex().numbers.get(normalizeId(label)) ?? null;
|
|
2614
2739
|
},
|
|
2615
2740
|
resolveLinkDef(label) {
|
|
2616
|
-
const
|
|
2617
|
-
|
|
2618
|
-
return this.chunkData.get(sym)?.linkDefs.get(
|
|
2741
|
+
const id = normalizeId(label);
|
|
2742
|
+
const sym = getIndex().links.get(id);
|
|
2743
|
+
return sym ? this.chunkData.get(sym)?.linkDefs.get(id) ?? null : null;
|
|
2619
2744
|
},
|
|
2620
2745
|
getRefsForLabel(label) {
|
|
2621
|
-
|
|
2622
|
-
let n = 0;
|
|
2623
|
-
for (const sym of this.chunkOrder) {
|
|
2624
|
-
const data = this.chunkData.get(sym);
|
|
2625
|
-
if (!data) continue;
|
|
2626
|
-
for (const ref of data.refs) {
|
|
2627
|
-
if (ref.kind === "footnote" && ref.label === id) n++;
|
|
2628
|
-
}
|
|
2629
|
-
}
|
|
2630
|
-
return n;
|
|
2746
|
+
return getIndex().counts.get(normalizeId(label)) ?? 0;
|
|
2631
2747
|
},
|
|
2632
2748
|
globalOccurrenceForRef(chunkSym, label, localOccurrence) {
|
|
2633
|
-
const
|
|
2634
|
-
|
|
2635
|
-
for (const sym of this.chunkOrder) {
|
|
2636
|
-
const data = this.chunkData.get(sym);
|
|
2637
|
-
if (!data) continue;
|
|
2638
|
-
let localCount = 0;
|
|
2639
|
-
for (const ref of data.refs) {
|
|
2640
|
-
if (ref.kind !== "footnote") continue;
|
|
2641
|
-
if (ref.label !== id) continue;
|
|
2642
|
-
localCount++;
|
|
2643
|
-
global2++;
|
|
2644
|
-
if (sym === chunkSym && localCount === localOccurrence) return global2;
|
|
2645
|
-
}
|
|
2646
|
-
}
|
|
2647
|
-
return null;
|
|
2749
|
+
const range = getIndex().occurrences.get(chunkSym)?.get(normalizeId(label));
|
|
2750
|
+
return range && Number.isInteger(localOccurrence) && localOccurrence > 0 && localOccurrence <= range.count ? range.start + localOccurrence - 1 : null;
|
|
2648
2751
|
},
|
|
2649
2752
|
_notify() {
|
|
2650
2753
|
this.version++;
|
|
@@ -2652,7 +2755,9 @@ function createRegistry(onEmpty) {
|
|
|
2652
2755
|
this._notifyScheduled = true;
|
|
2653
2756
|
queueMicrotask(() => {
|
|
2654
2757
|
this._notifyScheduled = false;
|
|
2758
|
+
const labelCallbacks = labels.collect();
|
|
2655
2759
|
for (const cb of [...this._subscribers]) cb();
|
|
2760
|
+
for (const cb of labelCallbacks) cb();
|
|
2656
2761
|
});
|
|
2657
2762
|
}
|
|
2658
2763
|
};
|
|
@@ -2709,7 +2814,7 @@ var ENGINE_PLACEHOLDER_TAGS = /* @__PURE__ */ new Set([
|
|
|
2709
2814
|
"cross-chunk-image"
|
|
2710
2815
|
]);
|
|
2711
2816
|
var ENGINE_PROVENANCE_PROPERTY = "engineProvenance";
|
|
2712
|
-
function walk(parent, provenance) {
|
|
2817
|
+
function walk(parent, provenance, ancestors) {
|
|
2713
2818
|
const children = parent.children;
|
|
2714
2819
|
let i = 0;
|
|
2715
2820
|
while (i < children.length) {
|
|
@@ -2720,21 +2825,32 @@ function walk(parent, provenance) {
|
|
|
2720
2825
|
const genuine = provenance !== "" && typeof stamped === "string" && stamped === provenance;
|
|
2721
2826
|
if (genuine) {
|
|
2722
2827
|
delete props[ENGINE_PROVENANCE_PROPERTY];
|
|
2723
|
-
|
|
2828
|
+
if (ancestors && (node.tagName === "cross-chunk-link" || node.tagName === "cross-chunk-image")) {
|
|
2829
|
+
(node.data ??= {}).referenceAncestors = ancestors.slice();
|
|
2830
|
+
}
|
|
2831
|
+
ancestors?.push(
|
|
2832
|
+
node.tagName === "cross-chunk-link" ? "a" : node.tagName === "cross-chunk-image" ? "img" : node.tagName
|
|
2833
|
+
);
|
|
2834
|
+
walk(node, provenance, ancestors);
|
|
2835
|
+
ancestors?.pop();
|
|
2724
2836
|
i += 1;
|
|
2725
2837
|
} else {
|
|
2726
2838
|
children.splice(i, 1, ...node.children);
|
|
2727
2839
|
}
|
|
2728
2840
|
continue;
|
|
2729
2841
|
}
|
|
2730
|
-
if (node.type === "element")
|
|
2842
|
+
if (node.type === "element") {
|
|
2843
|
+
ancestors?.push(node.tagName);
|
|
2844
|
+
walk(node, provenance, ancestors);
|
|
2845
|
+
ancestors?.pop();
|
|
2846
|
+
}
|
|
2731
2847
|
i += 1;
|
|
2732
2848
|
}
|
|
2733
2849
|
}
|
|
2734
2850
|
function rehypeVerifyEngineTags(options) {
|
|
2735
2851
|
const provenance = options?.provenance ?? "";
|
|
2736
2852
|
return function transformer(tree) {
|
|
2737
|
-
walk(tree, provenance);
|
|
2853
|
+
walk(tree, provenance, options?.referenceAncestors ? [] : void 0);
|
|
2738
2854
|
};
|
|
2739
2855
|
}
|
|
2740
2856
|
|
|
@@ -2755,16 +2871,18 @@ import remarkRemoveComments from "remark-remove-comments";
|
|
|
2755
2871
|
// src/components/rehypeRebaseHashLinks.ts
|
|
2756
2872
|
import { visit as visit5 } from "unist-util-visit";
|
|
2757
2873
|
var DEFAULT_PREFIX = "user-content-";
|
|
2874
|
+
function rebaseHashHref(href, prefix) {
|
|
2875
|
+
const hashPrefix = "#" + prefix;
|
|
2876
|
+
return href.startsWith("#") && !href.startsWith(hashPrefix) ? hashPrefix + href.slice(1) : href;
|
|
2877
|
+
}
|
|
2758
2878
|
var rehypeRebaseHashLinks = (options) => {
|
|
2759
2879
|
const prefix = options?.prefix ?? DEFAULT_PREFIX;
|
|
2760
|
-
const hashPrefix = "#" + prefix;
|
|
2761
2880
|
return (tree) => {
|
|
2762
2881
|
visit5(tree, "element", (node) => {
|
|
2763
2882
|
if (node.tagName !== "a") return;
|
|
2764
2883
|
const href = node.properties?.href;
|
|
2765
2884
|
if (typeof href !== "string" || !href.startsWith("#")) return;
|
|
2766
|
-
|
|
2767
|
-
node.properties.href = hashPrefix + href.slice(1);
|
|
2885
|
+
node.properties.href = rebaseHashHref(href, prefix);
|
|
2768
2886
|
});
|
|
2769
2887
|
};
|
|
2770
2888
|
};
|
|
@@ -2850,7 +2968,15 @@ function buildCoreRehypePlugins(sanitizeSchema2, clobberPrefix, options) {
|
|
|
2850
2968
|
[rehypeRaw, { passThrough: [] }],
|
|
2851
2969
|
// Unwrap forged engine placeholders BEFORE sanitize admits their tag
|
|
2852
2970
|
// names. Only when the caller holds a credential (see the option's doc).
|
|
2853
|
-
...options ? [
|
|
2971
|
+
...options ? [
|
|
2972
|
+
[
|
|
2973
|
+
rehypeVerifyEngineTags,
|
|
2974
|
+
{
|
|
2975
|
+
provenance: options.provenance,
|
|
2976
|
+
...sanitizeSchema2.ancestors?.a || sanitizeSchema2.ancestors?.img ? { referenceAncestors: true } : {}
|
|
2977
|
+
}
|
|
2978
|
+
]
|
|
2979
|
+
] : [],
|
|
2854
2980
|
// Sanitize HTML while allowing <mark> (highlight), KaTeX class names,
|
|
2855
2981
|
// and any extra protocols the caller permitted via the `sanitizeSchema`
|
|
2856
2982
|
// prop. Override `clobberPrefix` with the instance-scoped value — the
|
|
@@ -2924,11 +3050,9 @@ function buildCrossChunkHandlers() {
|
|
|
2924
3050
|
type: "element",
|
|
2925
3051
|
tagName: "cross-chunk-link",
|
|
2926
3052
|
properties: {
|
|
2927
|
-
//
|
|
2928
|
-
//
|
|
2929
|
-
|
|
2930
|
-
// which also preserves source case. Registry lookups normalize
|
|
2931
|
-
// internally, so cross-chunk case-insensitive matching still works.
|
|
3053
|
+
// Display labels decode escapes; registry identifiers must retain
|
|
3054
|
+
// those bytes. Never use the display label as the lookup key.
|
|
3055
|
+
identifier: node.identifier,
|
|
2932
3056
|
label: node.label ?? node.identifier,
|
|
2933
3057
|
referenceType: node.referenceType,
|
|
2934
3058
|
documentId: s.options.documentId,
|
|
@@ -2947,6 +3071,7 @@ function buildCrossChunkHandlers() {
|
|
|
2947
3071
|
type: "element",
|
|
2948
3072
|
tagName: "cross-chunk-image",
|
|
2949
3073
|
properties: {
|
|
3074
|
+
identifier: node.identifier,
|
|
2950
3075
|
label: node.label ?? node.identifier,
|
|
2951
3076
|
referenceType: node.referenceType,
|
|
2952
3077
|
alt: node.alt ?? "",
|
|
@@ -4209,8 +4334,8 @@ var sanitizeSchema = deepFreeze(
|
|
|
4209
4334
|
attributes: {
|
|
4210
4335
|
...defaultSchema.attributes,
|
|
4211
4336
|
code: mergeClassNameAllowlist(defaultSchema.attributes?.code, ["math-inline", "math-display"]),
|
|
4212
|
-
"cross-chunk-link": ["label", "referenceType", "documentId", "localUrl", "localTitle"],
|
|
4213
|
-
"cross-chunk-image": ["label", "referenceType", "documentId", "alt", "localUrl", "localTitle"],
|
|
4337
|
+
"cross-chunk-link": ["identifier", "label", "referenceType", "documentId", "localUrl", "localTitle"],
|
|
4338
|
+
"cross-chunk-image": ["identifier", "label", "referenceType", "documentId", "alt", "localUrl", "localTitle"],
|
|
4214
4339
|
"footnote-sup": ["label", "localOccurrence", "localNumber", "documentId"]
|
|
4215
4340
|
},
|
|
4216
4341
|
strip: [.../* @__PURE__ */ new Set([...defaultSchema.strip || [], ...STRIPPED_TAGS])]
|
|
@@ -4246,6 +4371,49 @@ function sanitizeCrossChunkUrl(rawUrl, key, tagName, urlTransform, schema) {
|
|
|
4246
4371
|
return String(transformed);
|
|
4247
4372
|
}
|
|
4248
4373
|
|
|
4374
|
+
// src/components/resolveCrossChunkReference.ts
|
|
4375
|
+
import rehypeSanitize2 from "rehype-sanitize";
|
|
4376
|
+
import { normalizeUri as normalizeUri3 } from "micromark-util-sanitize-uri";
|
|
4377
|
+
function resolveCrossChunkReference(input, schema, urlTransform, clobberPrefix) {
|
|
4378
|
+
const key = input.tagName === "a" ? "href" : "src";
|
|
4379
|
+
const element = {
|
|
4380
|
+
type: "element",
|
|
4381
|
+
tagName: input.tagName,
|
|
4382
|
+
properties: {
|
|
4383
|
+
[key]: normalizeUri3(input.url),
|
|
4384
|
+
...input.tagName === "img" ? { alt: input.alt ?? "" } : {},
|
|
4385
|
+
...input.title !== void 0 ? { title: input.title } : {}
|
|
4386
|
+
},
|
|
4387
|
+
children: input.tagName === "a" ? [{ type: "text", value: "__reference_children__" }] : []
|
|
4388
|
+
};
|
|
4389
|
+
const requiredAncestors = schema.ancestors?.[input.tagName];
|
|
4390
|
+
const recordedAncestors = input.node?.data?.referenceAncestors;
|
|
4391
|
+
let finalSchema = schema;
|
|
4392
|
+
if (requiredAncestors && Array.isArray(recordedAncestors) && requiredAncestors.some((tag) => recordedAncestors.includes(tag))) {
|
|
4393
|
+
const ancestors = { ...schema.ancestors };
|
|
4394
|
+
delete ancestors[input.tagName];
|
|
4395
|
+
finalSchema = { ...schema, ancestors };
|
|
4396
|
+
}
|
|
4397
|
+
const root2 = rehypeSanitize2({ ...finalSchema, clobberPrefix })({ type: "root", children: [element] });
|
|
4398
|
+
const node = root2.children[0];
|
|
4399
|
+
if (node?.type !== "element") return { element: null, keepChildren: node?.type === "text" };
|
|
4400
|
+
if (node.tagName === "a" && typeof node.properties.href === "string") {
|
|
4401
|
+
node.properties.href = rebaseHashHref(node.properties.href, clobberPrefix);
|
|
4402
|
+
}
|
|
4403
|
+
node.children = input.node?.children ?? [];
|
|
4404
|
+
if (input.node?.position) node.position = input.node.position;
|
|
4405
|
+
buildTransform({
|
|
4406
|
+
allowedElements: void 0,
|
|
4407
|
+
disallowedElements: void 0,
|
|
4408
|
+
allowElement: void 0,
|
|
4409
|
+
skipHtml: void 0,
|
|
4410
|
+
unwrapDisallowed: void 0,
|
|
4411
|
+
urlTransform
|
|
4412
|
+
})(node, 0, root2);
|
|
4413
|
+
node.children = [];
|
|
4414
|
+
return { element: node, keepChildren: false };
|
|
4415
|
+
}
|
|
4416
|
+
|
|
4249
4417
|
// src/plugins/defs.ts
|
|
4250
4418
|
function getEnginePluginInternals(plugin) {
|
|
4251
4419
|
const candidate = plugin;
|
|
@@ -4450,6 +4618,8 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4450
4618
|
let source = "";
|
|
4451
4619
|
let visibleEnd = 0;
|
|
4452
4620
|
let pending = [];
|
|
4621
|
+
let pendingHead = 0;
|
|
4622
|
+
const pendingCount = () => pending.length - pendingHead;
|
|
4453
4623
|
let tentativeEnd = 0;
|
|
4454
4624
|
let finished = false;
|
|
4455
4625
|
let seam;
|
|
@@ -4494,7 +4664,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4494
4664
|
cancelFrame = void 0;
|
|
4495
4665
|
};
|
|
4496
4666
|
const ensureScheduled = () => {
|
|
4497
|
-
if (disposed || cancelFrame ||
|
|
4667
|
+
if (disposed || cancelFrame || pendingCount() === 0) return;
|
|
4498
4668
|
lastTickAt = now();
|
|
4499
4669
|
credit = 0;
|
|
4500
4670
|
cancelFrame = schedule(tick);
|
|
@@ -4508,31 +4678,38 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4508
4678
|
const params = resolveParams();
|
|
4509
4679
|
let rate;
|
|
4510
4680
|
if (finished && drainDeadlineAt !== void 0) {
|
|
4511
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4681
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, drainDeadlineAt - t));
|
|
4512
4682
|
} else if (gapWindow.length > 0 && lastArrivalAt !== void 0) {
|
|
4513
4683
|
const gaps = gapWindow.map((s) => s.gap).sort((a, b) => a - b);
|
|
4514
4684
|
const intervalQ = gaps[Math.min(gaps.length - 1, Math.floor(gaps.length * INTERVAL_QUANTILE))];
|
|
4515
4685
|
const horizon = Math.max(16, Math.min(params.bufferFactor * intervalQ + HORIZON_PAD_MS, params.maxLagMs));
|
|
4516
4686
|
const deadline = Math.max(lastArrivalAt + horizon, t + DEADLINE_FLOOR_MS);
|
|
4517
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4687
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, deadline - t));
|
|
4518
4688
|
} else {
|
|
4519
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4689
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, params.correctionTauMs));
|
|
4520
4690
|
}
|
|
4521
4691
|
credit += rate * dt / 1e3;
|
|
4522
|
-
const reveal = Math.min(Math.floor(credit),
|
|
4692
|
+
const reveal = Math.min(Math.floor(credit), pendingCount());
|
|
4523
4693
|
if (reveal > 0) {
|
|
4524
|
-
visibleEnd = pending[reveal - 1];
|
|
4525
|
-
|
|
4526
|
-
|
|
4694
|
+
visibleEnd = pending[pendingHead + reveal - 1];
|
|
4695
|
+
pendingHead += reveal;
|
|
4696
|
+
if (pendingHead === pending.length) {
|
|
4697
|
+
pending = [];
|
|
4698
|
+
pendingHead = 0;
|
|
4699
|
+
} else if (pendingHead >= 1024 && pendingHead * 2 >= pending.length) {
|
|
4700
|
+
pending = pending.slice(pendingHead);
|
|
4701
|
+
pendingHead = 0;
|
|
4702
|
+
}
|
|
4703
|
+
credit = pendingCount() > 0 ? credit - reveal : 0;
|
|
4527
4704
|
notify();
|
|
4528
4705
|
}
|
|
4529
|
-
if (!disposed && !cancelFrame &&
|
|
4706
|
+
if (!disposed && !cancelFrame && pendingCount() > 0) cancelFrame = schedule(tick);
|
|
4530
4707
|
};
|
|
4531
4708
|
const resegmentTail = () => {
|
|
4532
|
-
if (seam !== void 0 && seam < source.length && pending[pending.length - 1] === seam) {
|
|
4709
|
+
if (pendingCount() > 0 && seam !== void 0 && seam < source.length && pending[pending.length - 1] === seam) {
|
|
4533
4710
|
pending.pop();
|
|
4534
4711
|
}
|
|
4535
|
-
const from =
|
|
4712
|
+
const from = pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd;
|
|
4536
4713
|
let anchor = from;
|
|
4537
4714
|
if (seam !== void 0 && from <= seam) {
|
|
4538
4715
|
anchor = Math.max(0, from - RESUME_LOOKBACK);
|
|
@@ -4566,6 +4743,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4566
4743
|
visibleEnd = next.length;
|
|
4567
4744
|
tentativeEnd = next.length;
|
|
4568
4745
|
pending = [];
|
|
4746
|
+
pendingHead = 0;
|
|
4569
4747
|
seam = next.length;
|
|
4570
4748
|
credit = 0;
|
|
4571
4749
|
cancelScheduled();
|
|
@@ -4597,7 +4775,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4597
4775
|
if (finished) return;
|
|
4598
4776
|
finished = true;
|
|
4599
4777
|
lastArrivalAt = void 0;
|
|
4600
|
-
if (tentativeEnd > (
|
|
4778
|
+
if (tentativeEnd > (pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd)) {
|
|
4601
4779
|
pending.push(tentativeEnd);
|
|
4602
4780
|
}
|
|
4603
4781
|
const params = resolveParams();
|
|
@@ -4623,10 +4801,11 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4623
4801
|
snap,
|
|
4624
4802
|
flush() {
|
|
4625
4803
|
disposed = false;
|
|
4626
|
-
const target = finished ? source.length :
|
|
4804
|
+
const target = finished ? source.length : pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd;
|
|
4627
4805
|
if (target <= visibleEnd) return;
|
|
4628
4806
|
visibleEnd = target;
|
|
4629
4807
|
pending = [];
|
|
4808
|
+
pendingHead = 0;
|
|
4630
4809
|
credit = 0;
|
|
4631
4810
|
cancelScheduled();
|
|
4632
4811
|
notify();
|
|
@@ -5476,6 +5655,7 @@ export {
|
|
|
5476
5655
|
rehypeRebaseHashLinks_default as rehypeRebaseHashLinks,
|
|
5477
5656
|
rehypeVerifyEngineTags,
|
|
5478
5657
|
removeComments,
|
|
5658
|
+
resolveCrossChunkReference,
|
|
5479
5659
|
sanitizeCrossChunkUrl,
|
|
5480
5660
|
sanitizeSchema,
|
|
5481
5661
|
shortenDocumentId,
|