@ai-react-markdown/engine 2.10.1 → 2.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +528 -144
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +113 -2
- package/dist/index.d.ts +113 -2
- package/dist/index.dev.cjs +528 -144
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +524 -144
- package/dist/index.dev.js.map +1 -1
- package/dist/index.js +524 -144
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/dist/index.dev.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,
|
|
@@ -2227,6 +2231,38 @@ function normalizeForMatch(s) {
|
|
|
2227
2231
|
return (0, import_micromark_util_normalize_identifier3.normalizeIdentifier)(s);
|
|
2228
2232
|
}
|
|
2229
2233
|
|
|
2234
|
+
// src/components/blankLineScanner.ts
|
|
2235
|
+
function createBlankLineScanner() {
|
|
2236
|
+
let end = 0;
|
|
2237
|
+
let newline = false;
|
|
2238
|
+
let cr = false;
|
|
2239
|
+
return (source, from = 0) => {
|
|
2240
|
+
if (from === 0) {
|
|
2241
|
+
end = 0;
|
|
2242
|
+
newline = false;
|
|
2243
|
+
cr = false;
|
|
2244
|
+
}
|
|
2245
|
+
for (let i = from; i < source.length; i++) {
|
|
2246
|
+
const c = source[i];
|
|
2247
|
+
if (c === "\n") {
|
|
2248
|
+
if (newline) {
|
|
2249
|
+
end = i + 1;
|
|
2250
|
+
newline = false;
|
|
2251
|
+
} else newline = true;
|
|
2252
|
+
cr = false;
|
|
2253
|
+
} else if (newline) {
|
|
2254
|
+
if ((c === " " || c === " ") && !cr) continue;
|
|
2255
|
+
if (c === "\r" && !cr) cr = true;
|
|
2256
|
+
else {
|
|
2257
|
+
newline = false;
|
|
2258
|
+
cr = false;
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2262
|
+
return end;
|
|
2263
|
+
};
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2230
2266
|
// src/components/collectDefLabels.ts
|
|
2231
2267
|
var SCANNER_BOUNDARY_PROFILE = { defListEnabled: false, mathFlow: false, referenceTaint: false };
|
|
2232
2268
|
function buildProcessor() {
|
|
@@ -2258,19 +2294,12 @@ var setsEqual = (a, b) => {
|
|
|
2258
2294
|
for (const v of a) if (!b.has(v)) return false;
|
|
2259
2295
|
return true;
|
|
2260
2296
|
};
|
|
2261
|
-
var BLANK_LINE_RE = /\r?\n[ \t]*\r?\n/g;
|
|
2262
|
-
function lastRegionStart(source) {
|
|
2263
|
-
BLANK_LINE_RE.lastIndex = 0;
|
|
2264
|
-
let start = 0;
|
|
2265
|
-
for (let m = BLANK_LINE_RE.exec(source); m !== null; m = BLANK_LINE_RE.exec(source)) {
|
|
2266
|
-
start = m.index + m[0].length;
|
|
2267
|
-
}
|
|
2268
|
-
return start;
|
|
2269
|
-
}
|
|
2270
2297
|
var DEF_LINE_START_RE = /^[ \t>*+\d.)-]*\[(?:[^\]\\]|\\[\s\S])*\]:/m;
|
|
2271
2298
|
function createDefLabelScanner(parse = collectDefLabels) {
|
|
2272
2299
|
let prevSource = null;
|
|
2273
2300
|
let prevLabels = null;
|
|
2301
|
+
const scanBlankLines = createBlankLineScanner();
|
|
2302
|
+
let regionStart = 0;
|
|
2274
2303
|
let frozenEnd = 0;
|
|
2275
2304
|
let frozenFootnotes = /* @__PURE__ */ new Set();
|
|
2276
2305
|
let frozenLinks = /* @__PURE__ */ new Set();
|
|
@@ -2283,13 +2312,16 @@ function createDefLabelScanner(parse = collectDefLabels) {
|
|
|
2283
2312
|
};
|
|
2284
2313
|
return {
|
|
2285
2314
|
scan(source) {
|
|
2315
|
+
if (source === prevSource && prevLabels !== null) return prevLabels;
|
|
2316
|
+
const previousRegionStart = regionStart;
|
|
2317
|
+
const appended = prevSource !== null && source.startsWith(prevSource);
|
|
2318
|
+
regionStart = scanBlankLines(source, appended ? prevSource.length : 0);
|
|
2286
2319
|
let isAppend = false;
|
|
2287
2320
|
if (prevSource !== null && prevLabels !== null) {
|
|
2288
2321
|
if (source === prevSource) return prevLabels;
|
|
2289
2322
|
if (source.startsWith(prevSource)) {
|
|
2290
2323
|
isAppend = true;
|
|
2291
|
-
const
|
|
2292
|
-
const region = prevSource.slice(regionStart) + source.slice(prevSource.length);
|
|
2324
|
+
const region = source.slice(previousRegionStart);
|
|
2293
2325
|
if (!DEF_LINE_START_RE.test(region)) {
|
|
2294
2326
|
prevSource = source;
|
|
2295
2327
|
return prevLabels;
|
|
@@ -2522,8 +2554,47 @@ function* extractContributions(mdast, options = {}) {
|
|
|
2522
2554
|
for (const c of out) yield c;
|
|
2523
2555
|
}
|
|
2524
2556
|
|
|
2557
|
+
// src/components/registryIndex.ts
|
|
2558
|
+
function buildRegistryIndex(registry) {
|
|
2559
|
+
const index = {
|
|
2560
|
+
footnotes: /* @__PURE__ */ new Map(),
|
|
2561
|
+
links: /* @__PURE__ */ new Map(),
|
|
2562
|
+
numbers: /* @__PURE__ */ new Map(),
|
|
2563
|
+
counts: /* @__PURE__ */ new Map(),
|
|
2564
|
+
occurrences: /* @__PURE__ */ new Map()
|
|
2565
|
+
};
|
|
2566
|
+
for (const sym of registry.chunkOrder) {
|
|
2567
|
+
const data = registry.chunkData.get(sym);
|
|
2568
|
+
if (!data) continue;
|
|
2569
|
+
for (const label of data.defs.keys()) if (!index.footnotes.has(label)) index.footnotes.set(label, sym);
|
|
2570
|
+
for (const label of data.linkDefs.keys()) if (!index.links.has(label)) index.links.set(label, sym);
|
|
2571
|
+
const local = /* @__PURE__ */ new Map();
|
|
2572
|
+
index.occurrences.set(sym, local);
|
|
2573
|
+
for (const ref of data.refs) {
|
|
2574
|
+
if (ref.kind !== "footnote") continue;
|
|
2575
|
+
const label = ref.label;
|
|
2576
|
+
if (!index.numbers.has(label)) index.numbers.set(label, index.numbers.size + 1);
|
|
2577
|
+
const total = (index.counts.get(label) ?? 0) + 1;
|
|
2578
|
+
index.counts.set(label, total);
|
|
2579
|
+
const prior = local.get(label);
|
|
2580
|
+
if (prior) prior.count++;
|
|
2581
|
+
else local.set(label, { start: total, count: 1 });
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
return index;
|
|
2585
|
+
}
|
|
2586
|
+
|
|
2525
2587
|
// src/components/documentRegistry.ts
|
|
2526
2588
|
function createRegistry(onEmpty) {
|
|
2589
|
+
let index;
|
|
2590
|
+
let indexedVersion = -1;
|
|
2591
|
+
const getIndex = () => {
|
|
2592
|
+
if (!index || indexedVersion !== reg.version) {
|
|
2593
|
+
index = buildRegistryIndex(reg);
|
|
2594
|
+
indexedVersion = reg.version;
|
|
2595
|
+
}
|
|
2596
|
+
return index;
|
|
2597
|
+
};
|
|
2527
2598
|
const reg = {
|
|
2528
2599
|
chunkOrder: [],
|
|
2529
2600
|
chunkData: /* @__PURE__ */ new Map(),
|
|
@@ -2675,72 +2746,25 @@ function createRegistry(onEmpty) {
|
|
|
2675
2746
|
};
|
|
2676
2747
|
},
|
|
2677
2748
|
canonicalFootnoteFor(label) {
|
|
2678
|
-
|
|
2679
|
-
for (const sym of this.chunkOrder) {
|
|
2680
|
-
const data = this.chunkData.get(sym);
|
|
2681
|
-
if (data?.defs.has(id)) return sym;
|
|
2682
|
-
}
|
|
2683
|
-
return null;
|
|
2749
|
+
return getIndex().footnotes.get(normalizeId(label)) ?? null;
|
|
2684
2750
|
},
|
|
2685
2751
|
canonicalLinkFor(label) {
|
|
2686
|
-
|
|
2687
|
-
for (const sym of this.chunkOrder) {
|
|
2688
|
-
const data = this.chunkData.get(sym);
|
|
2689
|
-
if (data?.linkDefs.has(id)) return sym;
|
|
2690
|
-
}
|
|
2691
|
-
return null;
|
|
2752
|
+
return getIndex().links.get(normalizeId(label)) ?? null;
|
|
2692
2753
|
},
|
|
2693
2754
|
globalNumber(label) {
|
|
2694
|
-
|
|
2695
|
-
let n = 0;
|
|
2696
|
-
const seen = /* @__PURE__ */ new Set();
|
|
2697
|
-
for (const sym of this.chunkOrder) {
|
|
2698
|
-
const data = this.chunkData.get(sym);
|
|
2699
|
-
if (!data) continue;
|
|
2700
|
-
for (const ref of data.refs) {
|
|
2701
|
-
if (ref.kind !== "footnote") continue;
|
|
2702
|
-
if (!seen.has(ref.label)) {
|
|
2703
|
-
seen.add(ref.label);
|
|
2704
|
-
n++;
|
|
2705
|
-
if (ref.label === id) return n;
|
|
2706
|
-
}
|
|
2707
|
-
}
|
|
2708
|
-
}
|
|
2709
|
-
return null;
|
|
2755
|
+
return getIndex().numbers.get(normalizeId(label)) ?? null;
|
|
2710
2756
|
},
|
|
2711
2757
|
resolveLinkDef(label) {
|
|
2712
|
-
const
|
|
2713
|
-
|
|
2714
|
-
return this.chunkData.get(sym)?.linkDefs.get(
|
|
2758
|
+
const id = normalizeId(label);
|
|
2759
|
+
const sym = getIndex().links.get(id);
|
|
2760
|
+
return sym ? this.chunkData.get(sym)?.linkDefs.get(id) ?? null : null;
|
|
2715
2761
|
},
|
|
2716
2762
|
getRefsForLabel(label) {
|
|
2717
|
-
|
|
2718
|
-
let n = 0;
|
|
2719
|
-
for (const sym of this.chunkOrder) {
|
|
2720
|
-
const data = this.chunkData.get(sym);
|
|
2721
|
-
if (!data) continue;
|
|
2722
|
-
for (const ref of data.refs) {
|
|
2723
|
-
if (ref.kind === "footnote" && ref.label === id) n++;
|
|
2724
|
-
}
|
|
2725
|
-
}
|
|
2726
|
-
return n;
|
|
2763
|
+
return getIndex().counts.get(normalizeId(label)) ?? 0;
|
|
2727
2764
|
},
|
|
2728
2765
|
globalOccurrenceForRef(chunkSym, label, localOccurrence) {
|
|
2729
|
-
const
|
|
2730
|
-
|
|
2731
|
-
for (const sym of this.chunkOrder) {
|
|
2732
|
-
const data = this.chunkData.get(sym);
|
|
2733
|
-
if (!data) continue;
|
|
2734
|
-
let localCount = 0;
|
|
2735
|
-
for (const ref of data.refs) {
|
|
2736
|
-
if (ref.kind !== "footnote") continue;
|
|
2737
|
-
if (ref.label !== id) continue;
|
|
2738
|
-
localCount++;
|
|
2739
|
-
global2++;
|
|
2740
|
-
if (sym === chunkSym && localCount === localOccurrence) return global2;
|
|
2741
|
-
}
|
|
2742
|
-
}
|
|
2743
|
-
return null;
|
|
2766
|
+
const range = getIndex().occurrences.get(chunkSym)?.get(normalizeId(label));
|
|
2767
|
+
return range && Number.isInteger(localOccurrence) && localOccurrence > 0 && localOccurrence <= range.count ? range.start + localOccurrence - 1 : null;
|
|
2744
2768
|
},
|
|
2745
2769
|
_notify() {
|
|
2746
2770
|
this.version++;
|
|
@@ -2797,6 +2821,55 @@ function rehypeUnwrapCrossChunkImages() {
|
|
|
2797
2821
|
|
|
2798
2822
|
// src/components/pluginChain.ts
|
|
2799
2823
|
var import_rehype_sanitize = __toESM(require("rehype-sanitize"), 1);
|
|
2824
|
+
|
|
2825
|
+
// src/components/rehypeVerifyEngineTags.ts
|
|
2826
|
+
var ENGINE_PLACEHOLDER_TAGS = /* @__PURE__ */ new Set([
|
|
2827
|
+
"footnote-sup",
|
|
2828
|
+
"cross-chunk-link",
|
|
2829
|
+
"cross-chunk-image"
|
|
2830
|
+
]);
|
|
2831
|
+
var ENGINE_PROVENANCE_PROPERTY = "engineProvenance";
|
|
2832
|
+
function walk(parent, provenance, ancestors) {
|
|
2833
|
+
const children = parent.children;
|
|
2834
|
+
let i = 0;
|
|
2835
|
+
while (i < children.length) {
|
|
2836
|
+
const node = children[i];
|
|
2837
|
+
if (node.type === "element" && ENGINE_PLACEHOLDER_TAGS.has(node.tagName)) {
|
|
2838
|
+
const props = node.properties ?? {};
|
|
2839
|
+
const stamped = props[ENGINE_PROVENANCE_PROPERTY];
|
|
2840
|
+
const genuine = provenance !== "" && typeof stamped === "string" && stamped === provenance;
|
|
2841
|
+
if (genuine) {
|
|
2842
|
+
delete props[ENGINE_PROVENANCE_PROPERTY];
|
|
2843
|
+
if (ancestors && (node.tagName === "cross-chunk-link" || node.tagName === "cross-chunk-image")) {
|
|
2844
|
+
(node.data ??= {}).referenceAncestors = ancestors.slice();
|
|
2845
|
+
}
|
|
2846
|
+
ancestors?.push(
|
|
2847
|
+
node.tagName === "cross-chunk-link" ? "a" : node.tagName === "cross-chunk-image" ? "img" : node.tagName
|
|
2848
|
+
);
|
|
2849
|
+
walk(node, provenance, ancestors);
|
|
2850
|
+
ancestors?.pop();
|
|
2851
|
+
i += 1;
|
|
2852
|
+
} else {
|
|
2853
|
+
children.splice(i, 1, ...node.children);
|
|
2854
|
+
}
|
|
2855
|
+
continue;
|
|
2856
|
+
}
|
|
2857
|
+
if (node.type === "element") {
|
|
2858
|
+
ancestors?.push(node.tagName);
|
|
2859
|
+
walk(node, provenance, ancestors);
|
|
2860
|
+
ancestors?.pop();
|
|
2861
|
+
}
|
|
2862
|
+
i += 1;
|
|
2863
|
+
}
|
|
2864
|
+
}
|
|
2865
|
+
function rehypeVerifyEngineTags(options) {
|
|
2866
|
+
const provenance = options?.provenance ?? "";
|
|
2867
|
+
return function transformer(tree) {
|
|
2868
|
+
walk(tree, provenance, options?.referenceAncestors ? [] : void 0);
|
|
2869
|
+
};
|
|
2870
|
+
}
|
|
2871
|
+
|
|
2872
|
+
// src/components/pluginChain.ts
|
|
2800
2873
|
var import_remark_breaks = __toESM(require("remark-breaks"), 1);
|
|
2801
2874
|
var import_remark_cjk_friendly = __toESM(require("remark-cjk-friendly"), 1);
|
|
2802
2875
|
var import_remark_cjk_friendly_gfm_strikethrough = __toESM(require("remark-cjk-friendly-gfm-strikethrough"), 1);
|
|
@@ -2813,16 +2886,18 @@ var import_remark_remove_comments = __toESM(require("remark-remove-comments"), 1
|
|
|
2813
2886
|
// src/components/rehypeRebaseHashLinks.ts
|
|
2814
2887
|
var import_unist_util_visit5 = require("unist-util-visit");
|
|
2815
2888
|
var DEFAULT_PREFIX = "user-content-";
|
|
2889
|
+
function rebaseHashHref(href, prefix) {
|
|
2890
|
+
const hashPrefix = "#" + prefix;
|
|
2891
|
+
return href.startsWith("#") && !href.startsWith(hashPrefix) ? hashPrefix + href.slice(1) : href;
|
|
2892
|
+
}
|
|
2816
2893
|
var rehypeRebaseHashLinks = (options) => {
|
|
2817
2894
|
const prefix = options?.prefix ?? DEFAULT_PREFIX;
|
|
2818
|
-
const hashPrefix = "#" + prefix;
|
|
2819
2895
|
return (tree) => {
|
|
2820
2896
|
(0, import_unist_util_visit5.visit)(tree, "element", (node) => {
|
|
2821
2897
|
if (node.tagName !== "a") return;
|
|
2822
2898
|
const href = node.properties?.href;
|
|
2823
2899
|
if (typeof href !== "string" || !href.startsWith("#")) return;
|
|
2824
|
-
|
|
2825
|
-
node.properties.href = hashPrefix + href.slice(1);
|
|
2900
|
+
node.properties.href = rebaseHashHref(href, prefix);
|
|
2826
2901
|
});
|
|
2827
2902
|
};
|
|
2828
2903
|
};
|
|
@@ -2902,10 +2977,21 @@ function buildCoreRemarkPlugins(enginePlugins) {
|
|
|
2902
2977
|
...DISPLAY_OPTIMIZE_CHAIN.filter(([name]) => selected.has(name)).map(([, plugin]) => plugin)
|
|
2903
2978
|
];
|
|
2904
2979
|
}
|
|
2905
|
-
function buildCoreRehypePlugins(sanitizeSchema2, clobberPrefix) {
|
|
2980
|
+
function buildCoreRehypePlugins(sanitizeSchema2, clobberPrefix, options) {
|
|
2906
2981
|
return [
|
|
2907
2982
|
// Allow raw HTML through so rehype-sanitize can handle it.
|
|
2908
2983
|
[import_rehype_raw.default, { passThrough: [] }],
|
|
2984
|
+
// Unwrap forged engine placeholders BEFORE sanitize admits their tag
|
|
2985
|
+
// names. Only when the caller holds a credential (see the option's doc).
|
|
2986
|
+
...options ? [
|
|
2987
|
+
[
|
|
2988
|
+
rehypeVerifyEngineTags,
|
|
2989
|
+
{
|
|
2990
|
+
provenance: options.provenance,
|
|
2991
|
+
...sanitizeSchema2.ancestors?.a || sanitizeSchema2.ancestors?.img ? { referenceAncestors: true } : {}
|
|
2992
|
+
}
|
|
2993
|
+
]
|
|
2994
|
+
] : [],
|
|
2909
2995
|
// Sanitize HTML while allowing <mark> (highlight), KaTeX class names,
|
|
2910
2996
|
// and any extra protocols the caller permitted via the `sanitizeSchema`
|
|
2911
2997
|
// prop. Override `clobberPrefix` with the instance-scoped value — the
|
|
@@ -2945,6 +3031,10 @@ function buildCoreRemarkRehypeOptions(enableDefinitionList) {
|
|
|
2945
3031
|
}
|
|
2946
3032
|
|
|
2947
3033
|
// src/components/customMdastHandlers.ts
|
|
3034
|
+
function provenanceProps(s) {
|
|
3035
|
+
const provenance = s.options.provenance;
|
|
3036
|
+
return typeof provenance === "string" ? { engineProvenance: provenance } : {};
|
|
3037
|
+
}
|
|
2948
3038
|
function localDefProps(s, id) {
|
|
2949
3039
|
const def = s.definitionById.get(id);
|
|
2950
3040
|
if (!def || typeof def.url !== "string" || def.url === SENTINEL_LINK_URL) return {};
|
|
@@ -2975,15 +3065,14 @@ function buildCrossChunkHandlers() {
|
|
|
2975
3065
|
type: "element",
|
|
2976
3066
|
tagName: "cross-chunk-link",
|
|
2977
3067
|
properties: {
|
|
2978
|
-
//
|
|
2979
|
-
//
|
|
2980
|
-
|
|
2981
|
-
// which also preserves source case. Registry lookups normalize
|
|
2982
|
-
// internally, so cross-chunk case-insensitive matching still works.
|
|
3068
|
+
// Display labels decode escapes; registry identifiers must retain
|
|
3069
|
+
// those bytes. Never use the display label as the lookup key.
|
|
3070
|
+
identifier: node.identifier,
|
|
2983
3071
|
label: node.label ?? node.identifier,
|
|
2984
3072
|
referenceType: node.referenceType,
|
|
2985
3073
|
documentId: s.options.documentId,
|
|
2986
|
-
...localDefProps(s, id)
|
|
3074
|
+
...localDefProps(s, id),
|
|
3075
|
+
...provenanceProps(s)
|
|
2987
3076
|
},
|
|
2988
3077
|
children: s.all(node)
|
|
2989
3078
|
};
|
|
@@ -2997,11 +3086,13 @@ function buildCrossChunkHandlers() {
|
|
|
2997
3086
|
type: "element",
|
|
2998
3087
|
tagName: "cross-chunk-image",
|
|
2999
3088
|
properties: {
|
|
3089
|
+
identifier: node.identifier,
|
|
3000
3090
|
label: node.label ?? node.identifier,
|
|
3001
3091
|
referenceType: node.referenceType,
|
|
3002
3092
|
alt: node.alt ?? "",
|
|
3003
3093
|
documentId: s.options.documentId,
|
|
3004
|
-
...localDefProps(s, id)
|
|
3094
|
+
...localDefProps(s, id),
|
|
3095
|
+
...provenanceProps(s)
|
|
3005
3096
|
},
|
|
3006
3097
|
children: []
|
|
3007
3098
|
};
|
|
@@ -3018,7 +3109,8 @@ function buildCrossChunkHandlers() {
|
|
|
3018
3109
|
properties: {
|
|
3019
3110
|
label: node.identifier,
|
|
3020
3111
|
localOccurrence,
|
|
3021
|
-
documentId: s.options.documentId
|
|
3112
|
+
documentId: s.options.documentId,
|
|
3113
|
+
...provenanceProps(s)
|
|
3022
3114
|
},
|
|
3023
3115
|
children: []
|
|
3024
3116
|
};
|
|
@@ -3036,7 +3128,8 @@ function buildCrossChunkHandlers() {
|
|
|
3036
3128
|
// first client frame), where the local synthetic footer is what
|
|
3037
3129
|
// renders, so marks and footer agree (core-render-02).
|
|
3038
3130
|
localNumber: s.footnoteOrder.indexOf(id) + 1,
|
|
3039
|
-
documentId: s.options.documentId
|
|
3131
|
+
documentId: s.options.documentId,
|
|
3132
|
+
...provenanceProps(s)
|
|
3040
3133
|
},
|
|
3041
3134
|
children: []
|
|
3042
3135
|
};
|
|
@@ -4256,8 +4349,8 @@ var sanitizeSchema = deepFreeze(
|
|
|
4256
4349
|
attributes: {
|
|
4257
4350
|
...import_rehype_sanitize2.defaultSchema.attributes,
|
|
4258
4351
|
code: mergeClassNameAllowlist(import_rehype_sanitize2.defaultSchema.attributes?.code, ["math-inline", "math-display"]),
|
|
4259
|
-
"cross-chunk-link": ["label", "referenceType", "documentId", "localUrl", "localTitle"],
|
|
4260
|
-
"cross-chunk-image": ["label", "referenceType", "documentId", "alt", "localUrl", "localTitle"],
|
|
4352
|
+
"cross-chunk-link": ["identifier", "label", "referenceType", "documentId", "localUrl", "localTitle"],
|
|
4353
|
+
"cross-chunk-image": ["identifier", "label", "referenceType", "documentId", "alt", "localUrl", "localTitle"],
|
|
4261
4354
|
"footnote-sup": ["label", "localOccurrence", "localNumber", "documentId"]
|
|
4262
4355
|
},
|
|
4263
4356
|
strip: [.../* @__PURE__ */ new Set([...import_rehype_sanitize2.defaultSchema.strip || [], ...STRIPPED_TAGS])]
|
|
@@ -4293,6 +4386,49 @@ function sanitizeCrossChunkUrl(rawUrl, key, tagName, urlTransform, schema) {
|
|
|
4293
4386
|
return String(transformed);
|
|
4294
4387
|
}
|
|
4295
4388
|
|
|
4389
|
+
// src/components/resolveCrossChunkReference.ts
|
|
4390
|
+
var import_rehype_sanitize3 = __toESM(require("rehype-sanitize"), 1);
|
|
4391
|
+
var import_micromark_util_sanitize_uri3 = require("micromark-util-sanitize-uri");
|
|
4392
|
+
function resolveCrossChunkReference(input, schema, urlTransform, clobberPrefix) {
|
|
4393
|
+
const key = input.tagName === "a" ? "href" : "src";
|
|
4394
|
+
const element = {
|
|
4395
|
+
type: "element",
|
|
4396
|
+
tagName: input.tagName,
|
|
4397
|
+
properties: {
|
|
4398
|
+
[key]: (0, import_micromark_util_sanitize_uri3.normalizeUri)(input.url),
|
|
4399
|
+
...input.tagName === "img" ? { alt: input.alt ?? "" } : {},
|
|
4400
|
+
...input.title !== void 0 ? { title: input.title } : {}
|
|
4401
|
+
},
|
|
4402
|
+
children: input.tagName === "a" ? [{ type: "text", value: "__reference_children__" }] : []
|
|
4403
|
+
};
|
|
4404
|
+
const requiredAncestors = schema.ancestors?.[input.tagName];
|
|
4405
|
+
const recordedAncestors = input.node?.data?.referenceAncestors;
|
|
4406
|
+
let finalSchema = schema;
|
|
4407
|
+
if (requiredAncestors && Array.isArray(recordedAncestors) && requiredAncestors.some((tag) => recordedAncestors.includes(tag))) {
|
|
4408
|
+
const ancestors = { ...schema.ancestors };
|
|
4409
|
+
delete ancestors[input.tagName];
|
|
4410
|
+
finalSchema = { ...schema, ancestors };
|
|
4411
|
+
}
|
|
4412
|
+
const root2 = (0, import_rehype_sanitize3.default)({ ...finalSchema, clobberPrefix })({ type: "root", children: [element] });
|
|
4413
|
+
const node = root2.children[0];
|
|
4414
|
+
if (node?.type !== "element") return { element: null, keepChildren: node?.type === "text" };
|
|
4415
|
+
if (node.tagName === "a" && typeof node.properties.href === "string") {
|
|
4416
|
+
node.properties.href = rebaseHashHref(node.properties.href, clobberPrefix);
|
|
4417
|
+
}
|
|
4418
|
+
node.children = input.node?.children ?? [];
|
|
4419
|
+
if (input.node?.position) node.position = input.node.position;
|
|
4420
|
+
buildTransform({
|
|
4421
|
+
allowedElements: void 0,
|
|
4422
|
+
disallowedElements: void 0,
|
|
4423
|
+
allowElement: void 0,
|
|
4424
|
+
skipHtml: void 0,
|
|
4425
|
+
unwrapDisallowed: void 0,
|
|
4426
|
+
urlTransform
|
|
4427
|
+
})(node, 0, root2);
|
|
4428
|
+
node.children = [];
|
|
4429
|
+
return { element: node, keepChildren: false };
|
|
4430
|
+
}
|
|
4431
|
+
|
|
4296
4432
|
// src/plugins/defs.ts
|
|
4297
4433
|
function getEnginePluginInternals(plugin) {
|
|
4298
4434
|
const candidate = plugin;
|
|
@@ -4509,6 +4645,8 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4509
4645
|
let source = "";
|
|
4510
4646
|
let visibleEnd = 0;
|
|
4511
4647
|
let pending = [];
|
|
4648
|
+
let pendingHead = 0;
|
|
4649
|
+
const pendingCount = () => pending.length - pendingHead;
|
|
4512
4650
|
let tentativeEnd = 0;
|
|
4513
4651
|
let finished = false;
|
|
4514
4652
|
let seam;
|
|
@@ -4553,7 +4691,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4553
4691
|
cancelFrame = void 0;
|
|
4554
4692
|
};
|
|
4555
4693
|
const ensureScheduled = () => {
|
|
4556
|
-
if (disposed || cancelFrame ||
|
|
4694
|
+
if (disposed || cancelFrame || pendingCount() === 0) return;
|
|
4557
4695
|
lastTickAt = now();
|
|
4558
4696
|
credit = 0;
|
|
4559
4697
|
cancelFrame = schedule(tick);
|
|
@@ -4567,31 +4705,38 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4567
4705
|
const params = resolveParams();
|
|
4568
4706
|
let rate;
|
|
4569
4707
|
if (finished && drainDeadlineAt !== void 0) {
|
|
4570
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4708
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, drainDeadlineAt - t));
|
|
4571
4709
|
} else if (gapWindow.length > 0 && lastArrivalAt !== void 0) {
|
|
4572
4710
|
const gaps = gapWindow.map((s) => s.gap).sort((a, b) => a - b);
|
|
4573
4711
|
const intervalQ = gaps[Math.min(gaps.length - 1, Math.floor(gaps.length * INTERVAL_QUANTILE))];
|
|
4574
4712
|
const horizon = Math.max(16, Math.min(params.bufferFactor * intervalQ + HORIZON_PAD_MS, params.maxLagMs));
|
|
4575
4713
|
const deadline = Math.max(lastArrivalAt + horizon, t + DEADLINE_FLOOR_MS);
|
|
4576
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4714
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, deadline - t));
|
|
4577
4715
|
} else {
|
|
4578
|
-
rate = Math.max(params.minCharsPerSecond,
|
|
4716
|
+
rate = Math.max(params.minCharsPerSecond, pendingCount() * 1e3 / Math.max(1, params.correctionTauMs));
|
|
4579
4717
|
}
|
|
4580
4718
|
credit += rate * dt / 1e3;
|
|
4581
|
-
const reveal = Math.min(Math.floor(credit),
|
|
4719
|
+
const reveal = Math.min(Math.floor(credit), pendingCount());
|
|
4582
4720
|
if (reveal > 0) {
|
|
4583
|
-
visibleEnd = pending[reveal - 1];
|
|
4584
|
-
|
|
4585
|
-
|
|
4721
|
+
visibleEnd = pending[pendingHead + reveal - 1];
|
|
4722
|
+
pendingHead += reveal;
|
|
4723
|
+
if (pendingHead === pending.length) {
|
|
4724
|
+
pending = [];
|
|
4725
|
+
pendingHead = 0;
|
|
4726
|
+
} else if (pendingHead >= 1024 && pendingHead * 2 >= pending.length) {
|
|
4727
|
+
pending = pending.slice(pendingHead);
|
|
4728
|
+
pendingHead = 0;
|
|
4729
|
+
}
|
|
4730
|
+
credit = pendingCount() > 0 ? credit - reveal : 0;
|
|
4586
4731
|
notify();
|
|
4587
4732
|
}
|
|
4588
|
-
if (!disposed && !cancelFrame &&
|
|
4733
|
+
if (!disposed && !cancelFrame && pendingCount() > 0) cancelFrame = schedule(tick);
|
|
4589
4734
|
};
|
|
4590
4735
|
const resegmentTail = () => {
|
|
4591
|
-
if (seam !== void 0 && seam < source.length && pending[pending.length - 1] === seam) {
|
|
4736
|
+
if (pendingCount() > 0 && seam !== void 0 && seam < source.length && pending[pending.length - 1] === seam) {
|
|
4592
4737
|
pending.pop();
|
|
4593
4738
|
}
|
|
4594
|
-
const from =
|
|
4739
|
+
const from = pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd;
|
|
4595
4740
|
let anchor = from;
|
|
4596
4741
|
if (seam !== void 0 && from <= seam) {
|
|
4597
4742
|
anchor = Math.max(0, from - RESUME_LOOKBACK);
|
|
@@ -4625,6 +4770,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4625
4770
|
visibleEnd = next.length;
|
|
4626
4771
|
tentativeEnd = next.length;
|
|
4627
4772
|
pending = [];
|
|
4773
|
+
pendingHead = 0;
|
|
4628
4774
|
seam = next.length;
|
|
4629
4775
|
credit = 0;
|
|
4630
4776
|
cancelScheduled();
|
|
@@ -4656,7 +4802,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4656
4802
|
if (finished) return;
|
|
4657
4803
|
finished = true;
|
|
4658
4804
|
lastArrivalAt = void 0;
|
|
4659
|
-
if (tentativeEnd > (
|
|
4805
|
+
if (tentativeEnd > (pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd)) {
|
|
4660
4806
|
pending.push(tentativeEnd);
|
|
4661
4807
|
}
|
|
4662
4808
|
const params = resolveParams();
|
|
@@ -4682,10 +4828,11 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4682
4828
|
snap,
|
|
4683
4829
|
flush() {
|
|
4684
4830
|
disposed = false;
|
|
4685
|
-
const target = finished ? source.length :
|
|
4831
|
+
const target = finished ? source.length : pendingCount() > 0 ? pending[pending.length - 1] : visibleEnd;
|
|
4686
4832
|
if (target <= visibleEnd) return;
|
|
4687
4833
|
visibleEnd = target;
|
|
4688
4834
|
pending = [];
|
|
4835
|
+
pendingHead = 0;
|
|
4689
4836
|
credit = 0;
|
|
4690
4837
|
cancelScheduled();
|
|
4691
4838
|
notify();
|
|
@@ -4708,6 +4855,12 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4708
4855
|
};
|
|
4709
4856
|
|
|
4710
4857
|
// src/preprocessors/latex.ts
|
|
4858
|
+
function isHardBoundary(kind) {
|
|
4859
|
+
return kind === "code" || kind === "literal" || kind === "multilineTag";
|
|
4860
|
+
}
|
|
4861
|
+
function hasLineEnding(text) {
|
|
4862
|
+
return text.includes("\n") || text.includes("\r");
|
|
4863
|
+
}
|
|
4711
4864
|
function getRepeatedMarkerLength(content, start, marker) {
|
|
4712
4865
|
let end = start;
|
|
4713
4866
|
while (end < content.length && content[end] === marker) {
|
|
@@ -4775,11 +4928,11 @@ function splitByProtectedRegions(content) {
|
|
|
4775
4928
|
let multilineFenceMarker = null;
|
|
4776
4929
|
let multilineFenceLength = 0;
|
|
4777
4930
|
let multilineFenceIndent = 0;
|
|
4778
|
-
function pushProtected(start, end) {
|
|
4931
|
+
function pushProtected(start, end, kind) {
|
|
4779
4932
|
if (start > lastIndex) {
|
|
4780
|
-
segments.push({ text: content.substring(lastIndex, start)
|
|
4933
|
+
segments.push({ kind: "text", text: content.substring(lastIndex, start) });
|
|
4781
4934
|
}
|
|
4782
|
-
segments.push({ text: content.substring(start, end)
|
|
4935
|
+
segments.push({ kind, text: content.substring(start, end) });
|
|
4783
4936
|
lastIndex = end;
|
|
4784
4937
|
}
|
|
4785
4938
|
let i = 0;
|
|
@@ -4790,7 +4943,7 @@ function splitByProtectedRegions(content) {
|
|
|
4790
4943
|
const runLen = getRepeatedMarkerLength(content, i, multilineFenceMarker);
|
|
4791
4944
|
const closerIndent = lineIndentBefore(content, i);
|
|
4792
4945
|
if (runLen >= multilineFenceLength && closerIndent !== -1 && closerIndent <= multilineFenceIndent + 3 && restOfLineIsBlank(content, i + runLen)) {
|
|
4793
|
-
pushProtected(multilineStart, i + runLen);
|
|
4946
|
+
pushProtected(multilineStart, i + runLen, "code");
|
|
4794
4947
|
multilineStart = -1;
|
|
4795
4948
|
multilineFenceMarker = null;
|
|
4796
4949
|
multilineFenceLength = 0;
|
|
@@ -4817,7 +4970,7 @@ function splitByProtectedRegions(content) {
|
|
|
4817
4970
|
if (char === "`") {
|
|
4818
4971
|
const closeIdx = findClosingBacktickRun(content, i + runLen, runLen);
|
|
4819
4972
|
if (closeIdx !== -1) {
|
|
4820
|
-
pushProtected(i, closeIdx + runLen);
|
|
4973
|
+
pushProtected(i, closeIdx + runLen, "code");
|
|
4821
4974
|
i = closeIdx + runLen;
|
|
4822
4975
|
continue;
|
|
4823
4976
|
}
|
|
@@ -4842,7 +4995,11 @@ function splitByProtectedRegions(content) {
|
|
|
4842
4995
|
endIndex = content.length;
|
|
4843
4996
|
}
|
|
4844
4997
|
}
|
|
4845
|
-
pushProtected(
|
|
4998
|
+
pushProtected(
|
|
4999
|
+
i,
|
|
5000
|
+
endIndex,
|
|
5001
|
+
isOpeningPairedTag ? "literal" : hasLineEnding(content.substring(i, endIndex)) ? "multilineTag" : "tag"
|
|
5002
|
+
);
|
|
4846
5003
|
i = endIndex;
|
|
4847
5004
|
continue;
|
|
4848
5005
|
}
|
|
@@ -4850,10 +5007,10 @@ function splitByProtectedRegions(content) {
|
|
|
4850
5007
|
i += 1;
|
|
4851
5008
|
}
|
|
4852
5009
|
if (multilineStart !== -1) {
|
|
4853
|
-
pushProtected(multilineStart, content.length);
|
|
5010
|
+
pushProtected(multilineStart, content.length, "code");
|
|
4854
5011
|
}
|
|
4855
5012
|
if (lastIndex < content.length) {
|
|
4856
|
-
segments.push({ text: content.substring(lastIndex)
|
|
5013
|
+
segments.push({ kind: "text", text: content.substring(lastIndex) });
|
|
4857
5014
|
}
|
|
4858
5015
|
return segments;
|
|
4859
5016
|
}
|
|
@@ -5007,20 +5164,22 @@ function escapeLatexPipesInUnclosed(text) {
|
|
|
5007
5164
|
const tail = text.substring(unclosedStart + delimLen);
|
|
5008
5165
|
return before + delim + replaceUnescapedPipes(tail);
|
|
5009
5166
|
}
|
|
5010
|
-
function opensMathFlow(text, pos) {
|
|
5167
|
+
function opensMathFlow(text, pos, runStartsAtLineStart) {
|
|
5011
5168
|
let i = pos;
|
|
5012
5169
|
let spaces = 0;
|
|
5013
|
-
while (i > 0
|
|
5170
|
+
while (i > 0) {
|
|
5171
|
+
const prev = text[i - 1];
|
|
5172
|
+
if (prev === "\n" || prev === "\r") return true;
|
|
5014
5173
|
i -= 1;
|
|
5015
5174
|
if (text[i] !== " ") return false;
|
|
5016
5175
|
spaces += 1;
|
|
5017
5176
|
if (spaces > 3) return false;
|
|
5018
5177
|
}
|
|
5019
|
-
return
|
|
5178
|
+
return runStartsAtLineStart;
|
|
5020
5179
|
}
|
|
5021
|
-
function truncateUnclosedLatexBlock(text, unclosedStart = findUnclosedDelimiterStart(text, "double-only")) {
|
|
5180
|
+
function truncateUnclosedLatexBlock(text, runStartsAtLineStart, unclosedStart = findUnclosedDelimiterStart(text, "double-only")) {
|
|
5022
5181
|
if (unclosedStart === -1) return text;
|
|
5023
|
-
if (!opensMathFlow(text, unclosedStart)) return text;
|
|
5182
|
+
if (!opensMathFlow(text, unclosedStart, runStartsAtLineStart)) return text;
|
|
5024
5183
|
return text.substring(0, unclosedStart).trimEnd();
|
|
5025
5184
|
}
|
|
5026
5185
|
function escapeTextUnderscores(text) {
|
|
@@ -5065,7 +5224,8 @@ function convertSingleToDoubleDollar(text) {
|
|
|
5065
5224
|
}
|
|
5066
5225
|
function preprocessLaTeX(str) {
|
|
5067
5226
|
if (!hasLatexTrigger(str)) return str;
|
|
5068
|
-
|
|
5227
|
+
const mask = selectMask(str);
|
|
5228
|
+
return (mask === null ? processSlice(str, { legacy: true, probe: false }) : processSlice(str, { probe: false, mask })).out;
|
|
5069
5229
|
}
|
|
5070
5230
|
function hasLatexTrigger(str) {
|
|
5071
5231
|
return str.includes("$") || str.includes("\\[") || str.includes("\\(");
|
|
@@ -5094,42 +5254,240 @@ function hasUnclosedTextCommand(text) {
|
|
|
5094
5254
|
}
|
|
5095
5255
|
var RESIDUAL_OPEN_BRACKET_RE = /(?<!!)\\\[/;
|
|
5096
5256
|
var LEADING_DOUBLE_DOLLAR_RE = /^\s*\$\$/;
|
|
5097
|
-
|
|
5257
|
+
var PUA_START = 57344;
|
|
5258
|
+
var PUA_END = 63743;
|
|
5259
|
+
var PUA_SIZE = PUA_END - PUA_START + 1;
|
|
5260
|
+
function selectMask(source) {
|
|
5261
|
+
const first = String.fromCharCode(PUA_START);
|
|
5262
|
+
if (source.indexOf(first) === -1) return first;
|
|
5263
|
+
const seen = new Uint8Array(PUA_SIZE);
|
|
5264
|
+
for (let i = 0; i < source.length; i++) {
|
|
5265
|
+
const c = source.charCodeAt(i);
|
|
5266
|
+
if (c >= PUA_START && c <= PUA_END) seen[c - PUA_START] = 1;
|
|
5267
|
+
}
|
|
5268
|
+
for (let k = 0; k < PUA_SIZE; k++) if (seen[k] === 0) return String.fromCharCode(PUA_START + k);
|
|
5269
|
+
return null;
|
|
5270
|
+
}
|
|
5271
|
+
var PuaPresence = class {
|
|
5272
|
+
bits = new Uint8Array(PUA_SIZE);
|
|
5273
|
+
distinct = 0;
|
|
5274
|
+
reset() {
|
|
5275
|
+
this.bits.fill(0);
|
|
5276
|
+
this.distinct = 0;
|
|
5277
|
+
}
|
|
5278
|
+
add(text, from) {
|
|
5279
|
+
for (let i = from; i < text.length; i++) {
|
|
5280
|
+
const c = text.charCodeAt(i);
|
|
5281
|
+
if (c >= PUA_START && c <= PUA_END) {
|
|
5282
|
+
const k = c - PUA_START;
|
|
5283
|
+
if (this.bits[k] === 0) {
|
|
5284
|
+
this.bits[k] = 1;
|
|
5285
|
+
this.distinct += 1;
|
|
5286
|
+
}
|
|
5287
|
+
}
|
|
5288
|
+
}
|
|
5289
|
+
}
|
|
5290
|
+
select() {
|
|
5291
|
+
if (this.distinct === 0) return String.fromCharCode(PUA_START);
|
|
5292
|
+
if (this.distinct >= PUA_SIZE) return null;
|
|
5293
|
+
for (let k = 0; k < PUA_SIZE; k++) if (this.bits[k] === 0) return String.fromCharCode(PUA_START + k);
|
|
5294
|
+
return null;
|
|
5295
|
+
}
|
|
5296
|
+
};
|
|
5297
|
+
function transformRun(input, probe, runStartsAtLineStart, seamEligible) {
|
|
5298
|
+
let text = input;
|
|
5299
|
+
let tailSensitive = false;
|
|
5300
|
+
let truncatedAtSeamStart = false;
|
|
5301
|
+
text = escapeMhchemCommands(text);
|
|
5302
|
+
text = escapeCurrencyDollarSigns(text);
|
|
5303
|
+
text = convertLatexDelimiters(text);
|
|
5304
|
+
if (probe && RESIDUAL_OPEN_BRACKET_RE.test(text)) tailSensitive = true;
|
|
5305
|
+
text = escapeLatexPipes(text);
|
|
5306
|
+
if (probe && findUnclosedDelimiterStart(text, "both") !== -1) tailSensitive = true;
|
|
5307
|
+
text = escapeLatexPipesInUnclosed(text);
|
|
5308
|
+
if (probe && hasUnclosedTextCommand(text)) tailSensitive = true;
|
|
5309
|
+
text = escapeTextUnderscores(text);
|
|
5310
|
+
text = convertSingleToDoubleDollar(text);
|
|
5311
|
+
let unclosedDouble;
|
|
5312
|
+
if (probe || seamEligible && LEADING_DOUBLE_DOLLAR_RE.test(text)) {
|
|
5313
|
+
unclosedDouble = findUnclosedDelimiterStart(text, "double-only");
|
|
5314
|
+
if (unclosedDouble !== -1) {
|
|
5315
|
+
tailSensitive = true;
|
|
5316
|
+
if (seamEligible && opensMathFlow(text, unclosedDouble, runStartsAtLineStart) && text.slice(0, unclosedDouble).trim() === "") {
|
|
5317
|
+
truncatedAtSeamStart = true;
|
|
5318
|
+
}
|
|
5319
|
+
}
|
|
5320
|
+
}
|
|
5321
|
+
text = truncateUnclosedLatexBlock(text, runStartsAtLineStart, unclosedDouble);
|
|
5322
|
+
return { out: text, tailSensitive, truncatedAtSeamStart };
|
|
5323
|
+
}
|
|
5324
|
+
function processSliceLegacy(slice, probe) {
|
|
5098
5325
|
const segments = splitByProtectedRegions(slice);
|
|
5099
5326
|
const parts = [];
|
|
5100
5327
|
let quiescent = true;
|
|
5101
5328
|
let truncatedAtSeamStart = false;
|
|
5102
5329
|
for (let index = 0; index < segments.length; index++) {
|
|
5103
5330
|
const segment = segments[index];
|
|
5104
|
-
if (segment.
|
|
5331
|
+
if (segment.kind !== "text") {
|
|
5105
5332
|
parts.push(segment.text);
|
|
5106
5333
|
continue;
|
|
5107
5334
|
}
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
|
|
5335
|
+
const r = transformRun(segment.text, probe, true, index === 0);
|
|
5336
|
+
if (r.tailSensitive) quiescent = false;
|
|
5337
|
+
if (r.truncatedAtSeamStart) truncatedAtSeamStart = true;
|
|
5338
|
+
parts.push(r.out);
|
|
5339
|
+
}
|
|
5340
|
+
return { out: parts.join(""), quiescent, truncatedAtSeamStart, degradedReason: null };
|
|
5341
|
+
}
|
|
5342
|
+
var SCOPE_DEPTH_CAP = 8;
|
|
5343
|
+
var VOID_TAGS2 = /* @__PURE__ */ new Set(["br", "hr", "img", "wbr", "input", "source"]);
|
|
5344
|
+
var TAG_NAME_RE = /^<(\/?)([A-Za-z][A-Za-z0-9]*)/;
|
|
5345
|
+
function tagInfo(tag) {
|
|
5346
|
+
const m = TAG_NAME_RE.exec(tag);
|
|
5347
|
+
const closing = m?.[1] === "/";
|
|
5348
|
+
const name = (m?.[2] ?? "").toLowerCase();
|
|
5349
|
+
const opensScope = !closing && !tag.endsWith("/>") && !VOID_TAGS2.has(name);
|
|
5350
|
+
return { name, closing, opensScope };
|
|
5351
|
+
}
|
|
5352
|
+
function buildRunTree(segments) {
|
|
5353
|
+
const root2 = [];
|
|
5354
|
+
const stack = [];
|
|
5355
|
+
const current = () => stack.length > 0 ? stack[stack.length - 1].children : root2;
|
|
5356
|
+
const unwind = () => {
|
|
5357
|
+
while (stack.length > 0) {
|
|
5358
|
+
const frame = stack.pop();
|
|
5359
|
+
current().push({ type: "atom", text: frame.open }, ...frame.children);
|
|
5360
|
+
}
|
|
5361
|
+
};
|
|
5362
|
+
for (const segment of segments) {
|
|
5363
|
+
if (segment.kind === "tag") {
|
|
5364
|
+
const info = tagInfo(segment.text);
|
|
5365
|
+
if (info.closing) {
|
|
5366
|
+
const top = stack[stack.length - 1];
|
|
5367
|
+
if (top !== void 0 && top.name === info.name) {
|
|
5368
|
+
stack.pop();
|
|
5369
|
+
const parent = current();
|
|
5370
|
+
if (top.suppressed) {
|
|
5371
|
+
parent.push({ type: "atom", text: top.open }, ...top.children, { type: "atom", text: segment.text });
|
|
5372
|
+
} else {
|
|
5373
|
+
parent.push({ type: "scope", open: top.open, close: segment.text, children: top.children });
|
|
5374
|
+
}
|
|
5375
|
+
} else {
|
|
5376
|
+
current().push({ type: "atom", text: segment.text });
|
|
5126
5377
|
}
|
|
5378
|
+
} else if (info.opensScope) {
|
|
5379
|
+
stack.push({ name: info.name, open: segment.text, suppressed: stack.length >= SCOPE_DEPTH_CAP, children: [] });
|
|
5380
|
+
} else {
|
|
5381
|
+
current().push({ type: "atom", text: segment.text });
|
|
5127
5382
|
}
|
|
5383
|
+
continue;
|
|
5384
|
+
}
|
|
5385
|
+
const t = segment.text;
|
|
5386
|
+
let start = 0;
|
|
5387
|
+
for (let i = 0; i < t.length; i++) {
|
|
5388
|
+
const c = t.charCodeAt(i);
|
|
5389
|
+
if (c !== 10 && c !== 13) continue;
|
|
5390
|
+
if (i > start) current().push({ type: "text", text: t.slice(start, i) });
|
|
5391
|
+
const end = c === 13 && t.charCodeAt(i + 1) === 10 ? i + 2 : i + 1;
|
|
5392
|
+
unwind();
|
|
5393
|
+
root2.push({ type: "text", text: t.slice(i, end) });
|
|
5394
|
+
start = end;
|
|
5395
|
+
i = end - 1;
|
|
5396
|
+
}
|
|
5397
|
+
if (start < t.length) current().push({ type: "text", text: t.slice(start) });
|
|
5398
|
+
}
|
|
5399
|
+
unwind();
|
|
5400
|
+
return root2;
|
|
5401
|
+
}
|
|
5402
|
+
var restoreFailureInjector = null;
|
|
5403
|
+
function restore(out, atoms, mask) {
|
|
5404
|
+
if (restoreFailureInjector !== null && restoreFailureInjector(atoms)) return null;
|
|
5405
|
+
let result = "";
|
|
5406
|
+
let k = 0;
|
|
5407
|
+
let last = 0;
|
|
5408
|
+
for (; ; ) {
|
|
5409
|
+
const idx = out.indexOf(mask, last);
|
|
5410
|
+
if (idx === -1) break;
|
|
5411
|
+
if (k >= atoms.length) return null;
|
|
5412
|
+
result += out.slice(last, idx) + atoms[k];
|
|
5413
|
+
k += 1;
|
|
5414
|
+
last = idx + 1;
|
|
5415
|
+
}
|
|
5416
|
+
return result + out.slice(last);
|
|
5417
|
+
}
|
|
5418
|
+
function emitRun(nodes, mask) {
|
|
5419
|
+
let text = "";
|
|
5420
|
+
const atoms = [];
|
|
5421
|
+
for (const node of nodes) {
|
|
5422
|
+
if (node.type === "text") {
|
|
5423
|
+
text += node.text;
|
|
5424
|
+
} else if (node.type === "atom") {
|
|
5425
|
+
atoms.push(node.text);
|
|
5426
|
+
text += mask;
|
|
5427
|
+
} else {
|
|
5428
|
+
const inner = emitRun(node.children, mask);
|
|
5429
|
+
if (inner === null) return null;
|
|
5430
|
+
const transformed = transformRun(inner.text, false, false, false);
|
|
5431
|
+
const restored = restore(transformed.out, inner.atoms, mask);
|
|
5432
|
+
if (restored === null) return null;
|
|
5433
|
+
atoms.push(node.open + restored + node.close);
|
|
5434
|
+
text += mask;
|
|
5128
5435
|
}
|
|
5129
|
-
text = truncateUnclosedLatexBlock(text, unclosedDouble);
|
|
5130
|
-
parts.push(text);
|
|
5131
5436
|
}
|
|
5132
|
-
return {
|
|
5437
|
+
return { text, atoms };
|
|
5438
|
+
}
|
|
5439
|
+
function reportRestoreViolation() {
|
|
5440
|
+
if (true) {
|
|
5441
|
+
console.error(
|
|
5442
|
+
"[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."
|
|
5443
|
+
);
|
|
5444
|
+
}
|
|
5445
|
+
}
|
|
5446
|
+
function processSliceDefault(slice, probe, mask) {
|
|
5447
|
+
const segments = splitByProtectedRegions(slice);
|
|
5448
|
+
const parts = [];
|
|
5449
|
+
let quiescent = true;
|
|
5450
|
+
let truncatedAtSeamStart = false;
|
|
5451
|
+
let offset = 0;
|
|
5452
|
+
let i = 0;
|
|
5453
|
+
while (i < segments.length) {
|
|
5454
|
+
const segment = segments[i];
|
|
5455
|
+
if (isHardBoundary(segment.kind)) {
|
|
5456
|
+
parts.push(segment.text);
|
|
5457
|
+
offset += segment.text.length;
|
|
5458
|
+
i += 1;
|
|
5459
|
+
continue;
|
|
5460
|
+
}
|
|
5461
|
+
const runStart = offset;
|
|
5462
|
+
const runSegments = [];
|
|
5463
|
+
while (i < segments.length && !isHardBoundary(segments[i].kind)) {
|
|
5464
|
+
runSegments.push(segments[i]);
|
|
5465
|
+
offset += segments[i].text.length;
|
|
5466
|
+
i += 1;
|
|
5467
|
+
}
|
|
5468
|
+
const before = runStart === 0 ? -1 : slice.charCodeAt(runStart - 1);
|
|
5469
|
+
const runStartsAtLineStart = before === -1 || before === 10 || before === 13;
|
|
5470
|
+
const seamEligible = runStart === 0;
|
|
5471
|
+
const emitted = emitRun(buildRunTree(runSegments), mask);
|
|
5472
|
+
if (emitted === null) {
|
|
5473
|
+
reportRestoreViolation();
|
|
5474
|
+
return { ...processSliceLegacy(slice, probe), degradedReason: "restore-invariant" };
|
|
5475
|
+
}
|
|
5476
|
+
const r = transformRun(emitted.text, probe, runStartsAtLineStart, seamEligible);
|
|
5477
|
+
const restored = restore(r.out, emitted.atoms, mask);
|
|
5478
|
+
if (restored === null) {
|
|
5479
|
+
reportRestoreViolation();
|
|
5480
|
+
return { ...processSliceLegacy(slice, probe), degradedReason: "restore-invariant" };
|
|
5481
|
+
}
|
|
5482
|
+
if (r.tailSensitive) quiescent = false;
|
|
5483
|
+
if (r.truncatedAtSeamStart) truncatedAtSeamStart = true;
|
|
5484
|
+
parts.push(restored);
|
|
5485
|
+
}
|
|
5486
|
+
return { out: parts.join(""), quiescent, truncatedAtSeamStart, degradedReason: null };
|
|
5487
|
+
}
|
|
5488
|
+
function processSlice(slice, options) {
|
|
5489
|
+
if (options.legacy === true) return processSliceLegacy(slice, options.probe);
|
|
5490
|
+
return processSliceDefault(slice, options.probe, options.mask);
|
|
5133
5491
|
}
|
|
5134
5492
|
function isBlankRawLine(text, from, to) {
|
|
5135
5493
|
for (let i = from; i < to; i++) {
|
|
@@ -5145,7 +5503,7 @@ function findRawSafeCut(active) {
|
|
|
5145
5503
|
let backtickHazard = false;
|
|
5146
5504
|
let latentLt = false;
|
|
5147
5505
|
for (const segment of segments) {
|
|
5148
|
-
if (segment.
|
|
5506
|
+
if (segment.kind !== "text") {
|
|
5149
5507
|
if (segment.text.includes(">")) latentLt = false;
|
|
5150
5508
|
offset += segment.text.length;
|
|
5151
5509
|
continue;
|
|
@@ -5180,12 +5538,28 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5180
5538
|
const freezeThreshold = options?.freezeThreshold ?? DEFAULT_FREEZE_ATTEMPT_THRESHOLD;
|
|
5181
5539
|
const onAttempt = options?.onAttempt;
|
|
5182
5540
|
const backoff = options?.backoff ?? true;
|
|
5541
|
+
const onDegrade = options?.onDegrade;
|
|
5183
5542
|
let prevSource = "";
|
|
5184
5543
|
let prevOutput = "";
|
|
5185
5544
|
let frozenSrcEnd = 0;
|
|
5186
5545
|
let frozenOut = "";
|
|
5187
5546
|
let triggered = false;
|
|
5188
5547
|
let nextAttemptLen = 0;
|
|
5548
|
+
let lineageDegraded = false;
|
|
5549
|
+
const presence = new PuaPresence();
|
|
5550
|
+
const commit = (source, out) => {
|
|
5551
|
+
prevSource = source;
|
|
5552
|
+
prevOutput = out;
|
|
5553
|
+
return out;
|
|
5554
|
+
};
|
|
5555
|
+
const legacyWhole = (source) => processSlice(source, { legacy: true, probe: false }).out;
|
|
5556
|
+
const degrade = (source, reason) => {
|
|
5557
|
+
lineageDegraded = true;
|
|
5558
|
+
frozenSrcEnd = 0;
|
|
5559
|
+
frozenOut = "";
|
|
5560
|
+
onDegrade?.(reason);
|
|
5561
|
+
return commit(source, legacyWhole(source));
|
|
5562
|
+
};
|
|
5189
5563
|
return function incrementalPreprocessLaTeX(source) {
|
|
5190
5564
|
if (source === prevSource) return prevOutput;
|
|
5191
5565
|
const isAppend = source.length > prevSource.length && source.startsWith(prevSource);
|
|
@@ -5194,16 +5568,20 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5194
5568
|
frozenOut = "";
|
|
5195
5569
|
triggered = false;
|
|
5196
5570
|
nextAttemptLen = 0;
|
|
5571
|
+
lineageDegraded = false;
|
|
5572
|
+
presence.reset();
|
|
5573
|
+
presence.add(source, 0);
|
|
5574
|
+
} else {
|
|
5575
|
+
presence.add(source, prevSource.length);
|
|
5197
5576
|
}
|
|
5198
5577
|
if (!triggered) {
|
|
5199
5578
|
const checkFrom = isAppend ? Math.max(0, prevSource.length - 1) : 0;
|
|
5200
|
-
if (!hasLatexTrigger(source.slice(checkFrom)))
|
|
5201
|
-
prevSource = source;
|
|
5202
|
-
prevOutput = source;
|
|
5203
|
-
return source;
|
|
5204
|
-
}
|
|
5579
|
+
if (!hasLatexTrigger(source.slice(checkFrom))) return commit(source, source);
|
|
5205
5580
|
triggered = true;
|
|
5206
5581
|
}
|
|
5582
|
+
if (lineageDegraded) return commit(source, legacyWhole(source));
|
|
5583
|
+
const mask = presence.select();
|
|
5584
|
+
if (mask === null) return degrade(source, "mask-exhausted");
|
|
5207
5585
|
let active = source.slice(frozenSrcEnd);
|
|
5208
5586
|
if (active.length > freezeThreshold && active.length >= nextAttemptLen) {
|
|
5209
5587
|
const activeLength = active.length;
|
|
@@ -5218,18 +5596,20 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5218
5596
|
};
|
|
5219
5597
|
const cut = findRawSafeCut(active);
|
|
5220
5598
|
if (cut > 0) {
|
|
5221
|
-
const candidate = processSlice(active.slice(0, cut));
|
|
5599
|
+
const candidate = processSlice(active.slice(0, cut), { probe: true, mask });
|
|
5600
|
+
if (candidate.degradedReason !== null) {
|
|
5601
|
+
onAttempt?.({ activeLength, frozenBytes: 0 });
|
|
5602
|
+
return degrade(source, candidate.degradedReason);
|
|
5603
|
+
}
|
|
5222
5604
|
if (candidate.quiescent) freeze(cut, candidate);
|
|
5223
5605
|
}
|
|
5224
5606
|
nextAttemptLen = advanced || !backoff ? 0 : active.length * 2;
|
|
5225
5607
|
onAttempt?.({ activeLength, frozenBytes });
|
|
5226
5608
|
}
|
|
5227
|
-
const tail = processSlice(active, false);
|
|
5609
|
+
const tail = processSlice(active, { probe: false, mask });
|
|
5610
|
+
if (tail.degradedReason !== null) return degrade(source, tail.degradedReason);
|
|
5228
5611
|
const head = tail.truncatedAtSeamStart ? frozenOut.replace(/\s+$/, "") : frozenOut;
|
|
5229
|
-
|
|
5230
|
-
prevSource = source;
|
|
5231
|
-
prevOutput = out;
|
|
5232
|
-
return out;
|
|
5612
|
+
return commit(source, head + tail.out);
|
|
5233
5613
|
};
|
|
5234
5614
|
}
|
|
5235
5615
|
|
|
@@ -5255,6 +5635,8 @@ function createRemendPreprocessor(options) {
|
|
|
5255
5635
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5256
5636
|
0 && (module.exports = {
|
|
5257
5637
|
DEFAULT_PAYLOAD,
|
|
5638
|
+
ENGINE_PLACEHOLDER_TAGS,
|
|
5639
|
+
ENGINE_PROVENANCE_PROPERTY,
|
|
5258
5640
|
PIPELINE_STAGES,
|
|
5259
5641
|
SENTINEL_FN_CONTENT,
|
|
5260
5642
|
SENTINEL_LINK_URL,
|
|
@@ -5299,7 +5681,9 @@ function createRemendPreprocessor(options) {
|
|
|
5299
5681
|
preprocessLaTeX,
|
|
5300
5682
|
rehypeFooterAdorn,
|
|
5301
5683
|
rehypeRebaseHashLinks,
|
|
5684
|
+
rehypeVerifyEngineTags,
|
|
5302
5685
|
removeComments,
|
|
5686
|
+
resolveCrossChunkReference,
|
|
5303
5687
|
sanitizeCrossChunkUrl,
|
|
5304
5688
|
sanitizeSchema,
|
|
5305
5689
|
shortenDocumentId,
|