@ai-react-markdown/engine 2.10.1 → 2.12.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/README.md +1 -1
- package/dist/index.cjs +528 -144
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +113 -2
- package/dist/index.d.ts +113 -2
- package/dist/index.dev.cjs +528 -144
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +524 -144
- package/dist/index.dev.js.map +1 -1
- package/dist/index.js +524 -144
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/dist/index.dev.js
CHANGED
|
@@ -2138,6 +2138,38 @@ function normalizeForMatch(s) {
|
|
|
2138
2138
|
return normalizeIdentifier3(s);
|
|
2139
2139
|
}
|
|
2140
2140
|
|
|
2141
|
+
// src/components/blankLineScanner.ts
|
|
2142
|
+
function createBlankLineScanner() {
|
|
2143
|
+
let end = 0;
|
|
2144
|
+
let newline = false;
|
|
2145
|
+
let cr = false;
|
|
2146
|
+
return (source, from = 0) => {
|
|
2147
|
+
if (from === 0) {
|
|
2148
|
+
end = 0;
|
|
2149
|
+
newline = false;
|
|
2150
|
+
cr = false;
|
|
2151
|
+
}
|
|
2152
|
+
for (let i = from; i < source.length; i++) {
|
|
2153
|
+
const c = source[i];
|
|
2154
|
+
if (c === "\n") {
|
|
2155
|
+
if (newline) {
|
|
2156
|
+
end = i + 1;
|
|
2157
|
+
newline = false;
|
|
2158
|
+
} else newline = true;
|
|
2159
|
+
cr = false;
|
|
2160
|
+
} else if (newline) {
|
|
2161
|
+
if ((c === " " || c === " ") && !cr) continue;
|
|
2162
|
+
if (c === "\r" && !cr) cr = true;
|
|
2163
|
+
else {
|
|
2164
|
+
newline = false;
|
|
2165
|
+
cr = false;
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
}
|
|
2169
|
+
return end;
|
|
2170
|
+
};
|
|
2171
|
+
}
|
|
2172
|
+
|
|
2141
2173
|
// src/components/collectDefLabels.ts
|
|
2142
2174
|
var SCANNER_BOUNDARY_PROFILE = { defListEnabled: false, mathFlow: false, referenceTaint: false };
|
|
2143
2175
|
function buildProcessor() {
|
|
@@ -2169,19 +2201,12 @@ var setsEqual = (a, b) => {
|
|
|
2169
2201
|
for (const v of a) if (!b.has(v)) return false;
|
|
2170
2202
|
return true;
|
|
2171
2203
|
};
|
|
2172
|
-
var BLANK_LINE_RE = /\r?\n[ \t]*\r?\n/g;
|
|
2173
|
-
function lastRegionStart(source) {
|
|
2174
|
-
BLANK_LINE_RE.lastIndex = 0;
|
|
2175
|
-
let start = 0;
|
|
2176
|
-
for (let m = BLANK_LINE_RE.exec(source); m !== null; m = BLANK_LINE_RE.exec(source)) {
|
|
2177
|
-
start = m.index + m[0].length;
|
|
2178
|
-
}
|
|
2179
|
-
return start;
|
|
2180
|
-
}
|
|
2181
2204
|
var DEF_LINE_START_RE = /^[ \t>*+\d.)-]*\[(?:[^\]\\]|\\[\s\S])*\]:/m;
|
|
2182
2205
|
function createDefLabelScanner(parse = collectDefLabels) {
|
|
2183
2206
|
let prevSource = null;
|
|
2184
2207
|
let prevLabels = null;
|
|
2208
|
+
const scanBlankLines = createBlankLineScanner();
|
|
2209
|
+
let regionStart = 0;
|
|
2185
2210
|
let frozenEnd = 0;
|
|
2186
2211
|
let frozenFootnotes = /* @__PURE__ */ new Set();
|
|
2187
2212
|
let frozenLinks = /* @__PURE__ */ new Set();
|
|
@@ -2194,13 +2219,16 @@ function createDefLabelScanner(parse = collectDefLabels) {
|
|
|
2194
2219
|
};
|
|
2195
2220
|
return {
|
|
2196
2221
|
scan(source) {
|
|
2222
|
+
if (source === prevSource && prevLabels !== null) return prevLabels;
|
|
2223
|
+
const previousRegionStart = regionStart;
|
|
2224
|
+
const appended = prevSource !== null && source.startsWith(prevSource);
|
|
2225
|
+
regionStart = scanBlankLines(source, appended ? prevSource.length : 0);
|
|
2197
2226
|
let isAppend = false;
|
|
2198
2227
|
if (prevSource !== null && prevLabels !== null) {
|
|
2199
2228
|
if (source === prevSource) return prevLabels;
|
|
2200
2229
|
if (source.startsWith(prevSource)) {
|
|
2201
2230
|
isAppend = true;
|
|
2202
|
-
const
|
|
2203
|
-
const region = prevSource.slice(regionStart) + source.slice(prevSource.length);
|
|
2231
|
+
const region = source.slice(previousRegionStart);
|
|
2204
2232
|
if (!DEF_LINE_START_RE.test(region)) {
|
|
2205
2233
|
prevSource = source;
|
|
2206
2234
|
return prevLabels;
|
|
@@ -2433,8 +2461,47 @@ function* extractContributions(mdast, options = {}) {
|
|
|
2433
2461
|
for (const c of out) yield c;
|
|
2434
2462
|
}
|
|
2435
2463
|
|
|
2464
|
+
// src/components/registryIndex.ts
|
|
2465
|
+
function buildRegistryIndex(registry) {
|
|
2466
|
+
const index = {
|
|
2467
|
+
footnotes: /* @__PURE__ */ new Map(),
|
|
2468
|
+
links: /* @__PURE__ */ new Map(),
|
|
2469
|
+
numbers: /* @__PURE__ */ new Map(),
|
|
2470
|
+
counts: /* @__PURE__ */ new Map(),
|
|
2471
|
+
occurrences: /* @__PURE__ */ new Map()
|
|
2472
|
+
};
|
|
2473
|
+
for (const sym of registry.chunkOrder) {
|
|
2474
|
+
const data = registry.chunkData.get(sym);
|
|
2475
|
+
if (!data) continue;
|
|
2476
|
+
for (const label of data.defs.keys()) if (!index.footnotes.has(label)) index.footnotes.set(label, sym);
|
|
2477
|
+
for (const label of data.linkDefs.keys()) if (!index.links.has(label)) index.links.set(label, sym);
|
|
2478
|
+
const local = /* @__PURE__ */ new Map();
|
|
2479
|
+
index.occurrences.set(sym, local);
|
|
2480
|
+
for (const ref of data.refs) {
|
|
2481
|
+
if (ref.kind !== "footnote") continue;
|
|
2482
|
+
const label = ref.label;
|
|
2483
|
+
if (!index.numbers.has(label)) index.numbers.set(label, index.numbers.size + 1);
|
|
2484
|
+
const total = (index.counts.get(label) ?? 0) + 1;
|
|
2485
|
+
index.counts.set(label, total);
|
|
2486
|
+
const prior = local.get(label);
|
|
2487
|
+
if (prior) prior.count++;
|
|
2488
|
+
else local.set(label, { start: total, count: 1 });
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2491
|
+
return index;
|
|
2492
|
+
}
|
|
2493
|
+
|
|
2436
2494
|
// src/components/documentRegistry.ts
|
|
2437
2495
|
function createRegistry(onEmpty) {
|
|
2496
|
+
let index;
|
|
2497
|
+
let indexedVersion = -1;
|
|
2498
|
+
const getIndex = () => {
|
|
2499
|
+
if (!index || indexedVersion !== reg.version) {
|
|
2500
|
+
index = buildRegistryIndex(reg);
|
|
2501
|
+
indexedVersion = reg.version;
|
|
2502
|
+
}
|
|
2503
|
+
return index;
|
|
2504
|
+
};
|
|
2438
2505
|
const reg = {
|
|
2439
2506
|
chunkOrder: [],
|
|
2440
2507
|
chunkData: /* @__PURE__ */ new Map(),
|
|
@@ -2586,72 +2653,25 @@ function createRegistry(onEmpty) {
|
|
|
2586
2653
|
};
|
|
2587
2654
|
},
|
|
2588
2655
|
canonicalFootnoteFor(label) {
|
|
2589
|
-
|
|
2590
|
-
for (const sym of this.chunkOrder) {
|
|
2591
|
-
const data = this.chunkData.get(sym);
|
|
2592
|
-
if (data?.defs.has(id)) return sym;
|
|
2593
|
-
}
|
|
2594
|
-
return null;
|
|
2656
|
+
return getIndex().footnotes.get(normalizeId(label)) ?? null;
|
|
2595
2657
|
},
|
|
2596
2658
|
canonicalLinkFor(label) {
|
|
2597
|
-
|
|
2598
|
-
for (const sym of this.chunkOrder) {
|
|
2599
|
-
const data = this.chunkData.get(sym);
|
|
2600
|
-
if (data?.linkDefs.has(id)) return sym;
|
|
2601
|
-
}
|
|
2602
|
-
return null;
|
|
2659
|
+
return getIndex().links.get(normalizeId(label)) ?? null;
|
|
2603
2660
|
},
|
|
2604
2661
|
globalNumber(label) {
|
|
2605
|
-
|
|
2606
|
-
let n = 0;
|
|
2607
|
-
const seen = /* @__PURE__ */ new Set();
|
|
2608
|
-
for (const sym of this.chunkOrder) {
|
|
2609
|
-
const data = this.chunkData.get(sym);
|
|
2610
|
-
if (!data) continue;
|
|
2611
|
-
for (const ref of data.refs) {
|
|
2612
|
-
if (ref.kind !== "footnote") continue;
|
|
2613
|
-
if (!seen.has(ref.label)) {
|
|
2614
|
-
seen.add(ref.label);
|
|
2615
|
-
n++;
|
|
2616
|
-
if (ref.label === id) return n;
|
|
2617
|
-
}
|
|
2618
|
-
}
|
|
2619
|
-
}
|
|
2620
|
-
return null;
|
|
2662
|
+
return getIndex().numbers.get(normalizeId(label)) ?? null;
|
|
2621
2663
|
},
|
|
2622
2664
|
resolveLinkDef(label) {
|
|
2623
|
-
const
|
|
2624
|
-
|
|
2625
|
-
return this.chunkData.get(sym)?.linkDefs.get(
|
|
2665
|
+
const id = normalizeId(label);
|
|
2666
|
+
const sym = getIndex().links.get(id);
|
|
2667
|
+
return sym ? this.chunkData.get(sym)?.linkDefs.get(id) ?? null : null;
|
|
2626
2668
|
},
|
|
2627
2669
|
getRefsForLabel(label) {
|
|
2628
|
-
|
|
2629
|
-
let n = 0;
|
|
2630
|
-
for (const sym of this.chunkOrder) {
|
|
2631
|
-
const data = this.chunkData.get(sym);
|
|
2632
|
-
if (!data) continue;
|
|
2633
|
-
for (const ref of data.refs) {
|
|
2634
|
-
if (ref.kind === "footnote" && ref.label === id) n++;
|
|
2635
|
-
}
|
|
2636
|
-
}
|
|
2637
|
-
return n;
|
|
2670
|
+
return getIndex().counts.get(normalizeId(label)) ?? 0;
|
|
2638
2671
|
},
|
|
2639
2672
|
globalOccurrenceForRef(chunkSym, label, localOccurrence) {
|
|
2640
|
-
const
|
|
2641
|
-
|
|
2642
|
-
for (const sym of this.chunkOrder) {
|
|
2643
|
-
const data = this.chunkData.get(sym);
|
|
2644
|
-
if (!data) continue;
|
|
2645
|
-
let localCount = 0;
|
|
2646
|
-
for (const ref of data.refs) {
|
|
2647
|
-
if (ref.kind !== "footnote") continue;
|
|
2648
|
-
if (ref.label !== id) continue;
|
|
2649
|
-
localCount++;
|
|
2650
|
-
global2++;
|
|
2651
|
-
if (sym === chunkSym && localCount === localOccurrence) return global2;
|
|
2652
|
-
}
|
|
2653
|
-
}
|
|
2654
|
-
return null;
|
|
2673
|
+
const range = getIndex().occurrences.get(chunkSym)?.get(normalizeId(label));
|
|
2674
|
+
return range && Number.isInteger(localOccurrence) && localOccurrence > 0 && localOccurrence <= range.count ? range.start + localOccurrence - 1 : null;
|
|
2655
2675
|
},
|
|
2656
2676
|
_notify() {
|
|
2657
2677
|
this.version++;
|
|
@@ -2708,6 +2728,55 @@ function rehypeUnwrapCrossChunkImages() {
|
|
|
2708
2728
|
|
|
2709
2729
|
// src/components/pluginChain.ts
|
|
2710
2730
|
import rehypeSanitize from "rehype-sanitize";
|
|
2731
|
+
|
|
2732
|
+
// src/components/rehypeVerifyEngineTags.ts
|
|
2733
|
+
var ENGINE_PLACEHOLDER_TAGS = /* @__PURE__ */ new Set([
|
|
2734
|
+
"footnote-sup",
|
|
2735
|
+
"cross-chunk-link",
|
|
2736
|
+
"cross-chunk-image"
|
|
2737
|
+
]);
|
|
2738
|
+
var ENGINE_PROVENANCE_PROPERTY = "engineProvenance";
|
|
2739
|
+
function walk(parent, provenance, ancestors) {
|
|
2740
|
+
const children = parent.children;
|
|
2741
|
+
let i = 0;
|
|
2742
|
+
while (i < children.length) {
|
|
2743
|
+
const node = children[i];
|
|
2744
|
+
if (node.type === "element" && ENGINE_PLACEHOLDER_TAGS.has(node.tagName)) {
|
|
2745
|
+
const props = node.properties ?? {};
|
|
2746
|
+
const stamped = props[ENGINE_PROVENANCE_PROPERTY];
|
|
2747
|
+
const genuine = provenance !== "" && typeof stamped === "string" && stamped === provenance;
|
|
2748
|
+
if (genuine) {
|
|
2749
|
+
delete props[ENGINE_PROVENANCE_PROPERTY];
|
|
2750
|
+
if (ancestors && (node.tagName === "cross-chunk-link" || node.tagName === "cross-chunk-image")) {
|
|
2751
|
+
(node.data ??= {}).referenceAncestors = ancestors.slice();
|
|
2752
|
+
}
|
|
2753
|
+
ancestors?.push(
|
|
2754
|
+
node.tagName === "cross-chunk-link" ? "a" : node.tagName === "cross-chunk-image" ? "img" : node.tagName
|
|
2755
|
+
);
|
|
2756
|
+
walk(node, provenance, ancestors);
|
|
2757
|
+
ancestors?.pop();
|
|
2758
|
+
i += 1;
|
|
2759
|
+
} else {
|
|
2760
|
+
children.splice(i, 1, ...node.children);
|
|
2761
|
+
}
|
|
2762
|
+
continue;
|
|
2763
|
+
}
|
|
2764
|
+
if (node.type === "element") {
|
|
2765
|
+
ancestors?.push(node.tagName);
|
|
2766
|
+
walk(node, provenance, ancestors);
|
|
2767
|
+
ancestors?.pop();
|
|
2768
|
+
}
|
|
2769
|
+
i += 1;
|
|
2770
|
+
}
|
|
2771
|
+
}
|
|
2772
|
+
function rehypeVerifyEngineTags(options) {
|
|
2773
|
+
const provenance = options?.provenance ?? "";
|
|
2774
|
+
return function transformer(tree) {
|
|
2775
|
+
walk(tree, provenance, options?.referenceAncestors ? [] : void 0);
|
|
2776
|
+
};
|
|
2777
|
+
}
|
|
2778
|
+
|
|
2779
|
+
// src/components/pluginChain.ts
|
|
2711
2780
|
import remarkBreaks from "remark-breaks";
|
|
2712
2781
|
import remarkCjkFriendly from "remark-cjk-friendly";
|
|
2713
2782
|
import remarkCjkFriendlyGfmStrikethrough from "remark-cjk-friendly-gfm-strikethrough";
|
|
@@ -2724,16 +2793,18 @@ import remarkRemoveComments from "remark-remove-comments";
|
|
|
2724
2793
|
// src/components/rehypeRebaseHashLinks.ts
|
|
2725
2794
|
import { visit as visit5 } from "unist-util-visit";
|
|
2726
2795
|
var DEFAULT_PREFIX = "user-content-";
|
|
2796
|
+
function rebaseHashHref(href, prefix) {
|
|
2797
|
+
const hashPrefix = "#" + prefix;
|
|
2798
|
+
return href.startsWith("#") && !href.startsWith(hashPrefix) ? hashPrefix + href.slice(1) : href;
|
|
2799
|
+
}
|
|
2727
2800
|
var rehypeRebaseHashLinks = (options) => {
|
|
2728
2801
|
const prefix = options?.prefix ?? DEFAULT_PREFIX;
|
|
2729
|
-
const hashPrefix = "#" + prefix;
|
|
2730
2802
|
return (tree) => {
|
|
2731
2803
|
visit5(tree, "element", (node) => {
|
|
2732
2804
|
if (node.tagName !== "a") return;
|
|
2733
2805
|
const href = node.properties?.href;
|
|
2734
2806
|
if (typeof href !== "string" || !href.startsWith("#")) return;
|
|
2735
|
-
|
|
2736
|
-
node.properties.href = hashPrefix + href.slice(1);
|
|
2807
|
+
node.properties.href = rebaseHashHref(href, prefix);
|
|
2737
2808
|
});
|
|
2738
2809
|
};
|
|
2739
2810
|
};
|
|
@@ -2813,10 +2884,21 @@ function buildCoreRemarkPlugins(enginePlugins) {
|
|
|
2813
2884
|
...DISPLAY_OPTIMIZE_CHAIN.filter(([name]) => selected.has(name)).map(([, plugin]) => plugin)
|
|
2814
2885
|
];
|
|
2815
2886
|
}
|
|
2816
|
-
function buildCoreRehypePlugins(sanitizeSchema2, clobberPrefix) {
|
|
2887
|
+
function buildCoreRehypePlugins(sanitizeSchema2, clobberPrefix, options) {
|
|
2817
2888
|
return [
|
|
2818
2889
|
// Allow raw HTML through so rehype-sanitize can handle it.
|
|
2819
2890
|
[rehypeRaw, { passThrough: [] }],
|
|
2891
|
+
// Unwrap forged engine placeholders BEFORE sanitize admits their tag
|
|
2892
|
+
// names. Only when the caller holds a credential (see the option's doc).
|
|
2893
|
+
...options ? [
|
|
2894
|
+
[
|
|
2895
|
+
rehypeVerifyEngineTags,
|
|
2896
|
+
{
|
|
2897
|
+
provenance: options.provenance,
|
|
2898
|
+
...sanitizeSchema2.ancestors?.a || sanitizeSchema2.ancestors?.img ? { referenceAncestors: true } : {}
|
|
2899
|
+
}
|
|
2900
|
+
]
|
|
2901
|
+
] : [],
|
|
2820
2902
|
// Sanitize HTML while allowing <mark> (highlight), KaTeX class names,
|
|
2821
2903
|
// and any extra protocols the caller permitted via the `sanitizeSchema`
|
|
2822
2904
|
// prop. Override `clobberPrefix` with the instance-scoped value — the
|
|
@@ -2856,6 +2938,10 @@ function buildCoreRemarkRehypeOptions(enableDefinitionList) {
|
|
|
2856
2938
|
}
|
|
2857
2939
|
|
|
2858
2940
|
// src/components/customMdastHandlers.ts
|
|
2941
|
+
function provenanceProps(s) {
|
|
2942
|
+
const provenance = s.options.provenance;
|
|
2943
|
+
return typeof provenance === "string" ? { engineProvenance: provenance } : {};
|
|
2944
|
+
}
|
|
2859
2945
|
function localDefProps(s, id) {
|
|
2860
2946
|
const def = s.definitionById.get(id);
|
|
2861
2947
|
if (!def || typeof def.url !== "string" || def.url === SENTINEL_LINK_URL) return {};
|
|
@@ -2886,15 +2972,14 @@ function buildCrossChunkHandlers() {
|
|
|
2886
2972
|
type: "element",
|
|
2887
2973
|
tagName: "cross-chunk-link",
|
|
2888
2974
|
properties: {
|
|
2889
|
-
//
|
|
2890
|
-
//
|
|
2891
|
-
|
|
2892
|
-
// which also preserves source case. Registry lookups normalize
|
|
2893
|
-
// internally, so cross-chunk case-insensitive matching still works.
|
|
2975
|
+
// Display labels decode escapes; registry identifiers must retain
|
|
2976
|
+
// those bytes. Never use the display label as the lookup key.
|
|
2977
|
+
identifier: node.identifier,
|
|
2894
2978
|
label: node.label ?? node.identifier,
|
|
2895
2979
|
referenceType: node.referenceType,
|
|
2896
2980
|
documentId: s.options.documentId,
|
|
2897
|
-
...localDefProps(s, id)
|
|
2981
|
+
...localDefProps(s, id),
|
|
2982
|
+
...provenanceProps(s)
|
|
2898
2983
|
},
|
|
2899
2984
|
children: s.all(node)
|
|
2900
2985
|
};
|
|
@@ -2908,11 +2993,13 @@ function buildCrossChunkHandlers() {
|
|
|
2908
2993
|
type: "element",
|
|
2909
2994
|
tagName: "cross-chunk-image",
|
|
2910
2995
|
properties: {
|
|
2996
|
+
identifier: node.identifier,
|
|
2911
2997
|
label: node.label ?? node.identifier,
|
|
2912
2998
|
referenceType: node.referenceType,
|
|
2913
2999
|
alt: node.alt ?? "",
|
|
2914
3000
|
documentId: s.options.documentId,
|
|
2915
|
-
...localDefProps(s, id)
|
|
3001
|
+
...localDefProps(s, id),
|
|
3002
|
+
...provenanceProps(s)
|
|
2916
3003
|
},
|
|
2917
3004
|
children: []
|
|
2918
3005
|
};
|
|
@@ -2929,7 +3016,8 @@ function buildCrossChunkHandlers() {
|
|
|
2929
3016
|
properties: {
|
|
2930
3017
|
label: node.identifier,
|
|
2931
3018
|
localOccurrence,
|
|
2932
|
-
documentId: s.options.documentId
|
|
3019
|
+
documentId: s.options.documentId,
|
|
3020
|
+
...provenanceProps(s)
|
|
2933
3021
|
},
|
|
2934
3022
|
children: []
|
|
2935
3023
|
};
|
|
@@ -2947,7 +3035,8 @@ function buildCrossChunkHandlers() {
|
|
|
2947
3035
|
// first client frame), where the local synthetic footer is what
|
|
2948
3036
|
// renders, so marks and footer agree (core-render-02).
|
|
2949
3037
|
localNumber: s.footnoteOrder.indexOf(id) + 1,
|
|
2950
|
-
documentId: s.options.documentId
|
|
3038
|
+
documentId: s.options.documentId,
|
|
3039
|
+
...provenanceProps(s)
|
|
2951
3040
|
},
|
|
2952
3041
|
children: []
|
|
2953
3042
|
};
|
|
@@ -4167,8 +4256,8 @@ var sanitizeSchema = deepFreeze(
|
|
|
4167
4256
|
attributes: {
|
|
4168
4257
|
...defaultSchema.attributes,
|
|
4169
4258
|
code: mergeClassNameAllowlist(defaultSchema.attributes?.code, ["math-inline", "math-display"]),
|
|
4170
|
-
"cross-chunk-link": ["label", "referenceType", "documentId", "localUrl", "localTitle"],
|
|
4171
|
-
"cross-chunk-image": ["label", "referenceType", "documentId", "alt", "localUrl", "localTitle"],
|
|
4259
|
+
"cross-chunk-link": ["identifier", "label", "referenceType", "documentId", "localUrl", "localTitle"],
|
|
4260
|
+
"cross-chunk-image": ["identifier", "label", "referenceType", "documentId", "alt", "localUrl", "localTitle"],
|
|
4172
4261
|
"footnote-sup": ["label", "localOccurrence", "localNumber", "documentId"]
|
|
4173
4262
|
},
|
|
4174
4263
|
strip: [.../* @__PURE__ */ new Set([...defaultSchema.strip || [], ...STRIPPED_TAGS])]
|
|
@@ -4204,6 +4293,49 @@ function sanitizeCrossChunkUrl(rawUrl, key, tagName, urlTransform, schema) {
|
|
|
4204
4293
|
return String(transformed);
|
|
4205
4294
|
}
|
|
4206
4295
|
|
|
4296
|
+
// src/components/resolveCrossChunkReference.ts
|
|
4297
|
+
import rehypeSanitize2 from "rehype-sanitize";
|
|
4298
|
+
import { normalizeUri as normalizeUri3 } from "micromark-util-sanitize-uri";
|
|
4299
|
+
function resolveCrossChunkReference(input, schema, urlTransform, clobberPrefix) {
|
|
4300
|
+
const key = input.tagName === "a" ? "href" : "src";
|
|
4301
|
+
const element = {
|
|
4302
|
+
type: "element",
|
|
4303
|
+
tagName: input.tagName,
|
|
4304
|
+
properties: {
|
|
4305
|
+
[key]: normalizeUri3(input.url),
|
|
4306
|
+
...input.tagName === "img" ? { alt: input.alt ?? "" } : {},
|
|
4307
|
+
...input.title !== void 0 ? { title: input.title } : {}
|
|
4308
|
+
},
|
|
4309
|
+
children: input.tagName === "a" ? [{ type: "text", value: "__reference_children__" }] : []
|
|
4310
|
+
};
|
|
4311
|
+
const requiredAncestors = schema.ancestors?.[input.tagName];
|
|
4312
|
+
const recordedAncestors = input.node?.data?.referenceAncestors;
|
|
4313
|
+
let finalSchema = schema;
|
|
4314
|
+
if (requiredAncestors && Array.isArray(recordedAncestors) && requiredAncestors.some((tag) => recordedAncestors.includes(tag))) {
|
|
4315
|
+
const ancestors = { ...schema.ancestors };
|
|
4316
|
+
delete ancestors[input.tagName];
|
|
4317
|
+
finalSchema = { ...schema, ancestors };
|
|
4318
|
+
}
|
|
4319
|
+
const root2 = rehypeSanitize2({ ...finalSchema, clobberPrefix })({ type: "root", children: [element] });
|
|
4320
|
+
const node = root2.children[0];
|
|
4321
|
+
if (node?.type !== "element") return { element: null, keepChildren: node?.type === "text" };
|
|
4322
|
+
if (node.tagName === "a" && typeof node.properties.href === "string") {
|
|
4323
|
+
node.properties.href = rebaseHashHref(node.properties.href, clobberPrefix);
|
|
4324
|
+
}
|
|
4325
|
+
node.children = input.node?.children ?? [];
|
|
4326
|
+
if (input.node?.position) node.position = input.node.position;
|
|
4327
|
+
buildTransform({
|
|
4328
|
+
allowedElements: void 0,
|
|
4329
|
+
disallowedElements: void 0,
|
|
4330
|
+
allowElement: void 0,
|
|
4331
|
+
skipHtml: void 0,
|
|
4332
|
+
unwrapDisallowed: void 0,
|
|
4333
|
+
urlTransform
|
|
4334
|
+
})(node, 0, root2);
|
|
4335
|
+
node.children = [];
|
|
4336
|
+
return { element: node, keepChildren: false };
|
|
4337
|
+
}
|
|
4338
|
+
|
|
4207
4339
|
// src/plugins/defs.ts
|
|
4208
4340
|
function getEnginePluginInternals(plugin) {
|
|
4209
4341
|
const candidate = plugin;
|
|
@@ -4420,6 +4552,8 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4420
4552
|
let source = "";
|
|
4421
4553
|
let visibleEnd = 0;
|
|
4422
4554
|
let pending = [];
|
|
4555
|
+
let pendingHead = 0;
|
|
4556
|
+
const pendingCount = () => pending.length - pendingHead;
|
|
4423
4557
|
let tentativeEnd = 0;
|
|
4424
4558
|
let finished = false;
|
|
4425
4559
|
let seam;
|
|
@@ -4464,7 +4598,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4464
4598
|
cancelFrame = void 0;
|
|
4465
4599
|
};
|
|
4466
4600
|
const ensureScheduled = () => {
|
|
4467
|
-
if (disposed || cancelFrame ||
|
|
4601
|
+
if (disposed || cancelFrame || pendingCount() === 0) return;
|
|
4468
4602
|
lastTickAt = now();
|
|
4469
4603
|
credit = 0;
|
|
4470
4604
|
cancelFrame = schedule(tick);
|
|
@@ -4478,31 +4612,38 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4478
4612
|
const params = resolveParams();
|
|
4479
4613
|
let rate;
|
|
4480
4614
|
if (finished && drainDeadlineAt !== void 0) {
|
|
4481
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4615
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, drainDeadlineAt - t));
|
|
4482
4616
|
} else if (gapWindow.length > 0 && lastArrivalAt !== void 0) {
|
|
4483
4617
|
const gaps = gapWindow.map((s) => s.gap).sort((a, b) => a - b);
|
|
4484
4618
|
const intervalQ = gaps[Math.min(gaps.length - 1, Math.floor(gaps.length * INTERVAL_QUANTILE))];
|
|
4485
4619
|
const horizon = Math.max(16, Math.min(params.bufferFactor * intervalQ + HORIZON_PAD_MS, params.maxLagMs));
|
|
4486
4620
|
const deadline = Math.max(lastArrivalAt + horizon, t + DEADLINE_FLOOR_MS);
|
|
4487
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4621
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, deadline - t));
|
|
4488
4622
|
} else {
|
|
4489
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4623
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, params.correctionTauMs));
|
|
4490
4624
|
}
|
|
4491
4625
|
credit += rate * dt / 1e3;
|
|
4492
|
-
const reveal = Math.min(Math.floor(credit),
|
|
4626
|
+
const reveal = Math.min(Math.floor(credit), pendingCount());
|
|
4493
4627
|
if (reveal > 0) {
|
|
4494
|
-
visibleEnd = pending[reveal - 1];
|
|
4495
|
-
|
|
4496
|
-
|
|
4628
|
+
visibleEnd = pending[pendingHead + reveal - 1];
|
|
4629
|
+
pendingHead += reveal;
|
|
4630
|
+
if (pendingHead === pending.length) {
|
|
4631
|
+
pending = [];
|
|
4632
|
+
pendingHead = 0;
|
|
4633
|
+
} else if (pendingHead >= 1024 && pendingHead * 2 >= pending.length) {
|
|
4634
|
+
pending = pending.slice(pendingHead);
|
|
4635
|
+
pendingHead = 0;
|
|
4636
|
+
}
|
|
4637
|
+
credit = pendingCount() > 0 ? credit - reveal : 0;
|
|
4497
4638
|
notify();
|
|
4498
4639
|
}
|
|
4499
|
-
if (!disposed && !cancelFrame &&
|
|
4640
|
+
if (!disposed && !cancelFrame && pendingCount() > 0) cancelFrame = schedule(tick);
|
|
4500
4641
|
};
|
|
4501
4642
|
const resegmentTail = () => {
|
|
4502
|
-
if (seam !== void 0 && seam < source.length && pending[pending.length - 1] === seam) {
|
|
4643
|
+
if (pendingCount() > 0 && seam !== void 0 && seam < source.length && pending[pending.length - 1] === seam) {
|
|
4503
4644
|
pending.pop();
|
|
4504
4645
|
}
|
|
4505
|
-
const from =
|
|
4646
|
+
const from = pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd;
|
|
4506
4647
|
let anchor = from;
|
|
4507
4648
|
if (seam !== void 0 && from <= seam) {
|
|
4508
4649
|
anchor = Math.max(0, from - RESUME_LOOKBACK);
|
|
@@ -4536,6 +4677,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4536
4677
|
visibleEnd = next.length;
|
|
4537
4678
|
tentativeEnd = next.length;
|
|
4538
4679
|
pending = [];
|
|
4680
|
+
pendingHead = 0;
|
|
4539
4681
|
seam = next.length;
|
|
4540
4682
|
credit = 0;
|
|
4541
4683
|
cancelScheduled();
|
|
@@ -4567,7 +4709,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4567
4709
|
if (finished) return;
|
|
4568
4710
|
finished = true;
|
|
4569
4711
|
lastArrivalAt = void 0;
|
|
4570
|
-
if (tentativeEnd > (
|
|
4712
|
+
if (tentativeEnd > (pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd)) {
|
|
4571
4713
|
pending.push(tentativeEnd);
|
|
4572
4714
|
}
|
|
4573
4715
|
const params = resolveParams();
|
|
@@ -4593,10 +4735,11 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4593
4735
|
snap,
|
|
4594
4736
|
flush() {
|
|
4595
4737
|
disposed = false;
|
|
4596
|
-
const target = finished ? source.length :
|
|
4738
|
+
const target = finished ? source.length : pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd;
|
|
4597
4739
|
if (target <= visibleEnd) return;
|
|
4598
4740
|
visibleEnd = target;
|
|
4599
4741
|
pending = [];
|
|
4742
|
+
pendingHead = 0;
|
|
4600
4743
|
credit = 0;
|
|
4601
4744
|
cancelScheduled();
|
|
4602
4745
|
notify();
|
|
@@ -4619,6 +4762,12 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4619
4762
|
};
|
|
4620
4763
|
|
|
4621
4764
|
// src/preprocessors/latex.ts
|
|
4765
|
+
function isHardBoundary(kind) {
|
|
4766
|
+
return kind === "code" || kind === "literal" || kind === "multilineTag";
|
|
4767
|
+
}
|
|
4768
|
+
function hasLineEnding(text) {
|
|
4769
|
+
return text.includes("\n") || text.includes("\r");
|
|
4770
|
+
}
|
|
4622
4771
|
function getRepeatedMarkerLength(content, start, marker) {
|
|
4623
4772
|
let end = start;
|
|
4624
4773
|
while (end < content.length && content[end] === marker) {
|
|
@@ -4686,11 +4835,11 @@ function splitByProtectedRegions(content) {
|
|
|
4686
4835
|
let multilineFenceMarker = null;
|
|
4687
4836
|
let multilineFenceLength = 0;
|
|
4688
4837
|
let multilineFenceIndent = 0;
|
|
4689
|
-
function pushProtected(start, end) {
|
|
4838
|
+
function pushProtected(start, end, kind) {
|
|
4690
4839
|
if (start > lastIndex) {
|
|
4691
|
-
segments.push({ text: content.substring(lastIndex, start)
|
|
4840
|
+
segments.push({ kind: "text", text: content.substring(lastIndex, start) });
|
|
4692
4841
|
}
|
|
4693
|
-
segments.push({ text: content.substring(start, end)
|
|
4842
|
+
segments.push({ kind, text: content.substring(start, end) });
|
|
4694
4843
|
lastIndex = end;
|
|
4695
4844
|
}
|
|
4696
4845
|
let i = 0;
|
|
@@ -4701,7 +4850,7 @@ function splitByProtectedRegions(content) {
|
|
|
4701
4850
|
const runLen = getRepeatedMarkerLength(content, i, multilineFenceMarker);
|
|
4702
4851
|
const closerIndent = lineIndentBefore(content, i);
|
|
4703
4852
|
if (runLen >= multilineFenceLength && closerIndent !== -1 && closerIndent <= multilineFenceIndent + 3 && restOfLineIsBlank(content, i + runLen)) {
|
|
4704
|
-
pushProtected(multilineStart, i + runLen);
|
|
4853
|
+
pushProtected(multilineStart, i + runLen, "code");
|
|
4705
4854
|
multilineStart = -1;
|
|
4706
4855
|
multilineFenceMarker = null;
|
|
4707
4856
|
multilineFenceLength = 0;
|
|
@@ -4728,7 +4877,7 @@ function splitByProtectedRegions(content) {
|
|
|
4728
4877
|
if (char === "`") {
|
|
4729
4878
|
const closeIdx = findClosingBacktickRun(content, i + runLen, runLen);
|
|
4730
4879
|
if (closeIdx !== -1) {
|
|
4731
|
-
pushProtected(i, closeIdx + runLen);
|
|
4880
|
+
pushProtected(i, closeIdx + runLen, "code");
|
|
4732
4881
|
i = closeIdx + runLen;
|
|
4733
4882
|
continue;
|
|
4734
4883
|
}
|
|
@@ -4753,7 +4902,11 @@ function splitByProtectedRegions(content) {
|
|
|
4753
4902
|
endIndex = content.length;
|
|
4754
4903
|
}
|
|
4755
4904
|
}
|
|
4756
|
-
pushProtected(
|
|
4905
|
+
pushProtected(
|
|
4906
|
+
i,
|
|
4907
|
+
endIndex,
|
|
4908
|
+
isOpeningPairedTag ? "literal" : hasLineEnding(content.substring(i, endIndex)) ? "multilineTag" : "tag"
|
|
4909
|
+
);
|
|
4757
4910
|
i = endIndex;
|
|
4758
4911
|
continue;
|
|
4759
4912
|
}
|
|
@@ -4761,10 +4914,10 @@ function splitByProtectedRegions(content) {
|
|
|
4761
4914
|
i += 1;
|
|
4762
4915
|
}
|
|
4763
4916
|
if (multilineStart !== -1) {
|
|
4764
|
-
pushProtected(multilineStart, content.length);
|
|
4917
|
+
pushProtected(multilineStart, content.length, "code");
|
|
4765
4918
|
}
|
|
4766
4919
|
if (lastIndex < content.length) {
|
|
4767
|
-
segments.push({ text: content.substring(lastIndex)
|
|
4920
|
+
segments.push({ kind: "text", text: content.substring(lastIndex) });
|
|
4768
4921
|
}
|
|
4769
4922
|
return segments;
|
|
4770
4923
|
}
|
|
@@ -4918,20 +5071,22 @@ function escapeLatexPipesInUnclosed(text) {
|
|
|
4918
5071
|
const tail = text.substring(unclosedStart + delimLen);
|
|
4919
5072
|
return before + delim + replaceUnescapedPipes(tail);
|
|
4920
5073
|
}
|
|
4921
|
-
function opensMathFlow(text, pos) {
|
|
5074
|
+
function opensMathFlow(text, pos, runStartsAtLineStart) {
|
|
4922
5075
|
let i = pos;
|
|
4923
5076
|
let spaces = 0;
|
|
4924
|
-
while (i > 0
|
|
5077
|
+
while (i > 0) {
|
|
5078
|
+
const prev = text[i - 1];
|
|
5079
|
+
if (prev === "\n" || prev === "\r") return true;
|
|
4925
5080
|
i -= 1;
|
|
4926
5081
|
if (text[i] !== " ") return false;
|
|
4927
5082
|
spaces += 1;
|
|
4928
5083
|
if (spaces > 3) return false;
|
|
4929
5084
|
}
|
|
4930
|
-
return
|
|
5085
|
+
return runStartsAtLineStart;
|
|
4931
5086
|
}
|
|
4932
|
-
function truncateUnclosedLatexBlock(text, unclosedStart = findUnclosedDelimiterStart(text, "double-only")) {
|
|
5087
|
+
function truncateUnclosedLatexBlock(text, runStartsAtLineStart, unclosedStart = findUnclosedDelimiterStart(text, "double-only")) {
|
|
4933
5088
|
if (unclosedStart === -1) return text;
|
|
4934
|
-
if (!opensMathFlow(text, unclosedStart)) return text;
|
|
5089
|
+
if (!opensMathFlow(text, unclosedStart, runStartsAtLineStart)) return text;
|
|
4935
5090
|
return text.substring(0, unclosedStart).trimEnd();
|
|
4936
5091
|
}
|
|
4937
5092
|
function escapeTextUnderscores(text) {
|
|
@@ -4976,7 +5131,8 @@ function convertSingleToDoubleDollar(text) {
|
|
|
4976
5131
|
}
|
|
4977
5132
|
function preprocessLaTeX(str) {
|
|
4978
5133
|
if (!hasLatexTrigger(str)) return str;
|
|
4979
|
-
|
|
5134
|
+
const mask = selectMask(str);
|
|
5135
|
+
return (mask === null ? processSlice(str, { legacy: true, probe: false }) : processSlice(str, { probe: false, mask })).out;
|
|
4980
5136
|
}
|
|
4981
5137
|
function hasLatexTrigger(str) {
|
|
4982
5138
|
return str.includes("$") || str.includes("\\[") || str.includes("\\(");
|
|
@@ -5005,42 +5161,240 @@ function hasUnclosedTextCommand(text) {
|
|
|
5005
5161
|
}
|
|
5006
5162
|
var RESIDUAL_OPEN_BRACKET_RE = /(?<!!)\\\[/;
|
|
5007
5163
|
var LEADING_DOUBLE_DOLLAR_RE = /^\s*\$\$/;
|
|
5008
|
-
|
|
5164
|
+
var PUA_START = 57344;
|
|
5165
|
+
var PUA_END = 63743;
|
|
5166
|
+
var PUA_SIZE = PUA_END - PUA_START + 1;
|
|
5167
|
+
function selectMask(source) {
|
|
5168
|
+
const first = String.fromCharCode(PUA_START);
|
|
5169
|
+
if (source.indexOf(first) === -1) return first;
|
|
5170
|
+
const seen = new Uint8Array(PUA_SIZE);
|
|
5171
|
+
for (let i = 0; i < source.length; i++) {
|
|
5172
|
+
const c = source.charCodeAt(i);
|
|
5173
|
+
if (c >= PUA_START && c <= PUA_END) seen[c - PUA_START] = 1;
|
|
5174
|
+
}
|
|
5175
|
+
for (let k = 0; k < PUA_SIZE; k++) if (seen[k] === 0) return String.fromCharCode(PUA_START + k);
|
|
5176
|
+
return null;
|
|
5177
|
+
}
|
|
5178
|
+
var PuaPresence = class {
|
|
5179
|
+
bits = new Uint8Array(PUA_SIZE);
|
|
5180
|
+
distinct = 0;
|
|
5181
|
+
reset() {
|
|
5182
|
+
this.bits.fill(0);
|
|
5183
|
+
this.distinct = 0;
|
|
5184
|
+
}
|
|
5185
|
+
add(text, from) {
|
|
5186
|
+
for (let i = from; i < text.length; i++) {
|
|
5187
|
+
const c = text.charCodeAt(i);
|
|
5188
|
+
if (c >= PUA_START && c <= PUA_END) {
|
|
5189
|
+
const k = c - PUA_START;
|
|
5190
|
+
if (this.bits[k] === 0) {
|
|
5191
|
+
this.bits[k] = 1;
|
|
5192
|
+
this.distinct += 1;
|
|
5193
|
+
}
|
|
5194
|
+
}
|
|
5195
|
+
}
|
|
5196
|
+
}
|
|
5197
|
+
select() {
|
|
5198
|
+
if (this.distinct === 0) return String.fromCharCode(PUA_START);
|
|
5199
|
+
if (this.distinct >= PUA_SIZE) return null;
|
|
5200
|
+
for (let k = 0; k < PUA_SIZE; k++) if (this.bits[k] === 0) return String.fromCharCode(PUA_START + k);
|
|
5201
|
+
return null;
|
|
5202
|
+
}
|
|
5203
|
+
};
|
|
5204
|
+
function transformRun(input, probe, runStartsAtLineStart, seamEligible) {
|
|
5205
|
+
let text = input;
|
|
5206
|
+
let tailSensitive = false;
|
|
5207
|
+
let truncatedAtSeamStart = false;
|
|
5208
|
+
text = escapeMhchemCommands(text);
|
|
5209
|
+
text = escapeCurrencyDollarSigns(text);
|
|
5210
|
+
text = convertLatexDelimiters(text);
|
|
5211
|
+
if (probe && RESIDUAL_OPEN_BRACKET_RE.test(text)) tailSensitive = true;
|
|
5212
|
+
text = escapeLatexPipes(text);
|
|
5213
|
+
if (probe && findUnclosedDelimiterStart(text, "both") !== -1) tailSensitive = true;
|
|
5214
|
+
text = escapeLatexPipesInUnclosed(text);
|
|
5215
|
+
if (probe && hasUnclosedTextCommand(text)) tailSensitive = true;
|
|
5216
|
+
text = escapeTextUnderscores(text);
|
|
5217
|
+
text = convertSingleToDoubleDollar(text);
|
|
5218
|
+
let unclosedDouble;
|
|
5219
|
+
if (probe || seamEligible && LEADING_DOUBLE_DOLLAR_RE.test(text)) {
|
|
5220
|
+
unclosedDouble = findUnclosedDelimiterStart(text, "double-only");
|
|
5221
|
+
if (unclosedDouble !== -1) {
|
|
5222
|
+
tailSensitive = true;
|
|
5223
|
+
if (seamEligible && opensMathFlow(text, unclosedDouble, runStartsAtLineStart) && text.slice(0, unclosedDouble).trim() === "") {
|
|
5224
|
+
truncatedAtSeamStart = true;
|
|
5225
|
+
}
|
|
5226
|
+
}
|
|
5227
|
+
}
|
|
5228
|
+
text = truncateUnclosedLatexBlock(text, runStartsAtLineStart, unclosedDouble);
|
|
5229
|
+
return { out: text, tailSensitive, truncatedAtSeamStart };
|
|
5230
|
+
}
|
|
5231
|
+
function processSliceLegacy(slice, probe) {
|
|
5009
5232
|
const segments = splitByProtectedRegions(slice);
|
|
5010
5233
|
const parts = [];
|
|
5011
5234
|
let quiescent = true;
|
|
5012
5235
|
let truncatedAtSeamStart = false;
|
|
5013
5236
|
for (let index = 0; index < segments.length; index++) {
|
|
5014
5237
|
const segment = segments[index];
|
|
5015
|
-
if (segment.
|
|
5238
|
+
if (segment.kind !== "text") {
|
|
5016
5239
|
parts.push(segment.text);
|
|
5017
5240
|
continue;
|
|
5018
5241
|
}
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
|
|
5242
|
+
const r = transformRun(segment.text, probe, true, index === 0);
|
|
5243
|
+
if (r.tailSensitive) quiescent = false;
|
|
5244
|
+
if (r.truncatedAtSeamStart) truncatedAtSeamStart = true;
|
|
5245
|
+
parts.push(r.out);
|
|
5246
|
+
}
|
|
5247
|
+
return { out: parts.join(""), quiescent, truncatedAtSeamStart, degradedReason: null };
|
|
5248
|
+
}
|
|
5249
|
+
var SCOPE_DEPTH_CAP = 8;
|
|
5250
|
+
var VOID_TAGS2 = /* @__PURE__ */ new Set(["br", "hr", "img", "wbr", "input", "source"]);
|
|
5251
|
+
var TAG_NAME_RE = /^<(\/?)([A-Za-z][A-Za-z0-9]*)/;
|
|
5252
|
+
function tagInfo(tag) {
|
|
5253
|
+
const m = TAG_NAME_RE.exec(tag);
|
|
5254
|
+
const closing = m?.[1] === "/";
|
|
5255
|
+
const name = (m?.[2] ?? "").toLowerCase();
|
|
5256
|
+
const opensScope = !closing && !tag.endsWith("/>") && !VOID_TAGS2.has(name);
|
|
5257
|
+
return { name, closing, opensScope };
|
|
5258
|
+
}
|
|
5259
|
+
function buildRunTree(segments) {
|
|
5260
|
+
const root2 = [];
|
|
5261
|
+
const stack = [];
|
|
5262
|
+
const current = () => stack.length > 0 ? stack[stack.length - 1].children : root2;
|
|
5263
|
+
const unwind = () => {
|
|
5264
|
+
while (stack.length > 0) {
|
|
5265
|
+
const frame = stack.pop();
|
|
5266
|
+
current().push({ type: "atom", text: frame.open }, ...frame.children);
|
|
5267
|
+
}
|
|
5268
|
+
};
|
|
5269
|
+
for (const segment of segments) {
|
|
5270
|
+
if (segment.kind === "tag") {
|
|
5271
|
+
const info = tagInfo(segment.text);
|
|
5272
|
+
if (info.closing) {
|
|
5273
|
+
const top = stack[stack.length - 1];
|
|
5274
|
+
if (top !== void 0 && top.name === info.name) {
|
|
5275
|
+
stack.pop();
|
|
5276
|
+
const parent = current();
|
|
5277
|
+
if (top.suppressed) {
|
|
5278
|
+
parent.push({ type: "atom", text: top.open }, ...top.children, { type: "atom", text: segment.text });
|
|
5279
|
+
} else {
|
|
5280
|
+
parent.push({ type: "scope", open: top.open, close: segment.text, children: top.children });
|
|
5281
|
+
}
|
|
5282
|
+
} else {
|
|
5283
|
+
current().push({ type: "atom", text: segment.text });
|
|
5037
5284
|
}
|
|
5285
|
+
} else if (info.opensScope) {
|
|
5286
|
+
stack.push({ name: info.name, open: segment.text, suppressed: stack.length >= SCOPE_DEPTH_CAP, children: [] });
|
|
5287
|
+
} else {
|
|
5288
|
+
current().push({ type: "atom", text: segment.text });
|
|
5038
5289
|
}
|
|
5290
|
+
continue;
|
|
5291
|
+
}
|
|
5292
|
+
const t = segment.text;
|
|
5293
|
+
let start = 0;
|
|
5294
|
+
for (let i = 0; i < t.length; i++) {
|
|
5295
|
+
const c = t.charCodeAt(i);
|
|
5296
|
+
if (c !== 10 && c !== 13) continue;
|
|
5297
|
+
if (i > start) current().push({ type: "text", text: t.slice(start, i) });
|
|
5298
|
+
const end = c === 13 && t.charCodeAt(i + 1) === 10 ? i + 2 : i + 1;
|
|
5299
|
+
unwind();
|
|
5300
|
+
root2.push({ type: "text", text: t.slice(i, end) });
|
|
5301
|
+
start = end;
|
|
5302
|
+
i = end - 1;
|
|
5303
|
+
}
|
|
5304
|
+
if (start < t.length) current().push({ type: "text", text: t.slice(start) });
|
|
5305
|
+
}
|
|
5306
|
+
unwind();
|
|
5307
|
+
return root2;
|
|
5308
|
+
}
|
|
5309
|
+
var restoreFailureInjector = null;
|
|
5310
|
+
function restore(out, atoms, mask) {
|
|
5311
|
+
if (restoreFailureInjector !== null && restoreFailureInjector(atoms)) return null;
|
|
5312
|
+
let result = "";
|
|
5313
|
+
let k = 0;
|
|
5314
|
+
let last = 0;
|
|
5315
|
+
for (; ; ) {
|
|
5316
|
+
const idx = out.indexOf(mask, last);
|
|
5317
|
+
if (idx === -1) break;
|
|
5318
|
+
if (k >= atoms.length) return null;
|
|
5319
|
+
result += out.slice(last, idx) + atoms[k];
|
|
5320
|
+
k += 1;
|
|
5321
|
+
last = idx + 1;
|
|
5322
|
+
}
|
|
5323
|
+
return result + out.slice(last);
|
|
5324
|
+
}
|
|
5325
|
+
function emitRun(nodes, mask) {
|
|
5326
|
+
let text = "";
|
|
5327
|
+
const atoms = [];
|
|
5328
|
+
for (const node of nodes) {
|
|
5329
|
+
if (node.type === "text") {
|
|
5330
|
+
text += node.text;
|
|
5331
|
+
} else if (node.type === "atom") {
|
|
5332
|
+
atoms.push(node.text);
|
|
5333
|
+
text += mask;
|
|
5334
|
+
} else {
|
|
5335
|
+
const inner = emitRun(node.children, mask);
|
|
5336
|
+
if (inner === null) return null;
|
|
5337
|
+
const transformed = transformRun(inner.text, false, false, false);
|
|
5338
|
+
const restored = restore(transformed.out, inner.atoms, mask);
|
|
5339
|
+
if (restored === null) return null;
|
|
5340
|
+
atoms.push(node.open + restored + node.close);
|
|
5341
|
+
text += mask;
|
|
5039
5342
|
}
|
|
5040
|
-
text = truncateUnclosedLatexBlock(text, unclosedDouble);
|
|
5041
|
-
parts.push(text);
|
|
5042
5343
|
}
|
|
5043
|
-
return {
|
|
5344
|
+
return { text, atoms };
|
|
5345
|
+
}
|
|
5346
|
+
function reportRestoreViolation() {
|
|
5347
|
+
if (true) {
|
|
5348
|
+
console.error(
|
|
5349
|
+
"[ai-react-markdown] LaTeX preprocessor: atom restoration violated its invariant (more masks in the output than atoms); the slice was re-processed on the legacy path. This is an engine defect \u2014 please report it."
|
|
5350
|
+
);
|
|
5351
|
+
}
|
|
5352
|
+
}
|
|
5353
|
+
function processSliceDefault(slice, probe, mask) {
|
|
5354
|
+
const segments = splitByProtectedRegions(slice);
|
|
5355
|
+
const parts = [];
|
|
5356
|
+
let quiescent = true;
|
|
5357
|
+
let truncatedAtSeamStart = false;
|
|
5358
|
+
let offset = 0;
|
|
5359
|
+
let i = 0;
|
|
5360
|
+
while (i < segments.length) {
|
|
5361
|
+
const segment = segments[i];
|
|
5362
|
+
if (isHardBoundary(segment.kind)) {
|
|
5363
|
+
parts.push(segment.text);
|
|
5364
|
+
offset += segment.text.length;
|
|
5365
|
+
i += 1;
|
|
5366
|
+
continue;
|
|
5367
|
+
}
|
|
5368
|
+
const runStart = offset;
|
|
5369
|
+
const runSegments = [];
|
|
5370
|
+
while (i < segments.length && !isHardBoundary(segments[i].kind)) {
|
|
5371
|
+
runSegments.push(segments[i]);
|
|
5372
|
+
offset += segments[i].text.length;
|
|
5373
|
+
i += 1;
|
|
5374
|
+
}
|
|
5375
|
+
const before = runStart === 0 ? -1 : slice.charCodeAt(runStart - 1);
|
|
5376
|
+
const runStartsAtLineStart = before === -1 || before === 10 || before === 13;
|
|
5377
|
+
const seamEligible = runStart === 0;
|
|
5378
|
+
const emitted = emitRun(buildRunTree(runSegments), mask);
|
|
5379
|
+
if (emitted === null) {
|
|
5380
|
+
reportRestoreViolation();
|
|
5381
|
+
return { ...processSliceLegacy(slice, probe), degradedReason: "restore-invariant" };
|
|
5382
|
+
}
|
|
5383
|
+
const r = transformRun(emitted.text, probe, runStartsAtLineStart, seamEligible);
|
|
5384
|
+
const restored = restore(r.out, emitted.atoms, mask);
|
|
5385
|
+
if (restored === null) {
|
|
5386
|
+
reportRestoreViolation();
|
|
5387
|
+
return { ...processSliceLegacy(slice, probe), degradedReason: "restore-invariant" };
|
|
5388
|
+
}
|
|
5389
|
+
if (r.tailSensitive) quiescent = false;
|
|
5390
|
+
if (r.truncatedAtSeamStart) truncatedAtSeamStart = true;
|
|
5391
|
+
parts.push(restored);
|
|
5392
|
+
}
|
|
5393
|
+
return { out: parts.join(""), quiescent, truncatedAtSeamStart, degradedReason: null };
|
|
5394
|
+
}
|
|
5395
|
+
function processSlice(slice, options) {
|
|
5396
|
+
if (options.legacy === true) return processSliceLegacy(slice, options.probe);
|
|
5397
|
+
return processSliceDefault(slice, options.probe, options.mask);
|
|
5044
5398
|
}
|
|
5045
5399
|
function isBlankRawLine(text, from, to) {
|
|
5046
5400
|
for (let i = from; i < to; i++) {
|
|
@@ -5056,7 +5410,7 @@ function findRawSafeCut(active) {
|
|
|
5056
5410
|
let backtickHazard = false;
|
|
5057
5411
|
let latentLt = false;
|
|
5058
5412
|
for (const segment of segments) {
|
|
5059
|
-
if (segment.
|
|
5413
|
+
if (segment.kind !== "text") {
|
|
5060
5414
|
if (segment.text.includes(">")) latentLt = false;
|
|
5061
5415
|
offset += segment.text.length;
|
|
5062
5416
|
continue;
|
|
@@ -5091,12 +5445,28 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5091
5445
|
const freezeThreshold = options?.freezeThreshold ?? DEFAULT_FREEZE_ATTEMPT_THRESHOLD;
|
|
5092
5446
|
const onAttempt = options?.onAttempt;
|
|
5093
5447
|
const backoff = options?.backoff ?? true;
|
|
5448
|
+
const onDegrade = options?.onDegrade;
|
|
5094
5449
|
let prevSource = "";
|
|
5095
5450
|
let prevOutput = "";
|
|
5096
5451
|
let frozenSrcEnd = 0;
|
|
5097
5452
|
let frozenOut = "";
|
|
5098
5453
|
let triggered = false;
|
|
5099
5454
|
let nextAttemptLen = 0;
|
|
5455
|
+
let lineageDegraded = false;
|
|
5456
|
+
const presence = new PuaPresence();
|
|
5457
|
+
const commit = (source, out) => {
|
|
5458
|
+
prevSource = source;
|
|
5459
|
+
prevOutput = out;
|
|
5460
|
+
return out;
|
|
5461
|
+
};
|
|
5462
|
+
const legacyWhole = (source) => processSlice(source, { legacy: true, probe: false }).out;
|
|
5463
|
+
const degrade = (source, reason) => {
|
|
5464
|
+
lineageDegraded = true;
|
|
5465
|
+
frozenSrcEnd = 0;
|
|
5466
|
+
frozenOut = "";
|
|
5467
|
+
onDegrade?.(reason);
|
|
5468
|
+
return commit(source, legacyWhole(source));
|
|
5469
|
+
};
|
|
5100
5470
|
return function incrementalPreprocessLaTeX(source) {
|
|
5101
5471
|
if (source === prevSource) return prevOutput;
|
|
5102
5472
|
const isAppend = source.length > prevSource.length && source.startsWith(prevSource);
|
|
@@ -5105,16 +5475,20 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5105
5475
|
frozenOut = "";
|
|
5106
5476
|
triggered = false;
|
|
5107
5477
|
nextAttemptLen = 0;
|
|
5478
|
+
lineageDegraded = false;
|
|
5479
|
+
presence.reset();
|
|
5480
|
+
presence.add(source, 0);
|
|
5481
|
+
} else {
|
|
5482
|
+
presence.add(source, prevSource.length);
|
|
5108
5483
|
}
|
|
5109
5484
|
if (!triggered) {
|
|
5110
5485
|
const checkFrom = isAppend ? Math.max(0, prevSource.length - 1) : 0;
|
|
5111
|
-
if (!hasLatexTrigger(source.slice(checkFrom)))
|
|
5112
|
-
prevSource = source;
|
|
5113
|
-
prevOutput = source;
|
|
5114
|
-
return source;
|
|
5115
|
-
}
|
|
5486
|
+
if (!hasLatexTrigger(source.slice(checkFrom))) return commit(source, source);
|
|
5116
5487
|
triggered = true;
|
|
5117
5488
|
}
|
|
5489
|
+
if (lineageDegraded) return commit(source, legacyWhole(source));
|
|
5490
|
+
const mask = presence.select();
|
|
5491
|
+
if (mask === null) return degrade(source, "mask-exhausted");
|
|
5118
5492
|
let active = source.slice(frozenSrcEnd);
|
|
5119
5493
|
if (active.length > freezeThreshold && active.length >= nextAttemptLen) {
|
|
5120
5494
|
const activeLength = active.length;
|
|
@@ -5129,18 +5503,20 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5129
5503
|
};
|
|
5130
5504
|
const cut = findRawSafeCut(active);
|
|
5131
5505
|
if (cut > 0) {
|
|
5132
|
-
const candidate = processSlice(active.slice(0, cut));
|
|
5506
|
+
const candidate = processSlice(active.slice(0, cut), { probe: true, mask });
|
|
5507
|
+
if (candidate.degradedReason !== null) {
|
|
5508
|
+
onAttempt?.({ activeLength, frozenBytes: 0 });
|
|
5509
|
+
return degrade(source, candidate.degradedReason);
|
|
5510
|
+
}
|
|
5133
5511
|
if (candidate.quiescent) freeze(cut, candidate);
|
|
5134
5512
|
}
|
|
5135
5513
|
nextAttemptLen = advanced || !backoff ? 0 : active.length * 2;
|
|
5136
5514
|
onAttempt?.({ activeLength, frozenBytes });
|
|
5137
5515
|
}
|
|
5138
|
-
const tail = processSlice(active, false);
|
|
5516
|
+
const tail = processSlice(active, { probe: false, mask });
|
|
5517
|
+
if (tail.degradedReason !== null) return degrade(source, tail.degradedReason);
|
|
5139
5518
|
const head = tail.truncatedAtSeamStart ? frozenOut.replace(/\s+$/, "") : frozenOut;
|
|
5140
|
-
|
|
5141
|
-
prevSource = source;
|
|
5142
|
-
prevOutput = out;
|
|
5143
|
-
return out;
|
|
5519
|
+
return commit(source, head + tail.out);
|
|
5144
5520
|
};
|
|
5145
5521
|
}
|
|
5146
5522
|
|
|
@@ -5165,6 +5541,8 @@ function createRemendPreprocessor(options) {
|
|
|
5165
5541
|
}
|
|
5166
5542
|
export {
|
|
5167
5543
|
DEFAULT_PAYLOAD,
|
|
5544
|
+
ENGINE_PLACEHOLDER_TAGS,
|
|
5545
|
+
ENGINE_PROVENANCE_PROPERTY,
|
|
5168
5546
|
PIPELINE_STAGES,
|
|
5169
5547
|
SENTINEL_FN_CONTENT,
|
|
5170
5548
|
SENTINEL_LINK_URL,
|
|
@@ -5209,7 +5587,9 @@ export {
|
|
|
5209
5587
|
preprocessLaTeX,
|
|
5210
5588
|
rehypeFooterAdorn,
|
|
5211
5589
|
rehypeRebaseHashLinks_default as rehypeRebaseHashLinks,
|
|
5590
|
+
rehypeVerifyEngineTags,
|
|
5212
5591
|
removeComments,
|
|
5592
|
+
resolveCrossChunkReference,
|
|
5213
5593
|
sanitizeCrossChunkUrl,
|
|
5214
5594
|
sanitizeSchema,
|
|
5215
5595
|
shortenDocumentId,
|