@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.cjs
CHANGED
|
@@ -31,6 +31,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var src_exports = {};
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
DEFAULT_PAYLOAD: () => DEFAULT_PAYLOAD,
|
|
34
|
+
ENGINE_PLACEHOLDER_TAGS: () => ENGINE_PLACEHOLDER_TAGS,
|
|
35
|
+
ENGINE_PROVENANCE_PROPERTY: () => ENGINE_PROVENANCE_PROPERTY,
|
|
34
36
|
PIPELINE_STAGES: () => PIPELINE_STAGES,
|
|
35
37
|
SENTINEL_FN_CONTENT: () => SENTINEL_FN_CONTENT,
|
|
36
38
|
SENTINEL_LINK_URL: () => SENTINEL_LINK_URL,
|
|
@@ -75,7 +77,9 @@ __export(src_exports, {
|
|
|
75
77
|
preprocessLaTeX: () => preprocessLaTeX,
|
|
76
78
|
rehypeFooterAdorn: () => rehypeFooterAdorn,
|
|
77
79
|
rehypeRebaseHashLinks: () => rehypeRebaseHashLinks_default,
|
|
80
|
+
rehypeVerifyEngineTags: () => rehypeVerifyEngineTags,
|
|
78
81
|
removeComments: () => removeComments,
|
|
82
|
+
resolveCrossChunkReference: () => resolveCrossChunkReference,
|
|
79
83
|
sanitizeCrossChunkUrl: () => sanitizeCrossChunkUrl,
|
|
80
84
|
sanitizeSchema: () => sanitizeSchema,
|
|
81
85
|
shortenDocumentId: () => shortenDocumentId,
|
|
@@ -2220,6 +2224,38 @@ function normalizeForMatch(s) {
|
|
|
2220
2224
|
return (0, import_micromark_util_normalize_identifier3.normalizeIdentifier)(s);
|
|
2221
2225
|
}
|
|
2222
2226
|
|
|
2227
|
+
// src/components/blankLineScanner.ts
|
|
2228
|
+
function createBlankLineScanner() {
|
|
2229
|
+
let end = 0;
|
|
2230
|
+
let newline = false;
|
|
2231
|
+
let cr = false;
|
|
2232
|
+
return (source, from = 0) => {
|
|
2233
|
+
if (from === 0) {
|
|
2234
|
+
end = 0;
|
|
2235
|
+
newline = false;
|
|
2236
|
+
cr = false;
|
|
2237
|
+
}
|
|
2238
|
+
for (let i = from; i < source.length; i++) {
|
|
2239
|
+
const c = source[i];
|
|
2240
|
+
if (c === "\n") {
|
|
2241
|
+
if (newline) {
|
|
2242
|
+
end = i + 1;
|
|
2243
|
+
newline = false;
|
|
2244
|
+
} else newline = true;
|
|
2245
|
+
cr = false;
|
|
2246
|
+
} else if (newline) {
|
|
2247
|
+
if ((c === " " || c === " ") && !cr) continue;
|
|
2248
|
+
if (c === "\r" && !cr) cr = true;
|
|
2249
|
+
else {
|
|
2250
|
+
newline = false;
|
|
2251
|
+
cr = false;
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
return end;
|
|
2256
|
+
};
|
|
2257
|
+
}
|
|
2258
|
+
|
|
2223
2259
|
// src/components/collectDefLabels.ts
|
|
2224
2260
|
var SCANNER_BOUNDARY_PROFILE = { defListEnabled: false, mathFlow: false, referenceTaint: false };
|
|
2225
2261
|
function buildProcessor() {
|
|
@@ -2251,19 +2287,12 @@ var setsEqual = (a, b) => {
|
|
|
2251
2287
|
for (const v of a) if (!b.has(v)) return false;
|
|
2252
2288
|
return true;
|
|
2253
2289
|
};
|
|
2254
|
-
var BLANK_LINE_RE = /\r?\n[ \t]*\r?\n/g;
|
|
2255
|
-
function lastRegionStart(source) {
|
|
2256
|
-
BLANK_LINE_RE.lastIndex = 0;
|
|
2257
|
-
let start = 0;
|
|
2258
|
-
for (let m = BLANK_LINE_RE.exec(source); m !== null; m = BLANK_LINE_RE.exec(source)) {
|
|
2259
|
-
start = m.index + m[0].length;
|
|
2260
|
-
}
|
|
2261
|
-
return start;
|
|
2262
|
-
}
|
|
2263
2290
|
var DEF_LINE_START_RE = /^[ \t>*+\d.)-]*\[(?:[^\]\\]|\\[\s\S])*\]:/m;
|
|
2264
2291
|
function createDefLabelScanner(parse = collectDefLabels) {
|
|
2265
2292
|
let prevSource = null;
|
|
2266
2293
|
let prevLabels = null;
|
|
2294
|
+
const scanBlankLines = createBlankLineScanner();
|
|
2295
|
+
let regionStart = 0;
|
|
2267
2296
|
let frozenEnd = 0;
|
|
2268
2297
|
let frozenFootnotes = /* @__PURE__ */ new Set();
|
|
2269
2298
|
let frozenLinks = /* @__PURE__ */ new Set();
|
|
@@ -2276,13 +2305,16 @@ function createDefLabelScanner(parse = collectDefLabels) {
|
|
|
2276
2305
|
};
|
|
2277
2306
|
return {
|
|
2278
2307
|
scan(source) {
|
|
2308
|
+
if (source === prevSource && prevLabels !== null) return prevLabels;
|
|
2309
|
+
const previousRegionStart = regionStart;
|
|
2310
|
+
const appended = prevSource !== null && source.startsWith(prevSource);
|
|
2311
|
+
regionStart = scanBlankLines(source, appended ? prevSource.length : 0);
|
|
2279
2312
|
let isAppend = false;
|
|
2280
2313
|
if (prevSource !== null && prevLabels !== null) {
|
|
2281
2314
|
if (source === prevSource) return prevLabels;
|
|
2282
2315
|
if (source.startsWith(prevSource)) {
|
|
2283
2316
|
isAppend = true;
|
|
2284
|
-
const
|
|
2285
|
-
const region = prevSource.slice(regionStart) + source.slice(prevSource.length);
|
|
2317
|
+
const region = source.slice(previousRegionStart);
|
|
2286
2318
|
if (!DEF_LINE_START_RE.test(region)) {
|
|
2287
2319
|
prevSource = source;
|
|
2288
2320
|
return prevLabels;
|
|
@@ -2515,8 +2547,47 @@ function* extractContributions(mdast, options = {}) {
|
|
|
2515
2547
|
for (const c of out) yield c;
|
|
2516
2548
|
}
|
|
2517
2549
|
|
|
2550
|
+
// src/components/registryIndex.ts
|
|
2551
|
+
function buildRegistryIndex(registry) {
|
|
2552
|
+
const index = {
|
|
2553
|
+
footnotes: /* @__PURE__ */ new Map(),
|
|
2554
|
+
links: /* @__PURE__ */ new Map(),
|
|
2555
|
+
numbers: /* @__PURE__ */ new Map(),
|
|
2556
|
+
counts: /* @__PURE__ */ new Map(),
|
|
2557
|
+
occurrences: /* @__PURE__ */ new Map()
|
|
2558
|
+
};
|
|
2559
|
+
for (const sym of registry.chunkOrder) {
|
|
2560
|
+
const data = registry.chunkData.get(sym);
|
|
2561
|
+
if (!data) continue;
|
|
2562
|
+
for (const label of data.defs.keys()) if (!index.footnotes.has(label)) index.footnotes.set(label, sym);
|
|
2563
|
+
for (const label of data.linkDefs.keys()) if (!index.links.has(label)) index.links.set(label, sym);
|
|
2564
|
+
const local = /* @__PURE__ */ new Map();
|
|
2565
|
+
index.occurrences.set(sym, local);
|
|
2566
|
+
for (const ref of data.refs) {
|
|
2567
|
+
if (ref.kind !== "footnote") continue;
|
|
2568
|
+
const label = ref.label;
|
|
2569
|
+
if (!index.numbers.has(label)) index.numbers.set(label, index.numbers.size + 1);
|
|
2570
|
+
const total = (index.counts.get(label) ?? 0) + 1;
|
|
2571
|
+
index.counts.set(label, total);
|
|
2572
|
+
const prior = local.get(label);
|
|
2573
|
+
if (prior) prior.count++;
|
|
2574
|
+
else local.set(label, { start: total, count: 1 });
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
return index;
|
|
2578
|
+
}
|
|
2579
|
+
|
|
2518
2580
|
// src/components/documentRegistry.ts
|
|
2519
2581
|
function createRegistry(onEmpty) {
|
|
2582
|
+
let index;
|
|
2583
|
+
let indexedVersion = -1;
|
|
2584
|
+
const getIndex = () => {
|
|
2585
|
+
if (!index || indexedVersion !== reg.version) {
|
|
2586
|
+
index = buildRegistryIndex(reg);
|
|
2587
|
+
indexedVersion = reg.version;
|
|
2588
|
+
}
|
|
2589
|
+
return index;
|
|
2590
|
+
};
|
|
2520
2591
|
const reg = {
|
|
2521
2592
|
chunkOrder: [],
|
|
2522
2593
|
chunkData: /* @__PURE__ */ new Map(),
|
|
@@ -2668,72 +2739,25 @@ function createRegistry(onEmpty) {
|
|
|
2668
2739
|
};
|
|
2669
2740
|
},
|
|
2670
2741
|
canonicalFootnoteFor(label) {
|
|
2671
|
-
|
|
2672
|
-
for (const sym of this.chunkOrder) {
|
|
2673
|
-
const data = this.chunkData.get(sym);
|
|
2674
|
-
if (data?.defs.has(id)) return sym;
|
|
2675
|
-
}
|
|
2676
|
-
return null;
|
|
2742
|
+
return getIndex().footnotes.get(normalizeId(label)) ?? null;
|
|
2677
2743
|
},
|
|
2678
2744
|
canonicalLinkFor(label) {
|
|
2679
|
-
|
|
2680
|
-
for (const sym of this.chunkOrder) {
|
|
2681
|
-
const data = this.chunkData.get(sym);
|
|
2682
|
-
if (data?.linkDefs.has(id)) return sym;
|
|
2683
|
-
}
|
|
2684
|
-
return null;
|
|
2745
|
+
return getIndex().links.get(normalizeId(label)) ?? null;
|
|
2685
2746
|
},
|
|
2686
2747
|
globalNumber(label) {
|
|
2687
|
-
|
|
2688
|
-
let n = 0;
|
|
2689
|
-
const seen = /* @__PURE__ */ new Set();
|
|
2690
|
-
for (const sym of this.chunkOrder) {
|
|
2691
|
-
const data = this.chunkData.get(sym);
|
|
2692
|
-
if (!data) continue;
|
|
2693
|
-
for (const ref of data.refs) {
|
|
2694
|
-
if (ref.kind !== "footnote") continue;
|
|
2695
|
-
if (!seen.has(ref.label)) {
|
|
2696
|
-
seen.add(ref.label);
|
|
2697
|
-
n++;
|
|
2698
|
-
if (ref.label === id) return n;
|
|
2699
|
-
}
|
|
2700
|
-
}
|
|
2701
|
-
}
|
|
2702
|
-
return null;
|
|
2748
|
+
return getIndex().numbers.get(normalizeId(label)) ?? null;
|
|
2703
2749
|
},
|
|
2704
2750
|
resolveLinkDef(label) {
|
|
2705
|
-
const
|
|
2706
|
-
|
|
2707
|
-
return this.chunkData.get(sym)?.linkDefs.get(
|
|
2751
|
+
const id = normalizeId(label);
|
|
2752
|
+
const sym = getIndex().links.get(id);
|
|
2753
|
+
return sym ? this.chunkData.get(sym)?.linkDefs.get(id) ?? null : null;
|
|
2708
2754
|
},
|
|
2709
2755
|
getRefsForLabel(label) {
|
|
2710
|
-
|
|
2711
|
-
let n = 0;
|
|
2712
|
-
for (const sym of this.chunkOrder) {
|
|
2713
|
-
const data = this.chunkData.get(sym);
|
|
2714
|
-
if (!data) continue;
|
|
2715
|
-
for (const ref of data.refs) {
|
|
2716
|
-
if (ref.kind === "footnote" && ref.label === id) n++;
|
|
2717
|
-
}
|
|
2718
|
-
}
|
|
2719
|
-
return n;
|
|
2756
|
+
return getIndex().counts.get(normalizeId(label)) ?? 0;
|
|
2720
2757
|
},
|
|
2721
2758
|
globalOccurrenceForRef(chunkSym, label, localOccurrence) {
|
|
2722
|
-
const
|
|
2723
|
-
|
|
2724
|
-
for (const sym of this.chunkOrder) {
|
|
2725
|
-
const data = this.chunkData.get(sym);
|
|
2726
|
-
if (!data) continue;
|
|
2727
|
-
let localCount = 0;
|
|
2728
|
-
for (const ref of data.refs) {
|
|
2729
|
-
if (ref.kind !== "footnote") continue;
|
|
2730
|
-
if (ref.label !== id) continue;
|
|
2731
|
-
localCount++;
|
|
2732
|
-
global2++;
|
|
2733
|
-
if (sym === chunkSym && localCount === localOccurrence) return global2;
|
|
2734
|
-
}
|
|
2735
|
-
}
|
|
2736
|
-
return null;
|
|
2759
|
+
const range = getIndex().occurrences.get(chunkSym)?.get(normalizeId(label));
|
|
2760
|
+
return range && Number.isInteger(localOccurrence) && localOccurrence > 0 && localOccurrence <= range.count ? range.start + localOccurrence - 1 : null;
|
|
2737
2761
|
},
|
|
2738
2762
|
_notify() {
|
|
2739
2763
|
this.version++;
|
|
@@ -2790,6 +2814,55 @@ function rehypeUnwrapCrossChunkImages() {
|
|
|
2790
2814
|
|
|
2791
2815
|
// src/components/pluginChain.ts
|
|
2792
2816
|
var import_rehype_sanitize = __toESM(require("rehype-sanitize"), 1);
|
|
2817
|
+
|
|
2818
|
+
// src/components/rehypeVerifyEngineTags.ts
|
|
2819
|
+
var ENGINE_PLACEHOLDER_TAGS = /* @__PURE__ */ new Set([
|
|
2820
|
+
"footnote-sup",
|
|
2821
|
+
"cross-chunk-link",
|
|
2822
|
+
"cross-chunk-image"
|
|
2823
|
+
]);
|
|
2824
|
+
var ENGINE_PROVENANCE_PROPERTY = "engineProvenance";
|
|
2825
|
+
function walk(parent, provenance, ancestors) {
|
|
2826
|
+
const children = parent.children;
|
|
2827
|
+
let i = 0;
|
|
2828
|
+
while (i < children.length) {
|
|
2829
|
+
const node = children[i];
|
|
2830
|
+
if (node.type === "element" && ENGINE_PLACEHOLDER_TAGS.has(node.tagName)) {
|
|
2831
|
+
const props = node.properties ?? {};
|
|
2832
|
+
const stamped = props[ENGINE_PROVENANCE_PROPERTY];
|
|
2833
|
+
const genuine = provenance !== "" && typeof stamped === "string" && stamped === provenance;
|
|
2834
|
+
if (genuine) {
|
|
2835
|
+
delete props[ENGINE_PROVENANCE_PROPERTY];
|
|
2836
|
+
if (ancestors && (node.tagName === "cross-chunk-link" || node.tagName === "cross-chunk-image")) {
|
|
2837
|
+
(node.data ??= {}).referenceAncestors = ancestors.slice();
|
|
2838
|
+
}
|
|
2839
|
+
ancestors?.push(
|
|
2840
|
+
node.tagName === "cross-chunk-link" ? "a" : node.tagName === "cross-chunk-image" ? "img" : node.tagName
|
|
2841
|
+
);
|
|
2842
|
+
walk(node, provenance, ancestors);
|
|
2843
|
+
ancestors?.pop();
|
|
2844
|
+
i += 1;
|
|
2845
|
+
} else {
|
|
2846
|
+
children.splice(i, 1, ...node.children);
|
|
2847
|
+
}
|
|
2848
|
+
continue;
|
|
2849
|
+
}
|
|
2850
|
+
if (node.type === "element") {
|
|
2851
|
+
ancestors?.push(node.tagName);
|
|
2852
|
+
walk(node, provenance, ancestors);
|
|
2853
|
+
ancestors?.pop();
|
|
2854
|
+
}
|
|
2855
|
+
i += 1;
|
|
2856
|
+
}
|
|
2857
|
+
}
|
|
2858
|
+
function rehypeVerifyEngineTags(options) {
|
|
2859
|
+
const provenance = options?.provenance ?? "";
|
|
2860
|
+
return function transformer(tree) {
|
|
2861
|
+
walk(tree, provenance, options?.referenceAncestors ? [] : void 0);
|
|
2862
|
+
};
|
|
2863
|
+
}
|
|
2864
|
+
|
|
2865
|
+
// src/components/pluginChain.ts
|
|
2793
2866
|
var import_remark_breaks = __toESM(require("remark-breaks"), 1);
|
|
2794
2867
|
var import_remark_cjk_friendly = __toESM(require("remark-cjk-friendly"), 1);
|
|
2795
2868
|
var import_remark_cjk_friendly_gfm_strikethrough = __toESM(require("remark-cjk-friendly-gfm-strikethrough"), 1);
|
|
@@ -2806,16 +2879,18 @@ var import_remark_remove_comments = __toESM(require("remark-remove-comments"), 1
|
|
|
2806
2879
|
// src/components/rehypeRebaseHashLinks.ts
|
|
2807
2880
|
var import_unist_util_visit5 = require("unist-util-visit");
|
|
2808
2881
|
var DEFAULT_PREFIX = "user-content-";
|
|
2882
|
+
function rebaseHashHref(href, prefix) {
|
|
2883
|
+
const hashPrefix = "#" + prefix;
|
|
2884
|
+
return href.startsWith("#") && !href.startsWith(hashPrefix) ? hashPrefix + href.slice(1) : href;
|
|
2885
|
+
}
|
|
2809
2886
|
var rehypeRebaseHashLinks = (options) => {
|
|
2810
2887
|
const prefix = options?.prefix ?? DEFAULT_PREFIX;
|
|
2811
|
-
const hashPrefix = "#" + prefix;
|
|
2812
2888
|
return (tree) => {
|
|
2813
2889
|
(0, import_unist_util_visit5.visit)(tree, "element", (node) => {
|
|
2814
2890
|
if (node.tagName !== "a") return;
|
|
2815
2891
|
const href = node.properties?.href;
|
|
2816
2892
|
if (typeof href !== "string" || !href.startsWith("#")) return;
|
|
2817
|
-
|
|
2818
|
-
node.properties.href = hashPrefix + href.slice(1);
|
|
2893
|
+
node.properties.href = rebaseHashHref(href, prefix);
|
|
2819
2894
|
});
|
|
2820
2895
|
};
|
|
2821
2896
|
};
|
|
@@ -2895,10 +2970,21 @@ function buildCoreRemarkPlugins(enginePlugins) {
|
|
|
2895
2970
|
...DISPLAY_OPTIMIZE_CHAIN.filter(([name]) => selected.has(name)).map(([, plugin]) => plugin)
|
|
2896
2971
|
];
|
|
2897
2972
|
}
|
|
2898
|
-
function buildCoreRehypePlugins(sanitizeSchema2, clobberPrefix) {
|
|
2973
|
+
function buildCoreRehypePlugins(sanitizeSchema2, clobberPrefix, options) {
|
|
2899
2974
|
return [
|
|
2900
2975
|
// Allow raw HTML through so rehype-sanitize can handle it.
|
|
2901
2976
|
[import_rehype_raw.default, { passThrough: [] }],
|
|
2977
|
+
// Unwrap forged engine placeholders BEFORE sanitize admits their tag
|
|
2978
|
+
// names. Only when the caller holds a credential (see the option's doc).
|
|
2979
|
+
...options ? [
|
|
2980
|
+
[
|
|
2981
|
+
rehypeVerifyEngineTags,
|
|
2982
|
+
{
|
|
2983
|
+
provenance: options.provenance,
|
|
2984
|
+
...sanitizeSchema2.ancestors?.a || sanitizeSchema2.ancestors?.img ? { referenceAncestors: true } : {}
|
|
2985
|
+
}
|
|
2986
|
+
]
|
|
2987
|
+
] : [],
|
|
2902
2988
|
// Sanitize HTML while allowing <mark> (highlight), KaTeX class names,
|
|
2903
2989
|
// and any extra protocols the caller permitted via the `sanitizeSchema`
|
|
2904
2990
|
// prop. Override `clobberPrefix` with the instance-scoped value — the
|
|
@@ -2938,6 +3024,10 @@ function buildCoreRemarkRehypeOptions(enableDefinitionList) {
|
|
|
2938
3024
|
}
|
|
2939
3025
|
|
|
2940
3026
|
// src/components/customMdastHandlers.ts
|
|
3027
|
+
function provenanceProps(s) {
|
|
3028
|
+
const provenance = s.options.provenance;
|
|
3029
|
+
return typeof provenance === "string" ? { engineProvenance: provenance } : {};
|
|
3030
|
+
}
|
|
2941
3031
|
function localDefProps(s, id) {
|
|
2942
3032
|
const def = s.definitionById.get(id);
|
|
2943
3033
|
if (!def || typeof def.url !== "string" || def.url === SENTINEL_LINK_URL) return {};
|
|
@@ -2968,15 +3058,14 @@ function buildCrossChunkHandlers() {
|
|
|
2968
3058
|
type: "element",
|
|
2969
3059
|
tagName: "cross-chunk-link",
|
|
2970
3060
|
properties: {
|
|
2971
|
-
//
|
|
2972
|
-
//
|
|
2973
|
-
|
|
2974
|
-
// which also preserves source case. Registry lookups normalize
|
|
2975
|
-
// internally, so cross-chunk case-insensitive matching still works.
|
|
3061
|
+
// Display labels decode escapes; registry identifiers must retain
|
|
3062
|
+
// those bytes. Never use the display label as the lookup key.
|
|
3063
|
+
identifier: node.identifier,
|
|
2976
3064
|
label: node.label ?? node.identifier,
|
|
2977
3065
|
referenceType: node.referenceType,
|
|
2978
3066
|
documentId: s.options.documentId,
|
|
2979
|
-
...localDefProps(s, id)
|
|
3067
|
+
...localDefProps(s, id),
|
|
3068
|
+
...provenanceProps(s)
|
|
2980
3069
|
},
|
|
2981
3070
|
children: s.all(node)
|
|
2982
3071
|
};
|
|
@@ -2990,11 +3079,13 @@ function buildCrossChunkHandlers() {
|
|
|
2990
3079
|
type: "element",
|
|
2991
3080
|
tagName: "cross-chunk-image",
|
|
2992
3081
|
properties: {
|
|
3082
|
+
identifier: node.identifier,
|
|
2993
3083
|
label: node.label ?? node.identifier,
|
|
2994
3084
|
referenceType: node.referenceType,
|
|
2995
3085
|
alt: node.alt ?? "",
|
|
2996
3086
|
documentId: s.options.documentId,
|
|
2997
|
-
...localDefProps(s, id)
|
|
3087
|
+
...localDefProps(s, id),
|
|
3088
|
+
...provenanceProps(s)
|
|
2998
3089
|
},
|
|
2999
3090
|
children: []
|
|
3000
3091
|
};
|
|
@@ -3011,7 +3102,8 @@ function buildCrossChunkHandlers() {
|
|
|
3011
3102
|
properties: {
|
|
3012
3103
|
label: node.identifier,
|
|
3013
3104
|
localOccurrence,
|
|
3014
|
-
documentId: s.options.documentId
|
|
3105
|
+
documentId: s.options.documentId,
|
|
3106
|
+
...provenanceProps(s)
|
|
3015
3107
|
},
|
|
3016
3108
|
children: []
|
|
3017
3109
|
};
|
|
@@ -3029,7 +3121,8 @@ function buildCrossChunkHandlers() {
|
|
|
3029
3121
|
// first client frame), where the local synthetic footer is what
|
|
3030
3122
|
// renders, so marks and footer agree (core-render-02).
|
|
3031
3123
|
localNumber: s.footnoteOrder.indexOf(id) + 1,
|
|
3032
|
-
documentId: s.options.documentId
|
|
3124
|
+
documentId: s.options.documentId,
|
|
3125
|
+
...provenanceProps(s)
|
|
3033
3126
|
},
|
|
3034
3127
|
children: []
|
|
3035
3128
|
};
|
|
@@ -4249,8 +4342,8 @@ var sanitizeSchema = deepFreeze(
|
|
|
4249
4342
|
attributes: {
|
|
4250
4343
|
...import_rehype_sanitize2.defaultSchema.attributes,
|
|
4251
4344
|
code: mergeClassNameAllowlist(import_rehype_sanitize2.defaultSchema.attributes?.code, ["math-inline", "math-display"]),
|
|
4252
|
-
"cross-chunk-link": ["label", "referenceType", "documentId", "localUrl", "localTitle"],
|
|
4253
|
-
"cross-chunk-image": ["label", "referenceType", "documentId", "alt", "localUrl", "localTitle"],
|
|
4345
|
+
"cross-chunk-link": ["identifier", "label", "referenceType", "documentId", "localUrl", "localTitle"],
|
|
4346
|
+
"cross-chunk-image": ["identifier", "label", "referenceType", "documentId", "alt", "localUrl", "localTitle"],
|
|
4254
4347
|
"footnote-sup": ["label", "localOccurrence", "localNumber", "documentId"]
|
|
4255
4348
|
},
|
|
4256
4349
|
strip: [.../* @__PURE__ */ new Set([...import_rehype_sanitize2.defaultSchema.strip || [], ...STRIPPED_TAGS])]
|
|
@@ -4286,6 +4379,49 @@ function sanitizeCrossChunkUrl(rawUrl, key, tagName, urlTransform, schema) {
|
|
|
4286
4379
|
return String(transformed);
|
|
4287
4380
|
}
|
|
4288
4381
|
|
|
4382
|
+
// src/components/resolveCrossChunkReference.ts
|
|
4383
|
+
var import_rehype_sanitize3 = __toESM(require("rehype-sanitize"), 1);
|
|
4384
|
+
var import_micromark_util_sanitize_uri3 = require("micromark-util-sanitize-uri");
|
|
4385
|
+
function resolveCrossChunkReference(input, schema, urlTransform, clobberPrefix) {
|
|
4386
|
+
const key = input.tagName === "a" ? "href" : "src";
|
|
4387
|
+
const element = {
|
|
4388
|
+
type: "element",
|
|
4389
|
+
tagName: input.tagName,
|
|
4390
|
+
properties: {
|
|
4391
|
+
[key]: (0, import_micromark_util_sanitize_uri3.normalizeUri)(input.url),
|
|
4392
|
+
...input.tagName === "img" ? { alt: input.alt ?? "" } : {},
|
|
4393
|
+
...input.title !== void 0 ? { title: input.title } : {}
|
|
4394
|
+
},
|
|
4395
|
+
children: input.tagName === "a" ? [{ type: "text", value: "__reference_children__" }] : []
|
|
4396
|
+
};
|
|
4397
|
+
const requiredAncestors = schema.ancestors?.[input.tagName];
|
|
4398
|
+
const recordedAncestors = input.node?.data?.referenceAncestors;
|
|
4399
|
+
let finalSchema = schema;
|
|
4400
|
+
if (requiredAncestors && Array.isArray(recordedAncestors) && requiredAncestors.some((tag) => recordedAncestors.includes(tag))) {
|
|
4401
|
+
const ancestors = { ...schema.ancestors };
|
|
4402
|
+
delete ancestors[input.tagName];
|
|
4403
|
+
finalSchema = { ...schema, ancestors };
|
|
4404
|
+
}
|
|
4405
|
+
const root2 = (0, import_rehype_sanitize3.default)({ ...finalSchema, clobberPrefix })({ type: "root", children: [element] });
|
|
4406
|
+
const node = root2.children[0];
|
|
4407
|
+
if (node?.type !== "element") return { element: null, keepChildren: node?.type === "text" };
|
|
4408
|
+
if (node.tagName === "a" && typeof node.properties.href === "string") {
|
|
4409
|
+
node.properties.href = rebaseHashHref(node.properties.href, clobberPrefix);
|
|
4410
|
+
}
|
|
4411
|
+
node.children = input.node?.children ?? [];
|
|
4412
|
+
if (input.node?.position) node.position = input.node.position;
|
|
4413
|
+
buildTransform({
|
|
4414
|
+
allowedElements: void 0,
|
|
4415
|
+
disallowedElements: void 0,
|
|
4416
|
+
allowElement: void 0,
|
|
4417
|
+
skipHtml: void 0,
|
|
4418
|
+
unwrapDisallowed: void 0,
|
|
4419
|
+
urlTransform
|
|
4420
|
+
})(node, 0, root2);
|
|
4421
|
+
node.children = [];
|
|
4422
|
+
return { element: node, keepChildren: false };
|
|
4423
|
+
}
|
|
4424
|
+
|
|
4289
4425
|
// src/plugins/defs.ts
|
|
4290
4426
|
function getEnginePluginInternals(plugin) {
|
|
4291
4427
|
const candidate = plugin;
|
|
@@ -4490,6 +4626,8 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4490
4626
|
let source = "";
|
|
4491
4627
|
let visibleEnd = 0;
|
|
4492
4628
|
let pending = [];
|
|
4629
|
+
let pendingHead = 0;
|
|
4630
|
+
const pendingCount = () => pending.length - pendingHead;
|
|
4493
4631
|
let tentativeEnd = 0;
|
|
4494
4632
|
let finished = false;
|
|
4495
4633
|
let seam;
|
|
@@ -4534,7 +4672,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4534
4672
|
cancelFrame = void 0;
|
|
4535
4673
|
};
|
|
4536
4674
|
const ensureScheduled = () => {
|
|
4537
|
-
if (disposed || cancelFrame ||
|
|
4675
|
+
if (disposed || cancelFrame || pendingCount() === 0) return;
|
|
4538
4676
|
lastTickAt = now();
|
|
4539
4677
|
credit = 0;
|
|
4540
4678
|
cancelFrame = schedule(tick);
|
|
@@ -4548,31 +4686,38 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4548
4686
|
const params = resolveParams();
|
|
4549
4687
|
let rate;
|
|
4550
4688
|
if (finished && drainDeadlineAt !== void 0) {
|
|
4551
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4689
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, drainDeadlineAt - t));
|
|
4552
4690
|
} else if (gapWindow.length > 0 && lastArrivalAt !== void 0) {
|
|
4553
4691
|
const gaps = gapWindow.map((s) => s.gap).sort((a, b) => a - b);
|
|
4554
4692
|
const intervalQ = gaps[Math.min(gaps.length - 1, Math.floor(gaps.length * INTERVAL_QUANTILE))];
|
|
4555
4693
|
const horizon = Math.max(16, Math.min(params.bufferFactor * intervalQ + HORIZON_PAD_MS, params.maxLagMs));
|
|
4556
4694
|
const deadline = Math.max(lastArrivalAt + horizon, t + DEADLINE_FLOOR_MS);
|
|
4557
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4695
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, deadline - t));
|
|
4558
4696
|
} else {
|
|
4559
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4697
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, params.correctionTauMs));
|
|
4560
4698
|
}
|
|
4561
4699
|
credit += rate * dt / 1e3;
|
|
4562
|
-
const reveal = Math.min(Math.floor(credit),
|
|
4700
|
+
const reveal = Math.min(Math.floor(credit), pendingCount());
|
|
4563
4701
|
if (reveal > 0) {
|
|
4564
|
-
visibleEnd = pending[reveal - 1];
|
|
4565
|
-
|
|
4566
|
-
|
|
4702
|
+
visibleEnd = pending[pendingHead + reveal - 1];
|
|
4703
|
+
pendingHead += reveal;
|
|
4704
|
+
if (pendingHead === pending.length) {
|
|
4705
|
+
pending = [];
|
|
4706
|
+
pendingHead = 0;
|
|
4707
|
+
} else if (pendingHead >= 1024 && pendingHead * 2 >= pending.length) {
|
|
4708
|
+
pending = pending.slice(pendingHead);
|
|
4709
|
+
pendingHead = 0;
|
|
4710
|
+
}
|
|
4711
|
+
credit = pendingCount() > 0 ? credit - reveal : 0;
|
|
4567
4712
|
notify();
|
|
4568
4713
|
}
|
|
4569
|
-
if (!disposed && !cancelFrame &&
|
|
4714
|
+
if (!disposed && !cancelFrame && pendingCount() > 0) cancelFrame = schedule(tick);
|
|
4570
4715
|
};
|
|
4571
4716
|
const resegmentTail = () => {
|
|
4572
|
-
if (seam !== void 0 && seam < source.length && pending[pending.length - 1] === seam) {
|
|
4717
|
+
if (pendingCount() > 0 && seam !== void 0 && seam < source.length && pending[pending.length - 1] === seam) {
|
|
4573
4718
|
pending.pop();
|
|
4574
4719
|
}
|
|
4575
|
-
const from =
|
|
4720
|
+
const from = pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd;
|
|
4576
4721
|
let anchor = from;
|
|
4577
4722
|
if (seam !== void 0 && from <= seam) {
|
|
4578
4723
|
anchor = Math.max(0, from - RESUME_LOOKBACK);
|
|
@@ -4606,6 +4751,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4606
4751
|
visibleEnd = next.length;
|
|
4607
4752
|
tentativeEnd = next.length;
|
|
4608
4753
|
pending = [];
|
|
4754
|
+
pendingHead = 0;
|
|
4609
4755
|
seam = next.length;
|
|
4610
4756
|
credit = 0;
|
|
4611
4757
|
cancelScheduled();
|
|
@@ -4637,7 +4783,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4637
4783
|
if (finished) return;
|
|
4638
4784
|
finished = true;
|
|
4639
4785
|
lastArrivalAt = void 0;
|
|
4640
|
-
if (tentativeEnd > (
|
|
4786
|
+
if (tentativeEnd > (pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd)) {
|
|
4641
4787
|
pending.push(tentativeEnd);
|
|
4642
4788
|
}
|
|
4643
4789
|
const params = resolveParams();
|
|
@@ -4663,10 +4809,11 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4663
4809
|
snap,
|
|
4664
4810
|
flush() {
|
|
4665
4811
|
disposed = false;
|
|
4666
|
-
const target = finished ? source.length :
|
|
4812
|
+
const target = finished ? source.length : pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd;
|
|
4667
4813
|
if (target <= visibleEnd) return;
|
|
4668
4814
|
visibleEnd = target;
|
|
4669
4815
|
pending = [];
|
|
4816
|
+
pendingHead = 0;
|
|
4670
4817
|
credit = 0;
|
|
4671
4818
|
cancelScheduled();
|
|
4672
4819
|
notify();
|
|
@@ -4689,6 +4836,12 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4689
4836
|
};
|
|
4690
4837
|
|
|
4691
4838
|
// src/preprocessors/latex.ts
|
|
4839
|
+
function isHardBoundary(kind) {
|
|
4840
|
+
return kind === "code" || kind === "literal" || kind === "multilineTag";
|
|
4841
|
+
}
|
|
4842
|
+
function hasLineEnding(text) {
|
|
4843
|
+
return text.includes("\n") || text.includes("\r");
|
|
4844
|
+
}
|
|
4692
4845
|
function getRepeatedMarkerLength(content, start, marker) {
|
|
4693
4846
|
let end = start;
|
|
4694
4847
|
while (end < content.length && content[end] === marker) {
|
|
@@ -4756,11 +4909,11 @@ function splitByProtectedRegions(content) {
|
|
|
4756
4909
|
let multilineFenceMarker = null;
|
|
4757
4910
|
let multilineFenceLength = 0;
|
|
4758
4911
|
let multilineFenceIndent = 0;
|
|
4759
|
-
function pushProtected(start, end) {
|
|
4912
|
+
function pushProtected(start, end, kind) {
|
|
4760
4913
|
if (start > lastIndex) {
|
|
4761
|
-
segments.push({ text: content.substring(lastIndex, start)
|
|
4914
|
+
segments.push({ kind: "text", text: content.substring(lastIndex, start) });
|
|
4762
4915
|
}
|
|
4763
|
-
segments.push({ text: content.substring(start, end)
|
|
4916
|
+
segments.push({ kind, text: content.substring(start, end) });
|
|
4764
4917
|
lastIndex = end;
|
|
4765
4918
|
}
|
|
4766
4919
|
let i = 0;
|
|
@@ -4771,7 +4924,7 @@ function splitByProtectedRegions(content) {
|
|
|
4771
4924
|
const runLen = getRepeatedMarkerLength(content, i, multilineFenceMarker);
|
|
4772
4925
|
const closerIndent = lineIndentBefore(content, i);
|
|
4773
4926
|
if (runLen >= multilineFenceLength && closerIndent !== -1 && closerIndent <= multilineFenceIndent + 3 && restOfLineIsBlank(content, i + runLen)) {
|
|
4774
|
-
pushProtected(multilineStart, i + runLen);
|
|
4927
|
+
pushProtected(multilineStart, i + runLen, "code");
|
|
4775
4928
|
multilineStart = -1;
|
|
4776
4929
|
multilineFenceMarker = null;
|
|
4777
4930
|
multilineFenceLength = 0;
|
|
@@ -4798,7 +4951,7 @@ function splitByProtectedRegions(content) {
|
|
|
4798
4951
|
if (char === "`") {
|
|
4799
4952
|
const closeIdx = findClosingBacktickRun(content, i + runLen, runLen);
|
|
4800
4953
|
if (closeIdx !== -1) {
|
|
4801
|
-
pushProtected(i, closeIdx + runLen);
|
|
4954
|
+
pushProtected(i, closeIdx + runLen, "code");
|
|
4802
4955
|
i = closeIdx + runLen;
|
|
4803
4956
|
continue;
|
|
4804
4957
|
}
|
|
@@ -4823,7 +4976,11 @@ function splitByProtectedRegions(content) {
|
|
|
4823
4976
|
endIndex = content.length;
|
|
4824
4977
|
}
|
|
4825
4978
|
}
|
|
4826
|
-
pushProtected(
|
|
4979
|
+
pushProtected(
|
|
4980
|
+
i,
|
|
4981
|
+
endIndex,
|
|
4982
|
+
isOpeningPairedTag ? "literal" : hasLineEnding(content.substring(i, endIndex)) ? "multilineTag" : "tag"
|
|
4983
|
+
);
|
|
4827
4984
|
i = endIndex;
|
|
4828
4985
|
continue;
|
|
4829
4986
|
}
|
|
@@ -4831,10 +4988,10 @@ function splitByProtectedRegions(content) {
|
|
|
4831
4988
|
i += 1;
|
|
4832
4989
|
}
|
|
4833
4990
|
if (multilineStart !== -1) {
|
|
4834
|
-
pushProtected(multilineStart, content.length);
|
|
4991
|
+
pushProtected(multilineStart, content.length, "code");
|
|
4835
4992
|
}
|
|
4836
4993
|
if (lastIndex < content.length) {
|
|
4837
|
-
segments.push({ text: content.substring(lastIndex)
|
|
4994
|
+
segments.push({ kind: "text", text: content.substring(lastIndex) });
|
|
4838
4995
|
}
|
|
4839
4996
|
return segments;
|
|
4840
4997
|
}
|
|
@@ -4988,20 +5145,22 @@ function escapeLatexPipesInUnclosed(text) {
|
|
|
4988
5145
|
const tail = text.substring(unclosedStart + delimLen);
|
|
4989
5146
|
return before + delim + replaceUnescapedPipes(tail);
|
|
4990
5147
|
}
|
|
4991
|
-
function opensMathFlow(text, pos) {
|
|
5148
|
+
function opensMathFlow(text, pos, runStartsAtLineStart) {
|
|
4992
5149
|
let i = pos;
|
|
4993
5150
|
let spaces = 0;
|
|
4994
|
-
while (i > 0
|
|
5151
|
+
while (i > 0) {
|
|
5152
|
+
const prev = text[i - 1];
|
|
5153
|
+
if (prev === "\n" || prev === "\r") return true;
|
|
4995
5154
|
i -= 1;
|
|
4996
5155
|
if (text[i] !== " ") return false;
|
|
4997
5156
|
spaces += 1;
|
|
4998
5157
|
if (spaces > 3) return false;
|
|
4999
5158
|
}
|
|
5000
|
-
return
|
|
5159
|
+
return runStartsAtLineStart;
|
|
5001
5160
|
}
|
|
5002
|
-
function truncateUnclosedLatexBlock(text, unclosedStart = findUnclosedDelimiterStart(text, "double-only")) {
|
|
5161
|
+
function truncateUnclosedLatexBlock(text, runStartsAtLineStart, unclosedStart = findUnclosedDelimiterStart(text, "double-only")) {
|
|
5003
5162
|
if (unclosedStart === -1) return text;
|
|
5004
|
-
if (!opensMathFlow(text, unclosedStart)) return text;
|
|
5163
|
+
if (!opensMathFlow(text, unclosedStart, runStartsAtLineStart)) return text;
|
|
5005
5164
|
return text.substring(0, unclosedStart).trimEnd();
|
|
5006
5165
|
}
|
|
5007
5166
|
function escapeTextUnderscores(text) {
|
|
@@ -5046,7 +5205,8 @@ function convertSingleToDoubleDollar(text) {
|
|
|
5046
5205
|
}
|
|
5047
5206
|
function preprocessLaTeX(str) {
|
|
5048
5207
|
if (!hasLatexTrigger(str)) return str;
|
|
5049
|
-
|
|
5208
|
+
const mask = selectMask(str);
|
|
5209
|
+
return (mask === null ? processSlice(str, { legacy: true, probe: false }) : processSlice(str, { probe: false, mask })).out;
|
|
5050
5210
|
}
|
|
5051
5211
|
function hasLatexTrigger(str) {
|
|
5052
5212
|
return str.includes("$") || str.includes("\\[") || str.includes("\\(");
|
|
@@ -5075,42 +5235,240 @@ function hasUnclosedTextCommand(text) {
|
|
|
5075
5235
|
}
|
|
5076
5236
|
var RESIDUAL_OPEN_BRACKET_RE = /(?<!!)\\\[/;
|
|
5077
5237
|
var LEADING_DOUBLE_DOLLAR_RE = /^\s*\$\$/;
|
|
5078
|
-
|
|
5238
|
+
var PUA_START = 57344;
|
|
5239
|
+
var PUA_END = 63743;
|
|
5240
|
+
var PUA_SIZE = PUA_END - PUA_START + 1;
|
|
5241
|
+
function selectMask(source) {
|
|
5242
|
+
const first = String.fromCharCode(PUA_START);
|
|
5243
|
+
if (source.indexOf(first) === -1) return first;
|
|
5244
|
+
const seen = new Uint8Array(PUA_SIZE);
|
|
5245
|
+
for (let i = 0; i < source.length; i++) {
|
|
5246
|
+
const c = source.charCodeAt(i);
|
|
5247
|
+
if (c >= PUA_START && c <= PUA_END) seen[c - PUA_START] = 1;
|
|
5248
|
+
}
|
|
5249
|
+
for (let k = 0; k < PUA_SIZE; k++) if (seen[k] === 0) return String.fromCharCode(PUA_START + k);
|
|
5250
|
+
return null;
|
|
5251
|
+
}
|
|
5252
|
+
var PuaPresence = class {
|
|
5253
|
+
bits = new Uint8Array(PUA_SIZE);
|
|
5254
|
+
distinct = 0;
|
|
5255
|
+
reset() {
|
|
5256
|
+
this.bits.fill(0);
|
|
5257
|
+
this.distinct = 0;
|
|
5258
|
+
}
|
|
5259
|
+
add(text, from) {
|
|
5260
|
+
for (let i = from; i < text.length; i++) {
|
|
5261
|
+
const c = text.charCodeAt(i);
|
|
5262
|
+
if (c >= PUA_START && c <= PUA_END) {
|
|
5263
|
+
const k = c - PUA_START;
|
|
5264
|
+
if (this.bits[k] === 0) {
|
|
5265
|
+
this.bits[k] = 1;
|
|
5266
|
+
this.distinct += 1;
|
|
5267
|
+
}
|
|
5268
|
+
}
|
|
5269
|
+
}
|
|
5270
|
+
}
|
|
5271
|
+
select() {
|
|
5272
|
+
if (this.distinct === 0) return String.fromCharCode(PUA_START);
|
|
5273
|
+
if (this.distinct >= PUA_SIZE) return null;
|
|
5274
|
+
for (let k = 0; k < PUA_SIZE; k++) if (this.bits[k] === 0) return String.fromCharCode(PUA_START + k);
|
|
5275
|
+
return null;
|
|
5276
|
+
}
|
|
5277
|
+
};
|
|
5278
|
+
function transformRun(input, probe, runStartsAtLineStart, seamEligible) {
|
|
5279
|
+
let text = input;
|
|
5280
|
+
let tailSensitive = false;
|
|
5281
|
+
let truncatedAtSeamStart = false;
|
|
5282
|
+
text = escapeMhchemCommands(text);
|
|
5283
|
+
text = escapeCurrencyDollarSigns(text);
|
|
5284
|
+
text = convertLatexDelimiters(text);
|
|
5285
|
+
if (probe && RESIDUAL_OPEN_BRACKET_RE.test(text)) tailSensitive = true;
|
|
5286
|
+
text = escapeLatexPipes(text);
|
|
5287
|
+
if (probe && findUnclosedDelimiterStart(text, "both") !== -1) tailSensitive = true;
|
|
5288
|
+
text = escapeLatexPipesInUnclosed(text);
|
|
5289
|
+
if (probe && hasUnclosedTextCommand(text)) tailSensitive = true;
|
|
5290
|
+
text = escapeTextUnderscores(text);
|
|
5291
|
+
text = convertSingleToDoubleDollar(text);
|
|
5292
|
+
let unclosedDouble;
|
|
5293
|
+
if (probe || seamEligible && LEADING_DOUBLE_DOLLAR_RE.test(text)) {
|
|
5294
|
+
unclosedDouble = findUnclosedDelimiterStart(text, "double-only");
|
|
5295
|
+
if (unclosedDouble !== -1) {
|
|
5296
|
+
tailSensitive = true;
|
|
5297
|
+
if (seamEligible && opensMathFlow(text, unclosedDouble, runStartsAtLineStart) && text.slice(0, unclosedDouble).trim() === "") {
|
|
5298
|
+
truncatedAtSeamStart = true;
|
|
5299
|
+
}
|
|
5300
|
+
}
|
|
5301
|
+
}
|
|
5302
|
+
text = truncateUnclosedLatexBlock(text, runStartsAtLineStart, unclosedDouble);
|
|
5303
|
+
return { out: text, tailSensitive, truncatedAtSeamStart };
|
|
5304
|
+
}
|
|
5305
|
+
function processSliceLegacy(slice, probe) {
|
|
5079
5306
|
const segments = splitByProtectedRegions(slice);
|
|
5080
5307
|
const parts = [];
|
|
5081
5308
|
let quiescent = true;
|
|
5082
5309
|
let truncatedAtSeamStart = false;
|
|
5083
5310
|
for (let index = 0; index < segments.length; index++) {
|
|
5084
5311
|
const segment = segments[index];
|
|
5085
|
-
if (segment.
|
|
5312
|
+
if (segment.kind !== "text") {
|
|
5086
5313
|
parts.push(segment.text);
|
|
5087
5314
|
continue;
|
|
5088
5315
|
}
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5316
|
+
const r = transformRun(segment.text, probe, true, index === 0);
|
|
5317
|
+
if (r.tailSensitive) quiescent = false;
|
|
5318
|
+
if (r.truncatedAtSeamStart) truncatedAtSeamStart = true;
|
|
5319
|
+
parts.push(r.out);
|
|
5320
|
+
}
|
|
5321
|
+
return { out: parts.join(""), quiescent, truncatedAtSeamStart, degradedReason: null };
|
|
5322
|
+
}
|
|
5323
|
+
var SCOPE_DEPTH_CAP = 8;
|
|
5324
|
+
var VOID_TAGS2 = /* @__PURE__ */ new Set(["br", "hr", "img", "wbr", "input", "source"]);
|
|
5325
|
+
var TAG_NAME_RE = /^<(\/?)([A-Za-z][A-Za-z0-9]*)/;
|
|
5326
|
+
function tagInfo(tag) {
|
|
5327
|
+
const m = TAG_NAME_RE.exec(tag);
|
|
5328
|
+
const closing = m?.[1] === "/";
|
|
5329
|
+
const name = (m?.[2] ?? "").toLowerCase();
|
|
5330
|
+
const opensScope = !closing && !tag.endsWith("/>") && !VOID_TAGS2.has(name);
|
|
5331
|
+
return { name, closing, opensScope };
|
|
5332
|
+
}
|
|
5333
|
+
function buildRunTree(segments) {
|
|
5334
|
+
const root2 = [];
|
|
5335
|
+
const stack = [];
|
|
5336
|
+
const current = () => stack.length > 0 ? stack[stack.length - 1].children : root2;
|
|
5337
|
+
const unwind = () => {
|
|
5338
|
+
while (stack.length > 0) {
|
|
5339
|
+
const frame = stack.pop();
|
|
5340
|
+
current().push({ type: "atom", text: frame.open }, ...frame.children);
|
|
5341
|
+
}
|
|
5342
|
+
};
|
|
5343
|
+
for (const segment of segments) {
|
|
5344
|
+
if (segment.kind === "tag") {
|
|
5345
|
+
const info = tagInfo(segment.text);
|
|
5346
|
+
if (info.closing) {
|
|
5347
|
+
const top = stack[stack.length - 1];
|
|
5348
|
+
if (top !== void 0 && top.name === info.name) {
|
|
5349
|
+
stack.pop();
|
|
5350
|
+
const parent = current();
|
|
5351
|
+
if (top.suppressed) {
|
|
5352
|
+
parent.push({ type: "atom", text: top.open }, ...top.children, { type: "atom", text: segment.text });
|
|
5353
|
+
} else {
|
|
5354
|
+
parent.push({ type: "scope", open: top.open, close: segment.text, children: top.children });
|
|
5355
|
+
}
|
|
5356
|
+
} else {
|
|
5357
|
+
current().push({ type: "atom", text: segment.text });
|
|
5107
5358
|
}
|
|
5359
|
+
} else if (info.opensScope) {
|
|
5360
|
+
stack.push({ name: info.name, open: segment.text, suppressed: stack.length >= SCOPE_DEPTH_CAP, children: [] });
|
|
5361
|
+
} else {
|
|
5362
|
+
current().push({ type: "atom", text: segment.text });
|
|
5108
5363
|
}
|
|
5364
|
+
continue;
|
|
5365
|
+
}
|
|
5366
|
+
const t = segment.text;
|
|
5367
|
+
let start = 0;
|
|
5368
|
+
for (let i = 0; i < t.length; i++) {
|
|
5369
|
+
const c = t.charCodeAt(i);
|
|
5370
|
+
if (c !== 10 && c !== 13) continue;
|
|
5371
|
+
if (i > start) current().push({ type: "text", text: t.slice(start, i) });
|
|
5372
|
+
const end = c === 13 && t.charCodeAt(i + 1) === 10 ? i + 2 : i + 1;
|
|
5373
|
+
unwind();
|
|
5374
|
+
root2.push({ type: "text", text: t.slice(i, end) });
|
|
5375
|
+
start = end;
|
|
5376
|
+
i = end - 1;
|
|
5377
|
+
}
|
|
5378
|
+
if (start < t.length) current().push({ type: "text", text: t.slice(start) });
|
|
5379
|
+
}
|
|
5380
|
+
unwind();
|
|
5381
|
+
return root2;
|
|
5382
|
+
}
|
|
5383
|
+
var restoreFailureInjector = null;
|
|
5384
|
+
function restore(out, atoms, mask) {
|
|
5385
|
+
if (restoreFailureInjector !== null && restoreFailureInjector(atoms)) return null;
|
|
5386
|
+
let result = "";
|
|
5387
|
+
let k = 0;
|
|
5388
|
+
let last = 0;
|
|
5389
|
+
for (; ; ) {
|
|
5390
|
+
const idx = out.indexOf(mask, last);
|
|
5391
|
+
if (idx === -1) break;
|
|
5392
|
+
if (k >= atoms.length) return null;
|
|
5393
|
+
result += out.slice(last, idx) + atoms[k];
|
|
5394
|
+
k += 1;
|
|
5395
|
+
last = idx + 1;
|
|
5396
|
+
}
|
|
5397
|
+
return result + out.slice(last);
|
|
5398
|
+
}
|
|
5399
|
+
function emitRun(nodes, mask) {
|
|
5400
|
+
let text = "";
|
|
5401
|
+
const atoms = [];
|
|
5402
|
+
for (const node of nodes) {
|
|
5403
|
+
if (node.type === "text") {
|
|
5404
|
+
text += node.text;
|
|
5405
|
+
} else if (node.type === "atom") {
|
|
5406
|
+
atoms.push(node.text);
|
|
5407
|
+
text += mask;
|
|
5408
|
+
} else {
|
|
5409
|
+
const inner = emitRun(node.children, mask);
|
|
5410
|
+
if (inner === null) return null;
|
|
5411
|
+
const transformed = transformRun(inner.text, false, false, false);
|
|
5412
|
+
const restored = restore(transformed.out, inner.atoms, mask);
|
|
5413
|
+
if (restored === null) return null;
|
|
5414
|
+
atoms.push(node.open + restored + node.close);
|
|
5415
|
+
text += mask;
|
|
5109
5416
|
}
|
|
5110
|
-
text = truncateUnclosedLatexBlock(text, unclosedDouble);
|
|
5111
|
-
parts.push(text);
|
|
5112
5417
|
}
|
|
5113
|
-
return {
|
|
5418
|
+
return { text, atoms };
|
|
5419
|
+
}
|
|
5420
|
+
function reportRestoreViolation() {
|
|
5421
|
+
if (false) {
|
|
5422
|
+
console.error(
|
|
5423
|
+
"[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."
|
|
5424
|
+
);
|
|
5425
|
+
}
|
|
5426
|
+
}
|
|
5427
|
+
function processSliceDefault(slice, probe, mask) {
|
|
5428
|
+
const segments = splitByProtectedRegions(slice);
|
|
5429
|
+
const parts = [];
|
|
5430
|
+
let quiescent = true;
|
|
5431
|
+
let truncatedAtSeamStart = false;
|
|
5432
|
+
let offset = 0;
|
|
5433
|
+
let i = 0;
|
|
5434
|
+
while (i < segments.length) {
|
|
5435
|
+
const segment = segments[i];
|
|
5436
|
+
if (isHardBoundary(segment.kind)) {
|
|
5437
|
+
parts.push(segment.text);
|
|
5438
|
+
offset += segment.text.length;
|
|
5439
|
+
i += 1;
|
|
5440
|
+
continue;
|
|
5441
|
+
}
|
|
5442
|
+
const runStart = offset;
|
|
5443
|
+
const runSegments = [];
|
|
5444
|
+
while (i < segments.length && !isHardBoundary(segments[i].kind)) {
|
|
5445
|
+
runSegments.push(segments[i]);
|
|
5446
|
+
offset += segments[i].text.length;
|
|
5447
|
+
i += 1;
|
|
5448
|
+
}
|
|
5449
|
+
const before = runStart === 0 ? -1 : slice.charCodeAt(runStart - 1);
|
|
5450
|
+
const runStartsAtLineStart = before === -1 || before === 10 || before === 13;
|
|
5451
|
+
const seamEligible = runStart === 0;
|
|
5452
|
+
const emitted = emitRun(buildRunTree(runSegments), mask);
|
|
5453
|
+
if (emitted === null) {
|
|
5454
|
+
reportRestoreViolation();
|
|
5455
|
+
return { ...processSliceLegacy(slice, probe), degradedReason: "restore-invariant" };
|
|
5456
|
+
}
|
|
5457
|
+
const r = transformRun(emitted.text, probe, runStartsAtLineStart, seamEligible);
|
|
5458
|
+
const restored = restore(r.out, emitted.atoms, mask);
|
|
5459
|
+
if (restored === null) {
|
|
5460
|
+
reportRestoreViolation();
|
|
5461
|
+
return { ...processSliceLegacy(slice, probe), degradedReason: "restore-invariant" };
|
|
5462
|
+
}
|
|
5463
|
+
if (r.tailSensitive) quiescent = false;
|
|
5464
|
+
if (r.truncatedAtSeamStart) truncatedAtSeamStart = true;
|
|
5465
|
+
parts.push(restored);
|
|
5466
|
+
}
|
|
5467
|
+
return { out: parts.join(""), quiescent, truncatedAtSeamStart, degradedReason: null };
|
|
5468
|
+
}
|
|
5469
|
+
function processSlice(slice, options) {
|
|
5470
|
+
if (options.legacy === true) return processSliceLegacy(slice, options.probe);
|
|
5471
|
+
return processSliceDefault(slice, options.probe, options.mask);
|
|
5114
5472
|
}
|
|
5115
5473
|
function isBlankRawLine(text, from, to) {
|
|
5116
5474
|
for (let i = from; i < to; i++) {
|
|
@@ -5126,7 +5484,7 @@ function findRawSafeCut(active) {
|
|
|
5126
5484
|
let backtickHazard = false;
|
|
5127
5485
|
let latentLt = false;
|
|
5128
5486
|
for (const segment of segments) {
|
|
5129
|
-
if (segment.
|
|
5487
|
+
if (segment.kind !== "text") {
|
|
5130
5488
|
if (segment.text.includes(">")) latentLt = false;
|
|
5131
5489
|
offset += segment.text.length;
|
|
5132
5490
|
continue;
|
|
@@ -5161,12 +5519,28 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5161
5519
|
const freezeThreshold = options?.freezeThreshold ?? DEFAULT_FREEZE_ATTEMPT_THRESHOLD;
|
|
5162
5520
|
const onAttempt = options?.onAttempt;
|
|
5163
5521
|
const backoff = options?.backoff ?? true;
|
|
5522
|
+
const onDegrade = options?.onDegrade;
|
|
5164
5523
|
let prevSource = "";
|
|
5165
5524
|
let prevOutput = "";
|
|
5166
5525
|
let frozenSrcEnd = 0;
|
|
5167
5526
|
let frozenOut = "";
|
|
5168
5527
|
let triggered = false;
|
|
5169
5528
|
let nextAttemptLen = 0;
|
|
5529
|
+
let lineageDegraded = false;
|
|
5530
|
+
const presence = new PuaPresence();
|
|
5531
|
+
const commit = (source, out) => {
|
|
5532
|
+
prevSource = source;
|
|
5533
|
+
prevOutput = out;
|
|
5534
|
+
return out;
|
|
5535
|
+
};
|
|
5536
|
+
const legacyWhole = (source) => processSlice(source, { legacy: true, probe: false }).out;
|
|
5537
|
+
const degrade = (source, reason) => {
|
|
5538
|
+
lineageDegraded = true;
|
|
5539
|
+
frozenSrcEnd = 0;
|
|
5540
|
+
frozenOut = "";
|
|
5541
|
+
onDegrade?.(reason);
|
|
5542
|
+
return commit(source, legacyWhole(source));
|
|
5543
|
+
};
|
|
5170
5544
|
return function incrementalPreprocessLaTeX(source) {
|
|
5171
5545
|
if (source === prevSource) return prevOutput;
|
|
5172
5546
|
const isAppend = source.length > prevSource.length && source.startsWith(prevSource);
|
|
@@ -5175,16 +5549,20 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5175
5549
|
frozenOut = "";
|
|
5176
5550
|
triggered = false;
|
|
5177
5551
|
nextAttemptLen = 0;
|
|
5552
|
+
lineageDegraded = false;
|
|
5553
|
+
presence.reset();
|
|
5554
|
+
presence.add(source, 0);
|
|
5555
|
+
} else {
|
|
5556
|
+
presence.add(source, prevSource.length);
|
|
5178
5557
|
}
|
|
5179
5558
|
if (!triggered) {
|
|
5180
5559
|
const checkFrom = isAppend ? Math.max(0, prevSource.length - 1) : 0;
|
|
5181
|
-
if (!hasLatexTrigger(source.slice(checkFrom)))
|
|
5182
|
-
prevSource = source;
|
|
5183
|
-
prevOutput = source;
|
|
5184
|
-
return source;
|
|
5185
|
-
}
|
|
5560
|
+
if (!hasLatexTrigger(source.slice(checkFrom))) return commit(source, source);
|
|
5186
5561
|
triggered = true;
|
|
5187
5562
|
}
|
|
5563
|
+
if (lineageDegraded) return commit(source, legacyWhole(source));
|
|
5564
|
+
const mask = presence.select();
|
|
5565
|
+
if (mask === null) return degrade(source, "mask-exhausted");
|
|
5188
5566
|
let active = source.slice(frozenSrcEnd);
|
|
5189
5567
|
if (active.length > freezeThreshold && active.length >= nextAttemptLen) {
|
|
5190
5568
|
const activeLength = active.length;
|
|
@@ -5199,18 +5577,20 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5199
5577
|
};
|
|
5200
5578
|
const cut = findRawSafeCut(active);
|
|
5201
5579
|
if (cut > 0) {
|
|
5202
|
-
const candidate = processSlice(active.slice(0, cut));
|
|
5580
|
+
const candidate = processSlice(active.slice(0, cut), { probe: true, mask });
|
|
5581
|
+
if (candidate.degradedReason !== null) {
|
|
5582
|
+
onAttempt?.({ activeLength, frozenBytes: 0 });
|
|
5583
|
+
return degrade(source, candidate.degradedReason);
|
|
5584
|
+
}
|
|
5203
5585
|
if (candidate.quiescent) freeze(cut, candidate);
|
|
5204
5586
|
}
|
|
5205
5587
|
nextAttemptLen = advanced || !backoff ? 0 : active.length * 2;
|
|
5206
5588
|
onAttempt?.({ activeLength, frozenBytes });
|
|
5207
5589
|
}
|
|
5208
|
-
const tail = processSlice(active, false);
|
|
5590
|
+
const tail = processSlice(active, { probe: false, mask });
|
|
5591
|
+
if (tail.degradedReason !== null) return degrade(source, tail.degradedReason);
|
|
5209
5592
|
const head = tail.truncatedAtSeamStart ? frozenOut.replace(/\s+$/, "") : frozenOut;
|
|
5210
|
-
|
|
5211
|
-
prevSource = source;
|
|
5212
|
-
prevOutput = out;
|
|
5213
|
-
return out;
|
|
5593
|
+
return commit(source, head + tail.out);
|
|
5214
5594
|
};
|
|
5215
5595
|
}
|
|
5216
5596
|
|
|
@@ -5236,6 +5616,8 @@ function createRemendPreprocessor(options) {
|
|
|
5236
5616
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5237
5617
|
0 && (module.exports = {
|
|
5238
5618
|
DEFAULT_PAYLOAD,
|
|
5619
|
+
ENGINE_PLACEHOLDER_TAGS,
|
|
5620
|
+
ENGINE_PROVENANCE_PROPERTY,
|
|
5239
5621
|
PIPELINE_STAGES,
|
|
5240
5622
|
SENTINEL_FN_CONTENT,
|
|
5241
5623
|
SENTINEL_LINK_URL,
|
|
@@ -5280,7 +5662,9 @@ function createRemendPreprocessor(options) {
|
|
|
5280
5662
|
preprocessLaTeX,
|
|
5281
5663
|
rehypeFooterAdorn,
|
|
5282
5664
|
rehypeRebaseHashLinks,
|
|
5665
|
+
rehypeVerifyEngineTags,
|
|
5283
5666
|
removeComments,
|
|
5667
|
+
resolveCrossChunkReference,
|
|
5284
5668
|
sanitizeCrossChunkUrl,
|
|
5285
5669
|
sanitizeSchema,
|
|
5286
5670
|
shortenDocumentId,
|