@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.js
CHANGED
|
@@ -2131,6 +2131,38 @@ function normalizeForMatch(s) {
|
|
|
2131
2131
|
return normalizeIdentifier3(s);
|
|
2132
2132
|
}
|
|
2133
2133
|
|
|
2134
|
+
// src/components/blankLineScanner.ts
|
|
2135
|
+
function createBlankLineScanner() {
|
|
2136
|
+
let end = 0;
|
|
2137
|
+
let newline = false;
|
|
2138
|
+
let cr = false;
|
|
2139
|
+
return (source, from = 0) => {
|
|
2140
|
+
if (from === 0) {
|
|
2141
|
+
end = 0;
|
|
2142
|
+
newline = false;
|
|
2143
|
+
cr = false;
|
|
2144
|
+
}
|
|
2145
|
+
for (let i = from; i < source.length; i++) {
|
|
2146
|
+
const c = source[i];
|
|
2147
|
+
if (c === "\n") {
|
|
2148
|
+
if (newline) {
|
|
2149
|
+
end = i + 1;
|
|
2150
|
+
newline = false;
|
|
2151
|
+
} else newline = true;
|
|
2152
|
+
cr = false;
|
|
2153
|
+
} else if (newline) {
|
|
2154
|
+
if ((c === " " || c === " ") && !cr) continue;
|
|
2155
|
+
if (c === "\r" && !cr) cr = true;
|
|
2156
|
+
else {
|
|
2157
|
+
newline = false;
|
|
2158
|
+
cr = false;
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
return end;
|
|
2163
|
+
};
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2134
2166
|
// src/components/collectDefLabels.ts
|
|
2135
2167
|
var SCANNER_BOUNDARY_PROFILE = { defListEnabled: false, mathFlow: false, referenceTaint: false };
|
|
2136
2168
|
function buildProcessor() {
|
|
@@ -2162,19 +2194,12 @@ var setsEqual = (a, b) => {
|
|
|
2162
2194
|
for (const v of a) if (!b.has(v)) return false;
|
|
2163
2195
|
return true;
|
|
2164
2196
|
};
|
|
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
2197
|
var DEF_LINE_START_RE = /^[ \t>*+\d.)-]*\[(?:[^\]\\]|\\[\s\S])*\]:/m;
|
|
2175
2198
|
function createDefLabelScanner(parse = collectDefLabels) {
|
|
2176
2199
|
let prevSource = null;
|
|
2177
2200
|
let prevLabels = null;
|
|
2201
|
+
const scanBlankLines = createBlankLineScanner();
|
|
2202
|
+
let regionStart = 0;
|
|
2178
2203
|
let frozenEnd = 0;
|
|
2179
2204
|
let frozenFootnotes = /* @__PURE__ */ new Set();
|
|
2180
2205
|
let frozenLinks = /* @__PURE__ */ new Set();
|
|
@@ -2187,13 +2212,16 @@ function createDefLabelScanner(parse = collectDefLabels) {
|
|
|
2187
2212
|
};
|
|
2188
2213
|
return {
|
|
2189
2214
|
scan(source) {
|
|
2215
|
+
if (source === prevSource && prevLabels !== null) return prevLabels;
|
|
2216
|
+
const previousRegionStart = regionStart;
|
|
2217
|
+
const appended = prevSource !== null && source.startsWith(prevSource);
|
|
2218
|
+
regionStart = scanBlankLines(source, appended ? prevSource.length : 0);
|
|
2190
2219
|
let isAppend = false;
|
|
2191
2220
|
if (prevSource !== null && prevLabels !== null) {
|
|
2192
2221
|
if (source === prevSource) return prevLabels;
|
|
2193
2222
|
if (source.startsWith(prevSource)) {
|
|
2194
2223
|
isAppend = true;
|
|
2195
|
-
const
|
|
2196
|
-
const region = prevSource.slice(regionStart) + source.slice(prevSource.length);
|
|
2224
|
+
const region = source.slice(previousRegionStart);
|
|
2197
2225
|
if (!DEF_LINE_START_RE.test(region)) {
|
|
2198
2226
|
prevSource = source;
|
|
2199
2227
|
return prevLabels;
|
|
@@ -2426,8 +2454,47 @@ function* extractContributions(mdast, options = {}) {
|
|
|
2426
2454
|
for (const c of out) yield c;
|
|
2427
2455
|
}
|
|
2428
2456
|
|
|
2457
|
+
// src/components/registryIndex.ts
|
|
2458
|
+
function buildRegistryIndex(registry) {
|
|
2459
|
+
const index = {
|
|
2460
|
+
footnotes: /* @__PURE__ */ new Map(),
|
|
2461
|
+
links: /* @__PURE__ */ new Map(),
|
|
2462
|
+
numbers: /* @__PURE__ */ new Map(),
|
|
2463
|
+
counts: /* @__PURE__ */ new Map(),
|
|
2464
|
+
occurrences: /* @__PURE__ */ new Map()
|
|
2465
|
+
};
|
|
2466
|
+
for (const sym of registry.chunkOrder) {
|
|
2467
|
+
const data = registry.chunkData.get(sym);
|
|
2468
|
+
if (!data) continue;
|
|
2469
|
+
for (const label of data.defs.keys()) if (!index.footnotes.has(label)) index.footnotes.set(label, sym);
|
|
2470
|
+
for (const label of data.linkDefs.keys()) if (!index.links.has(label)) index.links.set(label, sym);
|
|
2471
|
+
const local = /* @__PURE__ */ new Map();
|
|
2472
|
+
index.occurrences.set(sym, local);
|
|
2473
|
+
for (const ref of data.refs) {
|
|
2474
|
+
if (ref.kind !== "footnote") continue;
|
|
2475
|
+
const label = ref.label;
|
|
2476
|
+
if (!index.numbers.has(label)) index.numbers.set(label, index.numbers.size + 1);
|
|
2477
|
+
const total = (index.counts.get(label) ?? 0) + 1;
|
|
2478
|
+
index.counts.set(label, total);
|
|
2479
|
+
const prior = local.get(label);
|
|
2480
|
+
if (prior) prior.count++;
|
|
2481
|
+
else local.set(label, { start: total, count: 1 });
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
return index;
|
|
2485
|
+
}
|
|
2486
|
+
|
|
2429
2487
|
// src/components/documentRegistry.ts
|
|
2430
2488
|
function createRegistry(onEmpty) {
|
|
2489
|
+
let index;
|
|
2490
|
+
let indexedVersion = -1;
|
|
2491
|
+
const getIndex = () => {
|
|
2492
|
+
if (!index || indexedVersion !== reg.version) {
|
|
2493
|
+
index = buildRegistryIndex(reg);
|
|
2494
|
+
indexedVersion = reg.version;
|
|
2495
|
+
}
|
|
2496
|
+
return index;
|
|
2497
|
+
};
|
|
2431
2498
|
const reg = {
|
|
2432
2499
|
chunkOrder: [],
|
|
2433
2500
|
chunkData: /* @__PURE__ */ new Map(),
|
|
@@ -2579,72 +2646,25 @@ function createRegistry(onEmpty) {
|
|
|
2579
2646
|
};
|
|
2580
2647
|
},
|
|
2581
2648
|
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;
|
|
2649
|
+
return getIndex().footnotes.get(normalizeId(label)) ?? null;
|
|
2588
2650
|
},
|
|
2589
2651
|
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;
|
|
2652
|
+
return getIndex().links.get(normalizeId(label)) ?? null;
|
|
2596
2653
|
},
|
|
2597
2654
|
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;
|
|
2655
|
+
return getIndex().numbers.get(normalizeId(label)) ?? null;
|
|
2614
2656
|
},
|
|
2615
2657
|
resolveLinkDef(label) {
|
|
2616
|
-
const
|
|
2617
|
-
|
|
2618
|
-
return this.chunkData.get(sym)?.linkDefs.get(
|
|
2658
|
+
const id = normalizeId(label);
|
|
2659
|
+
const sym = getIndex().links.get(id);
|
|
2660
|
+
return sym ? this.chunkData.get(sym)?.linkDefs.get(id) ?? null : null;
|
|
2619
2661
|
},
|
|
2620
2662
|
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;
|
|
2663
|
+
return getIndex().counts.get(normalizeId(label)) ?? 0;
|
|
2631
2664
|
},
|
|
2632
2665
|
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;
|
|
2666
|
+
const range = getIndex().occurrences.get(chunkSym)?.get(normalizeId(label));
|
|
2667
|
+
return range && Number.isInteger(localOccurrence) && localOccurrence > 0 && localOccurrence <= range.count ? range.start + localOccurrence - 1 : null;
|
|
2648
2668
|
},
|
|
2649
2669
|
_notify() {
|
|
2650
2670
|
this.version++;
|
|
@@ -2701,6 +2721,55 @@ function rehypeUnwrapCrossChunkImages() {
|
|
|
2701
2721
|
|
|
2702
2722
|
// src/components/pluginChain.ts
|
|
2703
2723
|
import rehypeSanitize from "rehype-sanitize";
|
|
2724
|
+
|
|
2725
|
+
// src/components/rehypeVerifyEngineTags.ts
|
|
2726
|
+
var ENGINE_PLACEHOLDER_TAGS = /* @__PURE__ */ new Set([
|
|
2727
|
+
"footnote-sup",
|
|
2728
|
+
"cross-chunk-link",
|
|
2729
|
+
"cross-chunk-image"
|
|
2730
|
+
]);
|
|
2731
|
+
var ENGINE_PROVENANCE_PROPERTY = "engineProvenance";
|
|
2732
|
+
function walk(parent, provenance, ancestors) {
|
|
2733
|
+
const children = parent.children;
|
|
2734
|
+
let i = 0;
|
|
2735
|
+
while (i < children.length) {
|
|
2736
|
+
const node = children[i];
|
|
2737
|
+
if (node.type === "element" && ENGINE_PLACEHOLDER_TAGS.has(node.tagName)) {
|
|
2738
|
+
const props = node.properties ?? {};
|
|
2739
|
+
const stamped = props[ENGINE_PROVENANCE_PROPERTY];
|
|
2740
|
+
const genuine = provenance !== "" && typeof stamped === "string" && stamped === provenance;
|
|
2741
|
+
if (genuine) {
|
|
2742
|
+
delete props[ENGINE_PROVENANCE_PROPERTY];
|
|
2743
|
+
if (ancestors && (node.tagName === "cross-chunk-link" || node.tagName === "cross-chunk-image")) {
|
|
2744
|
+
(node.data ??= {}).referenceAncestors = ancestors.slice();
|
|
2745
|
+
}
|
|
2746
|
+
ancestors?.push(
|
|
2747
|
+
node.tagName === "cross-chunk-link" ? "a" : node.tagName === "cross-chunk-image" ? "img" : node.tagName
|
|
2748
|
+
);
|
|
2749
|
+
walk(node, provenance, ancestors);
|
|
2750
|
+
ancestors?.pop();
|
|
2751
|
+
i += 1;
|
|
2752
|
+
} else {
|
|
2753
|
+
children.splice(i, 1, ...node.children);
|
|
2754
|
+
}
|
|
2755
|
+
continue;
|
|
2756
|
+
}
|
|
2757
|
+
if (node.type === "element") {
|
|
2758
|
+
ancestors?.push(node.tagName);
|
|
2759
|
+
walk(node, provenance, ancestors);
|
|
2760
|
+
ancestors?.pop();
|
|
2761
|
+
}
|
|
2762
|
+
i += 1;
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
function rehypeVerifyEngineTags(options) {
|
|
2766
|
+
const provenance = options?.provenance ?? "";
|
|
2767
|
+
return function transformer(tree) {
|
|
2768
|
+
walk(tree, provenance, options?.referenceAncestors ? [] : void 0);
|
|
2769
|
+
};
|
|
2770
|
+
}
|
|
2771
|
+
|
|
2772
|
+
// src/components/pluginChain.ts
|
|
2704
2773
|
import remarkBreaks from "remark-breaks";
|
|
2705
2774
|
import remarkCjkFriendly from "remark-cjk-friendly";
|
|
2706
2775
|
import remarkCjkFriendlyGfmStrikethrough from "remark-cjk-friendly-gfm-strikethrough";
|
|
@@ -2717,16 +2786,18 @@ import remarkRemoveComments from "remark-remove-comments";
|
|
|
2717
2786
|
// src/components/rehypeRebaseHashLinks.ts
|
|
2718
2787
|
import { visit as visit5 } from "unist-util-visit";
|
|
2719
2788
|
var DEFAULT_PREFIX = "user-content-";
|
|
2789
|
+
function rebaseHashHref(href, prefix) {
|
|
2790
|
+
const hashPrefix = "#" + prefix;
|
|
2791
|
+
return href.startsWith("#") && !href.startsWith(hashPrefix) ? hashPrefix + href.slice(1) : href;
|
|
2792
|
+
}
|
|
2720
2793
|
var rehypeRebaseHashLinks = (options) => {
|
|
2721
2794
|
const prefix = options?.prefix ?? DEFAULT_PREFIX;
|
|
2722
|
-
const hashPrefix = "#" + prefix;
|
|
2723
2795
|
return (tree) => {
|
|
2724
2796
|
visit5(tree, "element", (node) => {
|
|
2725
2797
|
if (node.tagName !== "a") return;
|
|
2726
2798
|
const href = node.properties?.href;
|
|
2727
2799
|
if (typeof href !== "string" || !href.startsWith("#")) return;
|
|
2728
|
-
|
|
2729
|
-
node.properties.href = hashPrefix + href.slice(1);
|
|
2800
|
+
node.properties.href = rebaseHashHref(href, prefix);
|
|
2730
2801
|
});
|
|
2731
2802
|
};
|
|
2732
2803
|
};
|
|
@@ -2806,10 +2877,21 @@ function buildCoreRemarkPlugins(enginePlugins) {
|
|
|
2806
2877
|
...DISPLAY_OPTIMIZE_CHAIN.filter(([name]) => selected.has(name)).map(([, plugin]) => plugin)
|
|
2807
2878
|
];
|
|
2808
2879
|
}
|
|
2809
|
-
function buildCoreRehypePlugins(sanitizeSchema2, clobberPrefix) {
|
|
2880
|
+
function buildCoreRehypePlugins(sanitizeSchema2, clobberPrefix, options) {
|
|
2810
2881
|
return [
|
|
2811
2882
|
// Allow raw HTML through so rehype-sanitize can handle it.
|
|
2812
2883
|
[rehypeRaw, { passThrough: [] }],
|
|
2884
|
+
// Unwrap forged engine placeholders BEFORE sanitize admits their tag
|
|
2885
|
+
// names. Only when the caller holds a credential (see the option's doc).
|
|
2886
|
+
...options ? [
|
|
2887
|
+
[
|
|
2888
|
+
rehypeVerifyEngineTags,
|
|
2889
|
+
{
|
|
2890
|
+
provenance: options.provenance,
|
|
2891
|
+
...sanitizeSchema2.ancestors?.a || sanitizeSchema2.ancestors?.img ? { referenceAncestors: true } : {}
|
|
2892
|
+
}
|
|
2893
|
+
]
|
|
2894
|
+
] : [],
|
|
2813
2895
|
// Sanitize HTML while allowing <mark> (highlight), KaTeX class names,
|
|
2814
2896
|
// and any extra protocols the caller permitted via the `sanitizeSchema`
|
|
2815
2897
|
// prop. Override `clobberPrefix` with the instance-scoped value — the
|
|
@@ -2849,6 +2931,10 @@ function buildCoreRemarkRehypeOptions(enableDefinitionList) {
|
|
|
2849
2931
|
}
|
|
2850
2932
|
|
|
2851
2933
|
// src/components/customMdastHandlers.ts
|
|
2934
|
+
function provenanceProps(s) {
|
|
2935
|
+
const provenance = s.options.provenance;
|
|
2936
|
+
return typeof provenance === "string" ? { engineProvenance: provenance } : {};
|
|
2937
|
+
}
|
|
2852
2938
|
function localDefProps(s, id) {
|
|
2853
2939
|
const def = s.definitionById.get(id);
|
|
2854
2940
|
if (!def || typeof def.url !== "string" || def.url === SENTINEL_LINK_URL) return {};
|
|
@@ -2879,15 +2965,14 @@ function buildCrossChunkHandlers() {
|
|
|
2879
2965
|
type: "element",
|
|
2880
2966
|
tagName: "cross-chunk-link",
|
|
2881
2967
|
properties: {
|
|
2882
|
-
//
|
|
2883
|
-
//
|
|
2884
|
-
|
|
2885
|
-
// which also preserves source case. Registry lookups normalize
|
|
2886
|
-
// internally, so cross-chunk case-insensitive matching still works.
|
|
2968
|
+
// Display labels decode escapes; registry identifiers must retain
|
|
2969
|
+
// those bytes. Never use the display label as the lookup key.
|
|
2970
|
+
identifier: node.identifier,
|
|
2887
2971
|
label: node.label ?? node.identifier,
|
|
2888
2972
|
referenceType: node.referenceType,
|
|
2889
2973
|
documentId: s.options.documentId,
|
|
2890
|
-
...localDefProps(s, id)
|
|
2974
|
+
...localDefProps(s, id),
|
|
2975
|
+
...provenanceProps(s)
|
|
2891
2976
|
},
|
|
2892
2977
|
children: s.all(node)
|
|
2893
2978
|
};
|
|
@@ -2901,11 +2986,13 @@ function buildCrossChunkHandlers() {
|
|
|
2901
2986
|
type: "element",
|
|
2902
2987
|
tagName: "cross-chunk-image",
|
|
2903
2988
|
properties: {
|
|
2989
|
+
identifier: node.identifier,
|
|
2904
2990
|
label: node.label ?? node.identifier,
|
|
2905
2991
|
referenceType: node.referenceType,
|
|
2906
2992
|
alt: node.alt ?? "",
|
|
2907
2993
|
documentId: s.options.documentId,
|
|
2908
|
-
...localDefProps(s, id)
|
|
2994
|
+
...localDefProps(s, id),
|
|
2995
|
+
...provenanceProps(s)
|
|
2909
2996
|
},
|
|
2910
2997
|
children: []
|
|
2911
2998
|
};
|
|
@@ -2922,7 +3009,8 @@ function buildCrossChunkHandlers() {
|
|
|
2922
3009
|
properties: {
|
|
2923
3010
|
label: node.identifier,
|
|
2924
3011
|
localOccurrence,
|
|
2925
|
-
documentId: s.options.documentId
|
|
3012
|
+
documentId: s.options.documentId,
|
|
3013
|
+
...provenanceProps(s)
|
|
2926
3014
|
},
|
|
2927
3015
|
children: []
|
|
2928
3016
|
};
|
|
@@ -2940,7 +3028,8 @@ function buildCrossChunkHandlers() {
|
|
|
2940
3028
|
// first client frame), where the local synthetic footer is what
|
|
2941
3029
|
// renders, so marks and footer agree (core-render-02).
|
|
2942
3030
|
localNumber: s.footnoteOrder.indexOf(id) + 1,
|
|
2943
|
-
documentId: s.options.documentId
|
|
3031
|
+
documentId: s.options.documentId,
|
|
3032
|
+
...provenanceProps(s)
|
|
2944
3033
|
},
|
|
2945
3034
|
children: []
|
|
2946
3035
|
};
|
|
@@ -4160,8 +4249,8 @@ var sanitizeSchema = deepFreeze(
|
|
|
4160
4249
|
attributes: {
|
|
4161
4250
|
...defaultSchema.attributes,
|
|
4162
4251
|
code: mergeClassNameAllowlist(defaultSchema.attributes?.code, ["math-inline", "math-display"]),
|
|
4163
|
-
"cross-chunk-link": ["label", "referenceType", "documentId", "localUrl", "localTitle"],
|
|
4164
|
-
"cross-chunk-image": ["label", "referenceType", "documentId", "alt", "localUrl", "localTitle"],
|
|
4252
|
+
"cross-chunk-link": ["identifier", "label", "referenceType", "documentId", "localUrl", "localTitle"],
|
|
4253
|
+
"cross-chunk-image": ["identifier", "label", "referenceType", "documentId", "alt", "localUrl", "localTitle"],
|
|
4165
4254
|
"footnote-sup": ["label", "localOccurrence", "localNumber", "documentId"]
|
|
4166
4255
|
},
|
|
4167
4256
|
strip: [.../* @__PURE__ */ new Set([...defaultSchema.strip || [], ...STRIPPED_TAGS])]
|
|
@@ -4197,6 +4286,49 @@ function sanitizeCrossChunkUrl(rawUrl, key, tagName, urlTransform, schema) {
|
|
|
4197
4286
|
return String(transformed);
|
|
4198
4287
|
}
|
|
4199
4288
|
|
|
4289
|
+
// src/components/resolveCrossChunkReference.ts
|
|
4290
|
+
import rehypeSanitize2 from "rehype-sanitize";
|
|
4291
|
+
import { normalizeUri as normalizeUri3 } from "micromark-util-sanitize-uri";
|
|
4292
|
+
function resolveCrossChunkReference(input, schema, urlTransform, clobberPrefix) {
|
|
4293
|
+
const key = input.tagName === "a" ? "href" : "src";
|
|
4294
|
+
const element = {
|
|
4295
|
+
type: "element",
|
|
4296
|
+
tagName: input.tagName,
|
|
4297
|
+
properties: {
|
|
4298
|
+
[key]: normalizeUri3(input.url),
|
|
4299
|
+
...input.tagName === "img" ? { alt: input.alt ?? "" } : {},
|
|
4300
|
+
...input.title !== void 0 ? { title: input.title } : {}
|
|
4301
|
+
},
|
|
4302
|
+
children: input.tagName === "a" ? [{ type: "text", value: "__reference_children__" }] : []
|
|
4303
|
+
};
|
|
4304
|
+
const requiredAncestors = schema.ancestors?.[input.tagName];
|
|
4305
|
+
const recordedAncestors = input.node?.data?.referenceAncestors;
|
|
4306
|
+
let finalSchema = schema;
|
|
4307
|
+
if (requiredAncestors && Array.isArray(recordedAncestors) && requiredAncestors.some((tag) => recordedAncestors.includes(tag))) {
|
|
4308
|
+
const ancestors = { ...schema.ancestors };
|
|
4309
|
+
delete ancestors[input.tagName];
|
|
4310
|
+
finalSchema = { ...schema, ancestors };
|
|
4311
|
+
}
|
|
4312
|
+
const root2 = rehypeSanitize2({ ...finalSchema, clobberPrefix })({ type: "root", children: [element] });
|
|
4313
|
+
const node = root2.children[0];
|
|
4314
|
+
if (node?.type !== "element") return { element: null, keepChildren: node?.type === "text" };
|
|
4315
|
+
if (node.tagName === "a" && typeof node.properties.href === "string") {
|
|
4316
|
+
node.properties.href = rebaseHashHref(node.properties.href, clobberPrefix);
|
|
4317
|
+
}
|
|
4318
|
+
node.children = input.node?.children ?? [];
|
|
4319
|
+
if (input.node?.position) node.position = input.node.position;
|
|
4320
|
+
buildTransform({
|
|
4321
|
+
allowedElements: void 0,
|
|
4322
|
+
disallowedElements: void 0,
|
|
4323
|
+
allowElement: void 0,
|
|
4324
|
+
skipHtml: void 0,
|
|
4325
|
+
unwrapDisallowed: void 0,
|
|
4326
|
+
urlTransform
|
|
4327
|
+
})(node, 0, root2);
|
|
4328
|
+
node.children = [];
|
|
4329
|
+
return { element: node, keepChildren: false };
|
|
4330
|
+
}
|
|
4331
|
+
|
|
4200
4332
|
// src/plugins/defs.ts
|
|
4201
4333
|
function getEnginePluginInternals(plugin) {
|
|
4202
4334
|
const candidate = plugin;
|
|
@@ -4401,6 +4533,8 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4401
4533
|
let source = "";
|
|
4402
4534
|
let visibleEnd = 0;
|
|
4403
4535
|
let pending = [];
|
|
4536
|
+
let pendingHead = 0;
|
|
4537
|
+
const pendingCount = () => pending.length - pendingHead;
|
|
4404
4538
|
let tentativeEnd = 0;
|
|
4405
4539
|
let finished = false;
|
|
4406
4540
|
let seam;
|
|
@@ -4445,7 +4579,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4445
4579
|
cancelFrame = void 0;
|
|
4446
4580
|
};
|
|
4447
4581
|
const ensureScheduled = () => {
|
|
4448
|
-
if (disposed || cancelFrame ||
|
|
4582
|
+
if (disposed || cancelFrame || pendingCount() === 0) return;
|
|
4449
4583
|
lastTickAt = now();
|
|
4450
4584
|
credit = 0;
|
|
4451
4585
|
cancelFrame = schedule(tick);
|
|
@@ -4459,31 +4593,38 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4459
4593
|
const params = resolveParams();
|
|
4460
4594
|
let rate;
|
|
4461
4595
|
if (finished && drainDeadlineAt !== void 0) {
|
|
4462
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4596
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, drainDeadlineAt - t));
|
|
4463
4597
|
} else if (gapWindow.length > 0 && lastArrivalAt !== void 0) {
|
|
4464
4598
|
const gaps = gapWindow.map((s) => s.gap).sort((a, b) => a - b);
|
|
4465
4599
|
const intervalQ = gaps[Math.min(gaps.length - 1, Math.floor(gaps.length * INTERVAL_QUANTILE))];
|
|
4466
4600
|
const horizon = Math.max(16, Math.min(params.bufferFactor * intervalQ + HORIZON_PAD_MS, params.maxLagMs));
|
|
4467
4601
|
const deadline = Math.max(lastArrivalAt + horizon, t + DEADLINE_FLOOR_MS);
|
|
4468
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4602
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, deadline - t));
|
|
4469
4603
|
} else {
|
|
4470
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4604
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, params.correctionTauMs));
|
|
4471
4605
|
}
|
|
4472
4606
|
credit += rate * dt / 1e3;
|
|
4473
|
-
const reveal = Math.min(Math.floor(credit),
|
|
4607
|
+
const reveal = Math.min(Math.floor(credit), pendingCount());
|
|
4474
4608
|
if (reveal > 0) {
|
|
4475
|
-
visibleEnd = pending[reveal - 1];
|
|
4476
|
-
|
|
4477
|
-
|
|
4609
|
+
visibleEnd = pending[pendingHead + reveal - 1];
|
|
4610
|
+
pendingHead += reveal;
|
|
4611
|
+
if (pendingHead === pending.length) {
|
|
4612
|
+
pending = [];
|
|
4613
|
+
pendingHead = 0;
|
|
4614
|
+
} else if (pendingHead >= 1024 && pendingHead * 2 >= pending.length) {
|
|
4615
|
+
pending = pending.slice(pendingHead);
|
|
4616
|
+
pendingHead = 0;
|
|
4617
|
+
}
|
|
4618
|
+
credit = pendingCount() > 0 ? credit - reveal : 0;
|
|
4478
4619
|
notify();
|
|
4479
4620
|
}
|
|
4480
|
-
if (!disposed && !cancelFrame &&
|
|
4621
|
+
if (!disposed && !cancelFrame && pendingCount() > 0) cancelFrame = schedule(tick);
|
|
4481
4622
|
};
|
|
4482
4623
|
const resegmentTail = () => {
|
|
4483
|
-
if (seam !== void 0 && seam < source.length && pending[pending.length - 1] === seam) {
|
|
4624
|
+
if (pendingCount() > 0 && seam !== void 0 && seam < source.length && pending[pending.length - 1] === seam) {
|
|
4484
4625
|
pending.pop();
|
|
4485
4626
|
}
|
|
4486
|
-
const from =
|
|
4627
|
+
const from = pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd;
|
|
4487
4628
|
let anchor = from;
|
|
4488
4629
|
if (seam !== void 0 && from <= seam) {
|
|
4489
4630
|
anchor = Math.max(0, from - RESUME_LOOKBACK);
|
|
@@ -4517,6 +4658,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4517
4658
|
visibleEnd = next.length;
|
|
4518
4659
|
tentativeEnd = next.length;
|
|
4519
4660
|
pending = [];
|
|
4661
|
+
pendingHead = 0;
|
|
4520
4662
|
seam = next.length;
|
|
4521
4663
|
credit = 0;
|
|
4522
4664
|
cancelScheduled();
|
|
@@ -4548,7 +4690,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4548
4690
|
if (finished) return;
|
|
4549
4691
|
finished = true;
|
|
4550
4692
|
lastArrivalAt = void 0;
|
|
4551
|
-
if (tentativeEnd > (
|
|
4693
|
+
if (tentativeEnd > (pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd)) {
|
|
4552
4694
|
pending.push(tentativeEnd);
|
|
4553
4695
|
}
|
|
4554
4696
|
const params = resolveParams();
|
|
@@ -4574,10 +4716,11 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4574
4716
|
snap,
|
|
4575
4717
|
flush() {
|
|
4576
4718
|
disposed = false;
|
|
4577
|
-
const target = finished ? source.length :
|
|
4719
|
+
const target = finished ? source.length : pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd;
|
|
4578
4720
|
if (target <= visibleEnd) return;
|
|
4579
4721
|
visibleEnd = target;
|
|
4580
4722
|
pending = [];
|
|
4723
|
+
pendingHead = 0;
|
|
4581
4724
|
credit = 0;
|
|
4582
4725
|
cancelScheduled();
|
|
4583
4726
|
notify();
|
|
@@ -4600,6 +4743,12 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4600
4743
|
};
|
|
4601
4744
|
|
|
4602
4745
|
// src/preprocessors/latex.ts
|
|
4746
|
+
function isHardBoundary(kind) {
|
|
4747
|
+
return kind === "code" || kind === "literal" || kind === "multilineTag";
|
|
4748
|
+
}
|
|
4749
|
+
function hasLineEnding(text) {
|
|
4750
|
+
return text.includes("\n") || text.includes("\r");
|
|
4751
|
+
}
|
|
4603
4752
|
function getRepeatedMarkerLength(content, start, marker) {
|
|
4604
4753
|
let end = start;
|
|
4605
4754
|
while (end < content.length && content[end] === marker) {
|
|
@@ -4667,11 +4816,11 @@ function splitByProtectedRegions(content) {
|
|
|
4667
4816
|
let multilineFenceMarker = null;
|
|
4668
4817
|
let multilineFenceLength = 0;
|
|
4669
4818
|
let multilineFenceIndent = 0;
|
|
4670
|
-
function pushProtected(start, end) {
|
|
4819
|
+
function pushProtected(start, end, kind) {
|
|
4671
4820
|
if (start > lastIndex) {
|
|
4672
|
-
segments.push({ text: content.substring(lastIndex, start)
|
|
4821
|
+
segments.push({ kind: "text", text: content.substring(lastIndex, start) });
|
|
4673
4822
|
}
|
|
4674
|
-
segments.push({ text: content.substring(start, end)
|
|
4823
|
+
segments.push({ kind, text: content.substring(start, end) });
|
|
4675
4824
|
lastIndex = end;
|
|
4676
4825
|
}
|
|
4677
4826
|
let i = 0;
|
|
@@ -4682,7 +4831,7 @@ function splitByProtectedRegions(content) {
|
|
|
4682
4831
|
const runLen = getRepeatedMarkerLength(content, i, multilineFenceMarker);
|
|
4683
4832
|
const closerIndent = lineIndentBefore(content, i);
|
|
4684
4833
|
if (runLen >= multilineFenceLength && closerIndent !== -1 && closerIndent <= multilineFenceIndent + 3 && restOfLineIsBlank(content, i + runLen)) {
|
|
4685
|
-
pushProtected(multilineStart, i + runLen);
|
|
4834
|
+
pushProtected(multilineStart, i + runLen, "code");
|
|
4686
4835
|
multilineStart = -1;
|
|
4687
4836
|
multilineFenceMarker = null;
|
|
4688
4837
|
multilineFenceLength = 0;
|
|
@@ -4709,7 +4858,7 @@ function splitByProtectedRegions(content) {
|
|
|
4709
4858
|
if (char === "`") {
|
|
4710
4859
|
const closeIdx = findClosingBacktickRun(content, i + runLen, runLen);
|
|
4711
4860
|
if (closeIdx !== -1) {
|
|
4712
|
-
pushProtected(i, closeIdx + runLen);
|
|
4861
|
+
pushProtected(i, closeIdx + runLen, "code");
|
|
4713
4862
|
i = closeIdx + runLen;
|
|
4714
4863
|
continue;
|
|
4715
4864
|
}
|
|
@@ -4734,7 +4883,11 @@ function splitByProtectedRegions(content) {
|
|
|
4734
4883
|
endIndex = content.length;
|
|
4735
4884
|
}
|
|
4736
4885
|
}
|
|
4737
|
-
pushProtected(
|
|
4886
|
+
pushProtected(
|
|
4887
|
+
i,
|
|
4888
|
+
endIndex,
|
|
4889
|
+
isOpeningPairedTag ? "literal" : hasLineEnding(content.substring(i, endIndex)) ? "multilineTag" : "tag"
|
|
4890
|
+
);
|
|
4738
4891
|
i = endIndex;
|
|
4739
4892
|
continue;
|
|
4740
4893
|
}
|
|
@@ -4742,10 +4895,10 @@ function splitByProtectedRegions(content) {
|
|
|
4742
4895
|
i += 1;
|
|
4743
4896
|
}
|
|
4744
4897
|
if (multilineStart !== -1) {
|
|
4745
|
-
pushProtected(multilineStart, content.length);
|
|
4898
|
+
pushProtected(multilineStart, content.length, "code");
|
|
4746
4899
|
}
|
|
4747
4900
|
if (lastIndex < content.length) {
|
|
4748
|
-
segments.push({ text: content.substring(lastIndex)
|
|
4901
|
+
segments.push({ kind: "text", text: content.substring(lastIndex) });
|
|
4749
4902
|
}
|
|
4750
4903
|
return segments;
|
|
4751
4904
|
}
|
|
@@ -4899,20 +5052,22 @@ function escapeLatexPipesInUnclosed(text) {
|
|
|
4899
5052
|
const tail = text.substring(unclosedStart + delimLen);
|
|
4900
5053
|
return before + delim + replaceUnescapedPipes(tail);
|
|
4901
5054
|
}
|
|
4902
|
-
function opensMathFlow(text, pos) {
|
|
5055
|
+
function opensMathFlow(text, pos, runStartsAtLineStart) {
|
|
4903
5056
|
let i = pos;
|
|
4904
5057
|
let spaces = 0;
|
|
4905
|
-
while (i > 0
|
|
5058
|
+
while (i > 0) {
|
|
5059
|
+
const prev = text[i - 1];
|
|
5060
|
+
if (prev === "\n" || prev === "\r") return true;
|
|
4906
5061
|
i -= 1;
|
|
4907
5062
|
if (text[i] !== " ") return false;
|
|
4908
5063
|
spaces += 1;
|
|
4909
5064
|
if (spaces > 3) return false;
|
|
4910
5065
|
}
|
|
4911
|
-
return
|
|
5066
|
+
return runStartsAtLineStart;
|
|
4912
5067
|
}
|
|
4913
|
-
function truncateUnclosedLatexBlock(text, unclosedStart = findUnclosedDelimiterStart(text, "double-only")) {
|
|
5068
|
+
function truncateUnclosedLatexBlock(text, runStartsAtLineStart, unclosedStart = findUnclosedDelimiterStart(text, "double-only")) {
|
|
4914
5069
|
if (unclosedStart === -1) return text;
|
|
4915
|
-
if (!opensMathFlow(text, unclosedStart)) return text;
|
|
5070
|
+
if (!opensMathFlow(text, unclosedStart, runStartsAtLineStart)) return text;
|
|
4916
5071
|
return text.substring(0, unclosedStart).trimEnd();
|
|
4917
5072
|
}
|
|
4918
5073
|
function escapeTextUnderscores(text) {
|
|
@@ -4957,7 +5112,8 @@ function convertSingleToDoubleDollar(text) {
|
|
|
4957
5112
|
}
|
|
4958
5113
|
function preprocessLaTeX(str) {
|
|
4959
5114
|
if (!hasLatexTrigger(str)) return str;
|
|
4960
|
-
|
|
5115
|
+
const mask = selectMask(str);
|
|
5116
|
+
return (mask === null ? processSlice(str, { legacy: true, probe: false }) : processSlice(str, { probe: false, mask })).out;
|
|
4961
5117
|
}
|
|
4962
5118
|
function hasLatexTrigger(str) {
|
|
4963
5119
|
return str.includes("$") || str.includes("\\[") || str.includes("\\(");
|
|
@@ -4986,42 +5142,240 @@ function hasUnclosedTextCommand(text) {
|
|
|
4986
5142
|
}
|
|
4987
5143
|
var RESIDUAL_OPEN_BRACKET_RE = /(?<!!)\\\[/;
|
|
4988
5144
|
var LEADING_DOUBLE_DOLLAR_RE = /^\s*\$\$/;
|
|
4989
|
-
|
|
5145
|
+
var PUA_START = 57344;
|
|
5146
|
+
var PUA_END = 63743;
|
|
5147
|
+
var PUA_SIZE = PUA_END - PUA_START + 1;
|
|
5148
|
+
function selectMask(source) {
|
|
5149
|
+
const first = String.fromCharCode(PUA_START);
|
|
5150
|
+
if (source.indexOf(first) === -1) return first;
|
|
5151
|
+
const seen = new Uint8Array(PUA_SIZE);
|
|
5152
|
+
for (let i = 0; i < source.length; i++) {
|
|
5153
|
+
const c = source.charCodeAt(i);
|
|
5154
|
+
if (c >= PUA_START && c <= PUA_END) seen[c - PUA_START] = 1;
|
|
5155
|
+
}
|
|
5156
|
+
for (let k = 0; k < PUA_SIZE; k++) if (seen[k] === 0) return String.fromCharCode(PUA_START + k);
|
|
5157
|
+
return null;
|
|
5158
|
+
}
|
|
5159
|
+
var PuaPresence = class {
|
|
5160
|
+
bits = new Uint8Array(PUA_SIZE);
|
|
5161
|
+
distinct = 0;
|
|
5162
|
+
reset() {
|
|
5163
|
+
this.bits.fill(0);
|
|
5164
|
+
this.distinct = 0;
|
|
5165
|
+
}
|
|
5166
|
+
add(text, from) {
|
|
5167
|
+
for (let i = from; i < text.length; i++) {
|
|
5168
|
+
const c = text.charCodeAt(i);
|
|
5169
|
+
if (c >= PUA_START && c <= PUA_END) {
|
|
5170
|
+
const k = c - PUA_START;
|
|
5171
|
+
if (this.bits[k] === 0) {
|
|
5172
|
+
this.bits[k] = 1;
|
|
5173
|
+
this.distinct += 1;
|
|
5174
|
+
}
|
|
5175
|
+
}
|
|
5176
|
+
}
|
|
5177
|
+
}
|
|
5178
|
+
select() {
|
|
5179
|
+
if (this.distinct === 0) return String.fromCharCode(PUA_START);
|
|
5180
|
+
if (this.distinct >= PUA_SIZE) return null;
|
|
5181
|
+
for (let k = 0; k < PUA_SIZE; k++) if (this.bits[k] === 0) return String.fromCharCode(PUA_START + k);
|
|
5182
|
+
return null;
|
|
5183
|
+
}
|
|
5184
|
+
};
|
|
5185
|
+
function transformRun(input, probe, runStartsAtLineStart, seamEligible) {
|
|
5186
|
+
let text = input;
|
|
5187
|
+
let tailSensitive = false;
|
|
5188
|
+
let truncatedAtSeamStart = false;
|
|
5189
|
+
text = escapeMhchemCommands(text);
|
|
5190
|
+
text = escapeCurrencyDollarSigns(text);
|
|
5191
|
+
text = convertLatexDelimiters(text);
|
|
5192
|
+
if (probe && RESIDUAL_OPEN_BRACKET_RE.test(text)) tailSensitive = true;
|
|
5193
|
+
text = escapeLatexPipes(text);
|
|
5194
|
+
if (probe && findUnclosedDelimiterStart(text, "both") !== -1) tailSensitive = true;
|
|
5195
|
+
text = escapeLatexPipesInUnclosed(text);
|
|
5196
|
+
if (probe && hasUnclosedTextCommand(text)) tailSensitive = true;
|
|
5197
|
+
text = escapeTextUnderscores(text);
|
|
5198
|
+
text = convertSingleToDoubleDollar(text);
|
|
5199
|
+
let unclosedDouble;
|
|
5200
|
+
if (probe || seamEligible && LEADING_DOUBLE_DOLLAR_RE.test(text)) {
|
|
5201
|
+
unclosedDouble = findUnclosedDelimiterStart(text, "double-only");
|
|
5202
|
+
if (unclosedDouble !== -1) {
|
|
5203
|
+
tailSensitive = true;
|
|
5204
|
+
if (seamEligible && opensMathFlow(text, unclosedDouble, runStartsAtLineStart) && text.slice(0, unclosedDouble).trim() === "") {
|
|
5205
|
+
truncatedAtSeamStart = true;
|
|
5206
|
+
}
|
|
5207
|
+
}
|
|
5208
|
+
}
|
|
5209
|
+
text = truncateUnclosedLatexBlock(text, runStartsAtLineStart, unclosedDouble);
|
|
5210
|
+
return { out: text, tailSensitive, truncatedAtSeamStart };
|
|
5211
|
+
}
|
|
5212
|
+
function processSliceLegacy(slice, probe) {
|
|
4990
5213
|
const segments = splitByProtectedRegions(slice);
|
|
4991
5214
|
const parts = [];
|
|
4992
5215
|
let quiescent = true;
|
|
4993
5216
|
let truncatedAtSeamStart = false;
|
|
4994
5217
|
for (let index = 0; index < segments.length; index++) {
|
|
4995
5218
|
const segment = segments[index];
|
|
4996
|
-
if (segment.
|
|
5219
|
+
if (segment.kind !== "text") {
|
|
4997
5220
|
parts.push(segment.text);
|
|
4998
5221
|
continue;
|
|
4999
5222
|
}
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5223
|
+
const r = transformRun(segment.text, probe, true, index === 0);
|
|
5224
|
+
if (r.tailSensitive) quiescent = false;
|
|
5225
|
+
if (r.truncatedAtSeamStart) truncatedAtSeamStart = true;
|
|
5226
|
+
parts.push(r.out);
|
|
5227
|
+
}
|
|
5228
|
+
return { out: parts.join(""), quiescent, truncatedAtSeamStart, degradedReason: null };
|
|
5229
|
+
}
|
|
5230
|
+
var SCOPE_DEPTH_CAP = 8;
|
|
5231
|
+
var VOID_TAGS2 = /* @__PURE__ */ new Set(["br", "hr", "img", "wbr", "input", "source"]);
|
|
5232
|
+
var TAG_NAME_RE = /^<(\/?)([A-Za-z][A-Za-z0-9]*)/;
|
|
5233
|
+
function tagInfo(tag) {
|
|
5234
|
+
const m = TAG_NAME_RE.exec(tag);
|
|
5235
|
+
const closing = m?.[1] === "/";
|
|
5236
|
+
const name = (m?.[2] ?? "").toLowerCase();
|
|
5237
|
+
const opensScope = !closing && !tag.endsWith("/>") && !VOID_TAGS2.has(name);
|
|
5238
|
+
return { name, closing, opensScope };
|
|
5239
|
+
}
|
|
5240
|
+
function buildRunTree(segments) {
|
|
5241
|
+
const root2 = [];
|
|
5242
|
+
const stack = [];
|
|
5243
|
+
const current = () => stack.length > 0 ? stack[stack.length - 1].children : root2;
|
|
5244
|
+
const unwind = () => {
|
|
5245
|
+
while (stack.length > 0) {
|
|
5246
|
+
const frame = stack.pop();
|
|
5247
|
+
current().push({ type: "atom", text: frame.open }, ...frame.children);
|
|
5248
|
+
}
|
|
5249
|
+
};
|
|
5250
|
+
for (const segment of segments) {
|
|
5251
|
+
if (segment.kind === "tag") {
|
|
5252
|
+
const info = tagInfo(segment.text);
|
|
5253
|
+
if (info.closing) {
|
|
5254
|
+
const top = stack[stack.length - 1];
|
|
5255
|
+
if (top !== void 0 && top.name === info.name) {
|
|
5256
|
+
stack.pop();
|
|
5257
|
+
const parent = current();
|
|
5258
|
+
if (top.suppressed) {
|
|
5259
|
+
parent.push({ type: "atom", text: top.open }, ...top.children, { type: "atom", text: segment.text });
|
|
5260
|
+
} else {
|
|
5261
|
+
parent.push({ type: "scope", open: top.open, close: segment.text, children: top.children });
|
|
5262
|
+
}
|
|
5263
|
+
} else {
|
|
5264
|
+
current().push({ type: "atom", text: segment.text });
|
|
5018
5265
|
}
|
|
5266
|
+
} else if (info.opensScope) {
|
|
5267
|
+
stack.push({ name: info.name, open: segment.text, suppressed: stack.length >= SCOPE_DEPTH_CAP, children: [] });
|
|
5268
|
+
} else {
|
|
5269
|
+
current().push({ type: "atom", text: segment.text });
|
|
5019
5270
|
}
|
|
5271
|
+
continue;
|
|
5272
|
+
}
|
|
5273
|
+
const t = segment.text;
|
|
5274
|
+
let start = 0;
|
|
5275
|
+
for (let i = 0; i < t.length; i++) {
|
|
5276
|
+
const c = t.charCodeAt(i);
|
|
5277
|
+
if (c !== 10 && c !== 13) continue;
|
|
5278
|
+
if (i > start) current().push({ type: "text", text: t.slice(start, i) });
|
|
5279
|
+
const end = c === 13 && t.charCodeAt(i + 1) === 10 ? i + 2 : i + 1;
|
|
5280
|
+
unwind();
|
|
5281
|
+
root2.push({ type: "text", text: t.slice(i, end) });
|
|
5282
|
+
start = end;
|
|
5283
|
+
i = end - 1;
|
|
5284
|
+
}
|
|
5285
|
+
if (start < t.length) current().push({ type: "text", text: t.slice(start) });
|
|
5286
|
+
}
|
|
5287
|
+
unwind();
|
|
5288
|
+
return root2;
|
|
5289
|
+
}
|
|
5290
|
+
var restoreFailureInjector = null;
|
|
5291
|
+
function restore(out, atoms, mask) {
|
|
5292
|
+
if (restoreFailureInjector !== null && restoreFailureInjector(atoms)) return null;
|
|
5293
|
+
let result = "";
|
|
5294
|
+
let k = 0;
|
|
5295
|
+
let last = 0;
|
|
5296
|
+
for (; ; ) {
|
|
5297
|
+
const idx = out.indexOf(mask, last);
|
|
5298
|
+
if (idx === -1) break;
|
|
5299
|
+
if (k >= atoms.length) return null;
|
|
5300
|
+
result += out.slice(last, idx) + atoms[k];
|
|
5301
|
+
k += 1;
|
|
5302
|
+
last = idx + 1;
|
|
5303
|
+
}
|
|
5304
|
+
return result + out.slice(last);
|
|
5305
|
+
}
|
|
5306
|
+
function emitRun(nodes, mask) {
|
|
5307
|
+
let text = "";
|
|
5308
|
+
const atoms = [];
|
|
5309
|
+
for (const node of nodes) {
|
|
5310
|
+
if (node.type === "text") {
|
|
5311
|
+
text += node.text;
|
|
5312
|
+
} else if (node.type === "atom") {
|
|
5313
|
+
atoms.push(node.text);
|
|
5314
|
+
text += mask;
|
|
5315
|
+
} else {
|
|
5316
|
+
const inner = emitRun(node.children, mask);
|
|
5317
|
+
if (inner === null) return null;
|
|
5318
|
+
const transformed = transformRun(inner.text, false, false, false);
|
|
5319
|
+
const restored = restore(transformed.out, inner.atoms, mask);
|
|
5320
|
+
if (restored === null) return null;
|
|
5321
|
+
atoms.push(node.open + restored + node.close);
|
|
5322
|
+
text += mask;
|
|
5020
5323
|
}
|
|
5021
|
-
text = truncateUnclosedLatexBlock(text, unclosedDouble);
|
|
5022
|
-
parts.push(text);
|
|
5023
5324
|
}
|
|
5024
|
-
return {
|
|
5325
|
+
return { text, atoms };
|
|
5326
|
+
}
|
|
5327
|
+
function reportRestoreViolation() {
|
|
5328
|
+
if (false) {
|
|
5329
|
+
console.error(
|
|
5330
|
+
"[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."
|
|
5331
|
+
);
|
|
5332
|
+
}
|
|
5333
|
+
}
|
|
5334
|
+
function processSliceDefault(slice, probe, mask) {
|
|
5335
|
+
const segments = splitByProtectedRegions(slice);
|
|
5336
|
+
const parts = [];
|
|
5337
|
+
let quiescent = true;
|
|
5338
|
+
let truncatedAtSeamStart = false;
|
|
5339
|
+
let offset = 0;
|
|
5340
|
+
let i = 0;
|
|
5341
|
+
while (i < segments.length) {
|
|
5342
|
+
const segment = segments[i];
|
|
5343
|
+
if (isHardBoundary(segment.kind)) {
|
|
5344
|
+
parts.push(segment.text);
|
|
5345
|
+
offset += segment.text.length;
|
|
5346
|
+
i += 1;
|
|
5347
|
+
continue;
|
|
5348
|
+
}
|
|
5349
|
+
const runStart = offset;
|
|
5350
|
+
const runSegments = [];
|
|
5351
|
+
while (i < segments.length && !isHardBoundary(segments[i].kind)) {
|
|
5352
|
+
runSegments.push(segments[i]);
|
|
5353
|
+
offset += segments[i].text.length;
|
|
5354
|
+
i += 1;
|
|
5355
|
+
}
|
|
5356
|
+
const before = runStart === 0 ? -1 : slice.charCodeAt(runStart - 1);
|
|
5357
|
+
const runStartsAtLineStart = before === -1 || before === 10 || before === 13;
|
|
5358
|
+
const seamEligible = runStart === 0;
|
|
5359
|
+
const emitted = emitRun(buildRunTree(runSegments), mask);
|
|
5360
|
+
if (emitted === null) {
|
|
5361
|
+
reportRestoreViolation();
|
|
5362
|
+
return { ...processSliceLegacy(slice, probe), degradedReason: "restore-invariant" };
|
|
5363
|
+
}
|
|
5364
|
+
const r = transformRun(emitted.text, probe, runStartsAtLineStart, seamEligible);
|
|
5365
|
+
const restored = restore(r.out, emitted.atoms, mask);
|
|
5366
|
+
if (restored === null) {
|
|
5367
|
+
reportRestoreViolation();
|
|
5368
|
+
return { ...processSliceLegacy(slice, probe), degradedReason: "restore-invariant" };
|
|
5369
|
+
}
|
|
5370
|
+
if (r.tailSensitive) quiescent = false;
|
|
5371
|
+
if (r.truncatedAtSeamStart) truncatedAtSeamStart = true;
|
|
5372
|
+
parts.push(restored);
|
|
5373
|
+
}
|
|
5374
|
+
return { out: parts.join(""), quiescent, truncatedAtSeamStart, degradedReason: null };
|
|
5375
|
+
}
|
|
5376
|
+
function processSlice(slice, options) {
|
|
5377
|
+
if (options.legacy === true) return processSliceLegacy(slice, options.probe);
|
|
5378
|
+
return processSliceDefault(slice, options.probe, options.mask);
|
|
5025
5379
|
}
|
|
5026
5380
|
function isBlankRawLine(text, from, to) {
|
|
5027
5381
|
for (let i = from; i < to; i++) {
|
|
@@ -5037,7 +5391,7 @@ function findRawSafeCut(active) {
|
|
|
5037
5391
|
let backtickHazard = false;
|
|
5038
5392
|
let latentLt = false;
|
|
5039
5393
|
for (const segment of segments) {
|
|
5040
|
-
if (segment.
|
|
5394
|
+
if (segment.kind !== "text") {
|
|
5041
5395
|
if (segment.text.includes(">")) latentLt = false;
|
|
5042
5396
|
offset += segment.text.length;
|
|
5043
5397
|
continue;
|
|
@@ -5072,12 +5426,28 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5072
5426
|
const freezeThreshold = options?.freezeThreshold ?? DEFAULT_FREEZE_ATTEMPT_THRESHOLD;
|
|
5073
5427
|
const onAttempt = options?.onAttempt;
|
|
5074
5428
|
const backoff = options?.backoff ?? true;
|
|
5429
|
+
const onDegrade = options?.onDegrade;
|
|
5075
5430
|
let prevSource = "";
|
|
5076
5431
|
let prevOutput = "";
|
|
5077
5432
|
let frozenSrcEnd = 0;
|
|
5078
5433
|
let frozenOut = "";
|
|
5079
5434
|
let triggered = false;
|
|
5080
5435
|
let nextAttemptLen = 0;
|
|
5436
|
+
let lineageDegraded = false;
|
|
5437
|
+
const presence = new PuaPresence();
|
|
5438
|
+
const commit = (source, out) => {
|
|
5439
|
+
prevSource = source;
|
|
5440
|
+
prevOutput = out;
|
|
5441
|
+
return out;
|
|
5442
|
+
};
|
|
5443
|
+
const legacyWhole = (source) => processSlice(source, { legacy: true, probe: false }).out;
|
|
5444
|
+
const degrade = (source, reason) => {
|
|
5445
|
+
lineageDegraded = true;
|
|
5446
|
+
frozenSrcEnd = 0;
|
|
5447
|
+
frozenOut = "";
|
|
5448
|
+
onDegrade?.(reason);
|
|
5449
|
+
return commit(source, legacyWhole(source));
|
|
5450
|
+
};
|
|
5081
5451
|
return function incrementalPreprocessLaTeX(source) {
|
|
5082
5452
|
if (source === prevSource) return prevOutput;
|
|
5083
5453
|
const isAppend = source.length > prevSource.length && source.startsWith(prevSource);
|
|
@@ -5086,16 +5456,20 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5086
5456
|
frozenOut = "";
|
|
5087
5457
|
triggered = false;
|
|
5088
5458
|
nextAttemptLen = 0;
|
|
5459
|
+
lineageDegraded = false;
|
|
5460
|
+
presence.reset();
|
|
5461
|
+
presence.add(source, 0);
|
|
5462
|
+
} else {
|
|
5463
|
+
presence.add(source, prevSource.length);
|
|
5089
5464
|
}
|
|
5090
5465
|
if (!triggered) {
|
|
5091
5466
|
const checkFrom = isAppend ? Math.max(0, prevSource.length - 1) : 0;
|
|
5092
|
-
if (!hasLatexTrigger(source.slice(checkFrom)))
|
|
5093
|
-
prevSource = source;
|
|
5094
|
-
prevOutput = source;
|
|
5095
|
-
return source;
|
|
5096
|
-
}
|
|
5467
|
+
if (!hasLatexTrigger(source.slice(checkFrom))) return commit(source, source);
|
|
5097
5468
|
triggered = true;
|
|
5098
5469
|
}
|
|
5470
|
+
if (lineageDegraded) return commit(source, legacyWhole(source));
|
|
5471
|
+
const mask = presence.select();
|
|
5472
|
+
if (mask === null) return degrade(source, "mask-exhausted");
|
|
5099
5473
|
let active = source.slice(frozenSrcEnd);
|
|
5100
5474
|
if (active.length > freezeThreshold && active.length >= nextAttemptLen) {
|
|
5101
5475
|
const activeLength = active.length;
|
|
@@ -5110,18 +5484,20 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5110
5484
|
};
|
|
5111
5485
|
const cut = findRawSafeCut(active);
|
|
5112
5486
|
if (cut > 0) {
|
|
5113
|
-
const candidate = processSlice(active.slice(0, cut));
|
|
5487
|
+
const candidate = processSlice(active.slice(0, cut), { probe: true, mask });
|
|
5488
|
+
if (candidate.degradedReason !== null) {
|
|
5489
|
+
onAttempt?.({ activeLength, frozenBytes: 0 });
|
|
5490
|
+
return degrade(source, candidate.degradedReason);
|
|
5491
|
+
}
|
|
5114
5492
|
if (candidate.quiescent) freeze(cut, candidate);
|
|
5115
5493
|
}
|
|
5116
5494
|
nextAttemptLen = advanced || !backoff ? 0 : active.length * 2;
|
|
5117
5495
|
onAttempt?.({ activeLength, frozenBytes });
|
|
5118
5496
|
}
|
|
5119
|
-
const tail = processSlice(active, false);
|
|
5497
|
+
const tail = processSlice(active, { probe: false, mask });
|
|
5498
|
+
if (tail.degradedReason !== null) return degrade(source, tail.degradedReason);
|
|
5120
5499
|
const head = tail.truncatedAtSeamStart ? frozenOut.replace(/\s+$/, "") : frozenOut;
|
|
5121
|
-
|
|
5122
|
-
prevSource = source;
|
|
5123
|
-
prevOutput = out;
|
|
5124
|
-
return out;
|
|
5500
|
+
return commit(source, head + tail.out);
|
|
5125
5501
|
};
|
|
5126
5502
|
}
|
|
5127
5503
|
|
|
@@ -5146,6 +5522,8 @@ function createRemendPreprocessor(options) {
|
|
|
5146
5522
|
}
|
|
5147
5523
|
export {
|
|
5148
5524
|
DEFAULT_PAYLOAD,
|
|
5525
|
+
ENGINE_PLACEHOLDER_TAGS,
|
|
5526
|
+
ENGINE_PROVENANCE_PROPERTY,
|
|
5149
5527
|
PIPELINE_STAGES,
|
|
5150
5528
|
SENTINEL_FN_CONTENT,
|
|
5151
5529
|
SENTINEL_LINK_URL,
|
|
@@ -5190,7 +5568,9 @@ export {
|
|
|
5190
5568
|
preprocessLaTeX,
|
|
5191
5569
|
rehypeFooterAdorn,
|
|
5192
5570
|
rehypeRebaseHashLinks_default as rehypeRebaseHashLinks,
|
|
5571
|
+
rehypeVerifyEngineTags,
|
|
5193
5572
|
removeComments,
|
|
5573
|
+
resolveCrossChunkReference,
|
|
5194
5574
|
sanitizeCrossChunkUrl,
|
|
5195
5575
|
sanitizeSchema,
|
|
5196
5576
|
shortenDocumentId,
|