@ai-react-markdown/engine 2.10.0 → 2.11.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 +350 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +95 -2
- package/dist/index.d.ts +95 -2
- package/dist/index.dev.cjs +350 -50
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +347 -50
- package/dist/index.dev.js.map +1 -1
- package/dist/index.js +347 -50
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -90,7 +90,7 @@ for (const frame of ['# Hello', '# Hello\n\nworld', '# Hello\n\nworld and more']
|
|
|
90
90
|
|
|
91
91
|
## Verification
|
|
92
92
|
|
|
93
|
-
The incremental engine ships with a five-layer equivalence stack (fixture pins, fuzz arbiter, direction battery, exhaustive census, arbiter-sensitivity meta-suite) plus a
|
|
93
|
+
The incremental engine ships with a five-layer equivalence stack (fixture pins, fuzz arbiter, direction battery, exhaustive census, arbiter-sensitivity meta-suite) plus a six-leg release-gate soak (`scripts/soak/soak.sh`, from the repo root, with a fresh seed base); the full record lives in `src/experiments/prefixFreeze/README.md`. Every reachable divergence found so far is pinned as a deterministic test.
|
|
94
94
|
|
|
95
95
|
## Runtime support
|
|
96
96
|
|
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,6 +77,7 @@ __export(src_exports, {
|
|
|
75
77
|
preprocessLaTeX: () => preprocessLaTeX,
|
|
76
78
|
rehypeFooterAdorn: () => rehypeFooterAdorn,
|
|
77
79
|
rehypeRebaseHashLinks: () => rehypeRebaseHashLinks_default,
|
|
80
|
+
rehypeVerifyEngineTags: () => rehypeVerifyEngineTags,
|
|
78
81
|
removeComments: () => removeComments,
|
|
79
82
|
sanitizeCrossChunkUrl: () => sanitizeCrossChunkUrl,
|
|
80
83
|
sanitizeSchema: () => sanitizeSchema,
|
|
@@ -2790,6 +2793,44 @@ function rehypeUnwrapCrossChunkImages() {
|
|
|
2790
2793
|
|
|
2791
2794
|
// src/components/pluginChain.ts
|
|
2792
2795
|
var import_rehype_sanitize = __toESM(require("rehype-sanitize"), 1);
|
|
2796
|
+
|
|
2797
|
+
// src/components/rehypeVerifyEngineTags.ts
|
|
2798
|
+
var ENGINE_PLACEHOLDER_TAGS = /* @__PURE__ */ new Set([
|
|
2799
|
+
"footnote-sup",
|
|
2800
|
+
"cross-chunk-link",
|
|
2801
|
+
"cross-chunk-image"
|
|
2802
|
+
]);
|
|
2803
|
+
var ENGINE_PROVENANCE_PROPERTY = "engineProvenance";
|
|
2804
|
+
function walk(parent, provenance) {
|
|
2805
|
+
const children = parent.children;
|
|
2806
|
+
let i = 0;
|
|
2807
|
+
while (i < children.length) {
|
|
2808
|
+
const node = children[i];
|
|
2809
|
+
if (node.type === "element" && ENGINE_PLACEHOLDER_TAGS.has(node.tagName)) {
|
|
2810
|
+
const props = node.properties ?? {};
|
|
2811
|
+
const stamped = props[ENGINE_PROVENANCE_PROPERTY];
|
|
2812
|
+
const genuine = provenance !== "" && typeof stamped === "string" && stamped === provenance;
|
|
2813
|
+
if (genuine) {
|
|
2814
|
+
delete props[ENGINE_PROVENANCE_PROPERTY];
|
|
2815
|
+
walk(node, provenance);
|
|
2816
|
+
i += 1;
|
|
2817
|
+
} else {
|
|
2818
|
+
children.splice(i, 1, ...node.children);
|
|
2819
|
+
}
|
|
2820
|
+
continue;
|
|
2821
|
+
}
|
|
2822
|
+
if (node.type === "element") walk(node, provenance);
|
|
2823
|
+
i += 1;
|
|
2824
|
+
}
|
|
2825
|
+
}
|
|
2826
|
+
function rehypeVerifyEngineTags(options) {
|
|
2827
|
+
const provenance = options?.provenance ?? "";
|
|
2828
|
+
return function transformer(tree) {
|
|
2829
|
+
walk(tree, provenance);
|
|
2830
|
+
};
|
|
2831
|
+
}
|
|
2832
|
+
|
|
2833
|
+
// src/components/pluginChain.ts
|
|
2793
2834
|
var import_remark_breaks = __toESM(require("remark-breaks"), 1);
|
|
2794
2835
|
var import_remark_cjk_friendly = __toESM(require("remark-cjk-friendly"), 1);
|
|
2795
2836
|
var import_remark_cjk_friendly_gfm_strikethrough = __toESM(require("remark-cjk-friendly-gfm-strikethrough"), 1);
|
|
@@ -2895,10 +2936,13 @@ function buildCoreRemarkPlugins(enginePlugins) {
|
|
|
2895
2936
|
...DISPLAY_OPTIMIZE_CHAIN.filter(([name]) => selected.has(name)).map(([, plugin]) => plugin)
|
|
2896
2937
|
];
|
|
2897
2938
|
}
|
|
2898
|
-
function buildCoreRehypePlugins(sanitizeSchema2, clobberPrefix) {
|
|
2939
|
+
function buildCoreRehypePlugins(sanitizeSchema2, clobberPrefix, options) {
|
|
2899
2940
|
return [
|
|
2900
2941
|
// Allow raw HTML through so rehype-sanitize can handle it.
|
|
2901
2942
|
[import_rehype_raw.default, { passThrough: [] }],
|
|
2943
|
+
// Unwrap forged engine placeholders BEFORE sanitize admits their tag
|
|
2944
|
+
// names. Only when the caller holds a credential (see the option's doc).
|
|
2945
|
+
...options ? [[rehypeVerifyEngineTags, { provenance: options.provenance }]] : [],
|
|
2902
2946
|
// Sanitize HTML while allowing <mark> (highlight), KaTeX class names,
|
|
2903
2947
|
// and any extra protocols the caller permitted via the `sanitizeSchema`
|
|
2904
2948
|
// prop. Override `clobberPrefix` with the instance-scoped value — the
|
|
@@ -2938,6 +2982,10 @@ function buildCoreRemarkRehypeOptions(enableDefinitionList) {
|
|
|
2938
2982
|
}
|
|
2939
2983
|
|
|
2940
2984
|
// src/components/customMdastHandlers.ts
|
|
2985
|
+
function provenanceProps(s) {
|
|
2986
|
+
const provenance = s.options.provenance;
|
|
2987
|
+
return typeof provenance === "string" ? { engineProvenance: provenance } : {};
|
|
2988
|
+
}
|
|
2941
2989
|
function localDefProps(s, id) {
|
|
2942
2990
|
const def = s.definitionById.get(id);
|
|
2943
2991
|
if (!def || typeof def.url !== "string" || def.url === SENTINEL_LINK_URL) return {};
|
|
@@ -2976,7 +3024,8 @@ function buildCrossChunkHandlers() {
|
|
|
2976
3024
|
label: node.label ?? node.identifier,
|
|
2977
3025
|
referenceType: node.referenceType,
|
|
2978
3026
|
documentId: s.options.documentId,
|
|
2979
|
-
...localDefProps(s, id)
|
|
3027
|
+
...localDefProps(s, id),
|
|
3028
|
+
...provenanceProps(s)
|
|
2980
3029
|
},
|
|
2981
3030
|
children: s.all(node)
|
|
2982
3031
|
};
|
|
@@ -2994,7 +3043,8 @@ function buildCrossChunkHandlers() {
|
|
|
2994
3043
|
referenceType: node.referenceType,
|
|
2995
3044
|
alt: node.alt ?? "",
|
|
2996
3045
|
documentId: s.options.documentId,
|
|
2997
|
-
...localDefProps(s, id)
|
|
3046
|
+
...localDefProps(s, id),
|
|
3047
|
+
...provenanceProps(s)
|
|
2998
3048
|
},
|
|
2999
3049
|
children: []
|
|
3000
3050
|
};
|
|
@@ -3011,7 +3061,8 @@ function buildCrossChunkHandlers() {
|
|
|
3011
3061
|
properties: {
|
|
3012
3062
|
label: node.identifier,
|
|
3013
3063
|
localOccurrence,
|
|
3014
|
-
documentId: s.options.documentId
|
|
3064
|
+
documentId: s.options.documentId,
|
|
3065
|
+
...provenanceProps(s)
|
|
3015
3066
|
},
|
|
3016
3067
|
children: []
|
|
3017
3068
|
};
|
|
@@ -3029,7 +3080,8 @@ function buildCrossChunkHandlers() {
|
|
|
3029
3080
|
// first client frame), where the local synthetic footer is what
|
|
3030
3081
|
// renders, so marks and footer agree (core-render-02).
|
|
3031
3082
|
localNumber: s.footnoteOrder.indexOf(id) + 1,
|
|
3032
|
-
documentId: s.options.documentId
|
|
3083
|
+
documentId: s.options.documentId,
|
|
3084
|
+
...provenanceProps(s)
|
|
3033
3085
|
},
|
|
3034
3086
|
children: []
|
|
3035
3087
|
};
|
|
@@ -4689,6 +4741,12 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4689
4741
|
};
|
|
4690
4742
|
|
|
4691
4743
|
// src/preprocessors/latex.ts
|
|
4744
|
+
function isHardBoundary(kind) {
|
|
4745
|
+
return kind === "code" || kind === "literal" || kind === "multilineTag";
|
|
4746
|
+
}
|
|
4747
|
+
function hasLineEnding(text) {
|
|
4748
|
+
return text.includes("\n") || text.includes("\r");
|
|
4749
|
+
}
|
|
4692
4750
|
function getRepeatedMarkerLength(content, start, marker) {
|
|
4693
4751
|
let end = start;
|
|
4694
4752
|
while (end < content.length && content[end] === marker) {
|
|
@@ -4756,11 +4814,11 @@ function splitByProtectedRegions(content) {
|
|
|
4756
4814
|
let multilineFenceMarker = null;
|
|
4757
4815
|
let multilineFenceLength = 0;
|
|
4758
4816
|
let multilineFenceIndent = 0;
|
|
4759
|
-
function pushProtected(start, end) {
|
|
4817
|
+
function pushProtected(start, end, kind) {
|
|
4760
4818
|
if (start > lastIndex) {
|
|
4761
|
-
segments.push({ text: content.substring(lastIndex, start)
|
|
4819
|
+
segments.push({ kind: "text", text: content.substring(lastIndex, start) });
|
|
4762
4820
|
}
|
|
4763
|
-
segments.push({ text: content.substring(start, end)
|
|
4821
|
+
segments.push({ kind, text: content.substring(start, end) });
|
|
4764
4822
|
lastIndex = end;
|
|
4765
4823
|
}
|
|
4766
4824
|
let i = 0;
|
|
@@ -4771,7 +4829,7 @@ function splitByProtectedRegions(content) {
|
|
|
4771
4829
|
const runLen = getRepeatedMarkerLength(content, i, multilineFenceMarker);
|
|
4772
4830
|
const closerIndent = lineIndentBefore(content, i);
|
|
4773
4831
|
if (runLen >= multilineFenceLength && closerIndent !== -1 && closerIndent <= multilineFenceIndent + 3 && restOfLineIsBlank(content, i + runLen)) {
|
|
4774
|
-
pushProtected(multilineStart, i + runLen);
|
|
4832
|
+
pushProtected(multilineStart, i + runLen, "code");
|
|
4775
4833
|
multilineStart = -1;
|
|
4776
4834
|
multilineFenceMarker = null;
|
|
4777
4835
|
multilineFenceLength = 0;
|
|
@@ -4798,7 +4856,7 @@ function splitByProtectedRegions(content) {
|
|
|
4798
4856
|
if (char === "`") {
|
|
4799
4857
|
const closeIdx = findClosingBacktickRun(content, i + runLen, runLen);
|
|
4800
4858
|
if (closeIdx !== -1) {
|
|
4801
|
-
pushProtected(i, closeIdx + runLen);
|
|
4859
|
+
pushProtected(i, closeIdx + runLen, "code");
|
|
4802
4860
|
i = closeIdx + runLen;
|
|
4803
4861
|
continue;
|
|
4804
4862
|
}
|
|
@@ -4823,7 +4881,11 @@ function splitByProtectedRegions(content) {
|
|
|
4823
4881
|
endIndex = content.length;
|
|
4824
4882
|
}
|
|
4825
4883
|
}
|
|
4826
|
-
pushProtected(
|
|
4884
|
+
pushProtected(
|
|
4885
|
+
i,
|
|
4886
|
+
endIndex,
|
|
4887
|
+
isOpeningPairedTag ? "literal" : hasLineEnding(content.substring(i, endIndex)) ? "multilineTag" : "tag"
|
|
4888
|
+
);
|
|
4827
4889
|
i = endIndex;
|
|
4828
4890
|
continue;
|
|
4829
4891
|
}
|
|
@@ -4831,10 +4893,10 @@ function splitByProtectedRegions(content) {
|
|
|
4831
4893
|
i += 1;
|
|
4832
4894
|
}
|
|
4833
4895
|
if (multilineStart !== -1) {
|
|
4834
|
-
pushProtected(multilineStart, content.length);
|
|
4896
|
+
pushProtected(multilineStart, content.length, "code");
|
|
4835
4897
|
}
|
|
4836
4898
|
if (lastIndex < content.length) {
|
|
4837
|
-
segments.push({ text: content.substring(lastIndex)
|
|
4899
|
+
segments.push({ kind: "text", text: content.substring(lastIndex) });
|
|
4838
4900
|
}
|
|
4839
4901
|
return segments;
|
|
4840
4902
|
}
|
|
@@ -4988,8 +5050,22 @@ function escapeLatexPipesInUnclosed(text) {
|
|
|
4988
5050
|
const tail = text.substring(unclosedStart + delimLen);
|
|
4989
5051
|
return before + delim + replaceUnescapedPipes(tail);
|
|
4990
5052
|
}
|
|
4991
|
-
function
|
|
5053
|
+
function opensMathFlow(text, pos, runStartsAtLineStart) {
|
|
5054
|
+
let i = pos;
|
|
5055
|
+
let spaces = 0;
|
|
5056
|
+
while (i > 0) {
|
|
5057
|
+
const prev = text[i - 1];
|
|
5058
|
+
if (prev === "\n" || prev === "\r") return true;
|
|
5059
|
+
i -= 1;
|
|
5060
|
+
if (text[i] !== " ") return false;
|
|
5061
|
+
spaces += 1;
|
|
5062
|
+
if (spaces > 3) return false;
|
|
5063
|
+
}
|
|
5064
|
+
return runStartsAtLineStart;
|
|
5065
|
+
}
|
|
5066
|
+
function truncateUnclosedLatexBlock(text, runStartsAtLineStart, unclosedStart = findUnclosedDelimiterStart(text, "double-only")) {
|
|
4992
5067
|
if (unclosedStart === -1) return text;
|
|
5068
|
+
if (!opensMathFlow(text, unclosedStart, runStartsAtLineStart)) return text;
|
|
4993
5069
|
return text.substring(0, unclosedStart).trimEnd();
|
|
4994
5070
|
}
|
|
4995
5071
|
function escapeTextUnderscores(text) {
|
|
@@ -5034,7 +5110,8 @@ function convertSingleToDoubleDollar(text) {
|
|
|
5034
5110
|
}
|
|
5035
5111
|
function preprocessLaTeX(str) {
|
|
5036
5112
|
if (!hasLatexTrigger(str)) return str;
|
|
5037
|
-
|
|
5113
|
+
const mask = selectMask(str);
|
|
5114
|
+
return (mask === null ? processSlice(str, { legacy: true, probe: false }) : processSlice(str, { probe: false, mask })).out;
|
|
5038
5115
|
}
|
|
5039
5116
|
function hasLatexTrigger(str) {
|
|
5040
5117
|
return str.includes("$") || str.includes("\\[") || str.includes("\\(");
|
|
@@ -5063,42 +5140,240 @@ function hasUnclosedTextCommand(text) {
|
|
|
5063
5140
|
}
|
|
5064
5141
|
var RESIDUAL_OPEN_BRACKET_RE = /(?<!!)\\\[/;
|
|
5065
5142
|
var LEADING_DOUBLE_DOLLAR_RE = /^\s*\$\$/;
|
|
5066
|
-
|
|
5143
|
+
var PUA_START = 57344;
|
|
5144
|
+
var PUA_END = 63743;
|
|
5145
|
+
var PUA_SIZE = PUA_END - PUA_START + 1;
|
|
5146
|
+
function selectMask(source) {
|
|
5147
|
+
const first = String.fromCharCode(PUA_START);
|
|
5148
|
+
if (source.indexOf(first) === -1) return first;
|
|
5149
|
+
const seen = new Uint8Array(PUA_SIZE);
|
|
5150
|
+
for (let i = 0; i < source.length; i++) {
|
|
5151
|
+
const c = source.charCodeAt(i);
|
|
5152
|
+
if (c >= PUA_START && c <= PUA_END) seen[c - PUA_START] = 1;
|
|
5153
|
+
}
|
|
5154
|
+
for (let k = 0; k < PUA_SIZE; k++) if (seen[k] === 0) return String.fromCharCode(PUA_START + k);
|
|
5155
|
+
return null;
|
|
5156
|
+
}
|
|
5157
|
+
var PuaPresence = class {
|
|
5158
|
+
bits = new Uint8Array(PUA_SIZE);
|
|
5159
|
+
distinct = 0;
|
|
5160
|
+
reset() {
|
|
5161
|
+
this.bits.fill(0);
|
|
5162
|
+
this.distinct = 0;
|
|
5163
|
+
}
|
|
5164
|
+
add(text, from) {
|
|
5165
|
+
for (let i = from; i < text.length; i++) {
|
|
5166
|
+
const c = text.charCodeAt(i);
|
|
5167
|
+
if (c >= PUA_START && c <= PUA_END) {
|
|
5168
|
+
const k = c - PUA_START;
|
|
5169
|
+
if (this.bits[k] === 0) {
|
|
5170
|
+
this.bits[k] = 1;
|
|
5171
|
+
this.distinct += 1;
|
|
5172
|
+
}
|
|
5173
|
+
}
|
|
5174
|
+
}
|
|
5175
|
+
}
|
|
5176
|
+
select() {
|
|
5177
|
+
if (this.distinct === 0) return String.fromCharCode(PUA_START);
|
|
5178
|
+
if (this.distinct >= PUA_SIZE) return null;
|
|
5179
|
+
for (let k = 0; k < PUA_SIZE; k++) if (this.bits[k] === 0) return String.fromCharCode(PUA_START + k);
|
|
5180
|
+
return null;
|
|
5181
|
+
}
|
|
5182
|
+
};
|
|
5183
|
+
function transformRun(input, probe, runStartsAtLineStart, seamEligible) {
|
|
5184
|
+
let text = input;
|
|
5185
|
+
let tailSensitive = false;
|
|
5186
|
+
let truncatedAtSeamStart = false;
|
|
5187
|
+
text = escapeMhchemCommands(text);
|
|
5188
|
+
text = escapeCurrencyDollarSigns(text);
|
|
5189
|
+
text = convertLatexDelimiters(text);
|
|
5190
|
+
if (probe && RESIDUAL_OPEN_BRACKET_RE.test(text)) tailSensitive = true;
|
|
5191
|
+
text = escapeLatexPipes(text);
|
|
5192
|
+
if (probe && findUnclosedDelimiterStart(text, "both") !== -1) tailSensitive = true;
|
|
5193
|
+
text = escapeLatexPipesInUnclosed(text);
|
|
5194
|
+
if (probe && hasUnclosedTextCommand(text)) tailSensitive = true;
|
|
5195
|
+
text = escapeTextUnderscores(text);
|
|
5196
|
+
text = convertSingleToDoubleDollar(text);
|
|
5197
|
+
let unclosedDouble;
|
|
5198
|
+
if (probe || seamEligible && LEADING_DOUBLE_DOLLAR_RE.test(text)) {
|
|
5199
|
+
unclosedDouble = findUnclosedDelimiterStart(text, "double-only");
|
|
5200
|
+
if (unclosedDouble !== -1) {
|
|
5201
|
+
tailSensitive = true;
|
|
5202
|
+
if (seamEligible && opensMathFlow(text, unclosedDouble, runStartsAtLineStart) && text.slice(0, unclosedDouble).trim() === "") {
|
|
5203
|
+
truncatedAtSeamStart = true;
|
|
5204
|
+
}
|
|
5205
|
+
}
|
|
5206
|
+
}
|
|
5207
|
+
text = truncateUnclosedLatexBlock(text, runStartsAtLineStart, unclosedDouble);
|
|
5208
|
+
return { out: text, tailSensitive, truncatedAtSeamStart };
|
|
5209
|
+
}
|
|
5210
|
+
function processSliceLegacy(slice, probe) {
|
|
5067
5211
|
const segments = splitByProtectedRegions(slice);
|
|
5068
5212
|
const parts = [];
|
|
5069
5213
|
let quiescent = true;
|
|
5070
5214
|
let truncatedAtSeamStart = false;
|
|
5071
5215
|
for (let index = 0; index < segments.length; index++) {
|
|
5072
5216
|
const segment = segments[index];
|
|
5073
|
-
if (segment.
|
|
5217
|
+
if (segment.kind !== "text") {
|
|
5074
5218
|
parts.push(segment.text);
|
|
5075
5219
|
continue;
|
|
5076
5220
|
}
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5221
|
+
const r = transformRun(segment.text, probe, true, index === 0);
|
|
5222
|
+
if (r.tailSensitive) quiescent = false;
|
|
5223
|
+
if (r.truncatedAtSeamStart) truncatedAtSeamStart = true;
|
|
5224
|
+
parts.push(r.out);
|
|
5225
|
+
}
|
|
5226
|
+
return { out: parts.join(""), quiescent, truncatedAtSeamStart, degradedReason: null };
|
|
5227
|
+
}
|
|
5228
|
+
var SCOPE_DEPTH_CAP = 8;
|
|
5229
|
+
var VOID_TAGS2 = /* @__PURE__ */ new Set(["br", "hr", "img", "wbr", "input", "source"]);
|
|
5230
|
+
var TAG_NAME_RE = /^<(\/?)([A-Za-z][A-Za-z0-9]*)/;
|
|
5231
|
+
function tagInfo(tag) {
|
|
5232
|
+
const m = TAG_NAME_RE.exec(tag);
|
|
5233
|
+
const closing = m?.[1] === "/";
|
|
5234
|
+
const name = (m?.[2] ?? "").toLowerCase();
|
|
5235
|
+
const opensScope = !closing && !tag.endsWith("/>") && !VOID_TAGS2.has(name);
|
|
5236
|
+
return { name, closing, opensScope };
|
|
5237
|
+
}
|
|
5238
|
+
function buildRunTree(segments) {
|
|
5239
|
+
const root2 = [];
|
|
5240
|
+
const stack = [];
|
|
5241
|
+
const current = () => stack.length > 0 ? stack[stack.length - 1].children : root2;
|
|
5242
|
+
const unwind = () => {
|
|
5243
|
+
while (stack.length > 0) {
|
|
5244
|
+
const frame = stack.pop();
|
|
5245
|
+
current().push({ type: "atom", text: frame.open }, ...frame.children);
|
|
5246
|
+
}
|
|
5247
|
+
};
|
|
5248
|
+
for (const segment of segments) {
|
|
5249
|
+
if (segment.kind === "tag") {
|
|
5250
|
+
const info = tagInfo(segment.text);
|
|
5251
|
+
if (info.closing) {
|
|
5252
|
+
const top = stack[stack.length - 1];
|
|
5253
|
+
if (top !== void 0 && top.name === info.name) {
|
|
5254
|
+
stack.pop();
|
|
5255
|
+
const parent = current();
|
|
5256
|
+
if (top.suppressed) {
|
|
5257
|
+
parent.push({ type: "atom", text: top.open }, ...top.children, { type: "atom", text: segment.text });
|
|
5258
|
+
} else {
|
|
5259
|
+
parent.push({ type: "scope", open: top.open, close: segment.text, children: top.children });
|
|
5260
|
+
}
|
|
5261
|
+
} else {
|
|
5262
|
+
current().push({ type: "atom", text: segment.text });
|
|
5095
5263
|
}
|
|
5264
|
+
} else if (info.opensScope) {
|
|
5265
|
+
stack.push({ name: info.name, open: segment.text, suppressed: stack.length >= SCOPE_DEPTH_CAP, children: [] });
|
|
5266
|
+
} else {
|
|
5267
|
+
current().push({ type: "atom", text: segment.text });
|
|
5096
5268
|
}
|
|
5269
|
+
continue;
|
|
5097
5270
|
}
|
|
5098
|
-
|
|
5099
|
-
|
|
5271
|
+
const t = segment.text;
|
|
5272
|
+
let start = 0;
|
|
5273
|
+
for (let i = 0; i < t.length; i++) {
|
|
5274
|
+
const c = t.charCodeAt(i);
|
|
5275
|
+
if (c !== 10 && c !== 13) continue;
|
|
5276
|
+
if (i > start) current().push({ type: "text", text: t.slice(start, i) });
|
|
5277
|
+
const end = c === 13 && t.charCodeAt(i + 1) === 10 ? i + 2 : i + 1;
|
|
5278
|
+
unwind();
|
|
5279
|
+
root2.push({ type: "text", text: t.slice(i, end) });
|
|
5280
|
+
start = end;
|
|
5281
|
+
i = end - 1;
|
|
5282
|
+
}
|
|
5283
|
+
if (start < t.length) current().push({ type: "text", text: t.slice(start) });
|
|
5284
|
+
}
|
|
5285
|
+
unwind();
|
|
5286
|
+
return root2;
|
|
5287
|
+
}
|
|
5288
|
+
var restoreFailureInjector = null;
|
|
5289
|
+
function restore(out, atoms, mask) {
|
|
5290
|
+
if (restoreFailureInjector !== null && restoreFailureInjector(atoms)) return null;
|
|
5291
|
+
let result = "";
|
|
5292
|
+
let k = 0;
|
|
5293
|
+
let last = 0;
|
|
5294
|
+
for (; ; ) {
|
|
5295
|
+
const idx = out.indexOf(mask, last);
|
|
5296
|
+
if (idx === -1) break;
|
|
5297
|
+
if (k >= atoms.length) return null;
|
|
5298
|
+
result += out.slice(last, idx) + atoms[k];
|
|
5299
|
+
k += 1;
|
|
5300
|
+
last = idx + 1;
|
|
5301
|
+
}
|
|
5302
|
+
return result + out.slice(last);
|
|
5303
|
+
}
|
|
5304
|
+
function emitRun(nodes, mask) {
|
|
5305
|
+
let text = "";
|
|
5306
|
+
const atoms = [];
|
|
5307
|
+
for (const node of nodes) {
|
|
5308
|
+
if (node.type === "text") {
|
|
5309
|
+
text += node.text;
|
|
5310
|
+
} else if (node.type === "atom") {
|
|
5311
|
+
atoms.push(node.text);
|
|
5312
|
+
text += mask;
|
|
5313
|
+
} else {
|
|
5314
|
+
const inner = emitRun(node.children, mask);
|
|
5315
|
+
if (inner === null) return null;
|
|
5316
|
+
const transformed = transformRun(inner.text, false, false, false);
|
|
5317
|
+
const restored = restore(transformed.out, inner.atoms, mask);
|
|
5318
|
+
if (restored === null) return null;
|
|
5319
|
+
atoms.push(node.open + restored + node.close);
|
|
5320
|
+
text += mask;
|
|
5321
|
+
}
|
|
5322
|
+
}
|
|
5323
|
+
return { text, atoms };
|
|
5324
|
+
}
|
|
5325
|
+
function reportRestoreViolation() {
|
|
5326
|
+
if (false) {
|
|
5327
|
+
console.error(
|
|
5328
|
+
"[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."
|
|
5329
|
+
);
|
|
5100
5330
|
}
|
|
5101
|
-
|
|
5331
|
+
}
|
|
5332
|
+
function processSliceDefault(slice, probe, mask) {
|
|
5333
|
+
const segments = splitByProtectedRegions(slice);
|
|
5334
|
+
const parts = [];
|
|
5335
|
+
let quiescent = true;
|
|
5336
|
+
let truncatedAtSeamStart = false;
|
|
5337
|
+
let offset = 0;
|
|
5338
|
+
let i = 0;
|
|
5339
|
+
while (i < segments.length) {
|
|
5340
|
+
const segment = segments[i];
|
|
5341
|
+
if (isHardBoundary(segment.kind)) {
|
|
5342
|
+
parts.push(segment.text);
|
|
5343
|
+
offset += segment.text.length;
|
|
5344
|
+
i += 1;
|
|
5345
|
+
continue;
|
|
5346
|
+
}
|
|
5347
|
+
const runStart = offset;
|
|
5348
|
+
const runSegments = [];
|
|
5349
|
+
while (i < segments.length && !isHardBoundary(segments[i].kind)) {
|
|
5350
|
+
runSegments.push(segments[i]);
|
|
5351
|
+
offset += segments[i].text.length;
|
|
5352
|
+
i += 1;
|
|
5353
|
+
}
|
|
5354
|
+
const before = runStart === 0 ? -1 : slice.charCodeAt(runStart - 1);
|
|
5355
|
+
const runStartsAtLineStart = before === -1 || before === 10 || before === 13;
|
|
5356
|
+
const seamEligible = runStart === 0;
|
|
5357
|
+
const emitted = emitRun(buildRunTree(runSegments), mask);
|
|
5358
|
+
if (emitted === null) {
|
|
5359
|
+
reportRestoreViolation();
|
|
5360
|
+
return { ...processSliceLegacy(slice, probe), degradedReason: "restore-invariant" };
|
|
5361
|
+
}
|
|
5362
|
+
const r = transformRun(emitted.text, probe, runStartsAtLineStart, seamEligible);
|
|
5363
|
+
const restored = restore(r.out, emitted.atoms, mask);
|
|
5364
|
+
if (restored === null) {
|
|
5365
|
+
reportRestoreViolation();
|
|
5366
|
+
return { ...processSliceLegacy(slice, probe), degradedReason: "restore-invariant" };
|
|
5367
|
+
}
|
|
5368
|
+
if (r.tailSensitive) quiescent = false;
|
|
5369
|
+
if (r.truncatedAtSeamStart) truncatedAtSeamStart = true;
|
|
5370
|
+
parts.push(restored);
|
|
5371
|
+
}
|
|
5372
|
+
return { out: parts.join(""), quiescent, truncatedAtSeamStart, degradedReason: null };
|
|
5373
|
+
}
|
|
5374
|
+
function processSlice(slice, options) {
|
|
5375
|
+
if (options.legacy === true) return processSliceLegacy(slice, options.probe);
|
|
5376
|
+
return processSliceDefault(slice, options.probe, options.mask);
|
|
5102
5377
|
}
|
|
5103
5378
|
function isBlankRawLine(text, from, to) {
|
|
5104
5379
|
for (let i = from; i < to; i++) {
|
|
@@ -5114,7 +5389,7 @@ function findRawSafeCut(active) {
|
|
|
5114
5389
|
let backtickHazard = false;
|
|
5115
5390
|
let latentLt = false;
|
|
5116
5391
|
for (const segment of segments) {
|
|
5117
|
-
if (segment.
|
|
5392
|
+
if (segment.kind !== "text") {
|
|
5118
5393
|
if (segment.text.includes(">")) latentLt = false;
|
|
5119
5394
|
offset += segment.text.length;
|
|
5120
5395
|
continue;
|
|
@@ -5149,12 +5424,28 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5149
5424
|
const freezeThreshold = options?.freezeThreshold ?? DEFAULT_FREEZE_ATTEMPT_THRESHOLD;
|
|
5150
5425
|
const onAttempt = options?.onAttempt;
|
|
5151
5426
|
const backoff = options?.backoff ?? true;
|
|
5427
|
+
const onDegrade = options?.onDegrade;
|
|
5152
5428
|
let prevSource = "";
|
|
5153
5429
|
let prevOutput = "";
|
|
5154
5430
|
let frozenSrcEnd = 0;
|
|
5155
5431
|
let frozenOut = "";
|
|
5156
5432
|
let triggered = false;
|
|
5157
5433
|
let nextAttemptLen = 0;
|
|
5434
|
+
let lineageDegraded = false;
|
|
5435
|
+
const presence = new PuaPresence();
|
|
5436
|
+
const commit = (source, out) => {
|
|
5437
|
+
prevSource = source;
|
|
5438
|
+
prevOutput = out;
|
|
5439
|
+
return out;
|
|
5440
|
+
};
|
|
5441
|
+
const legacyWhole = (source) => processSlice(source, { legacy: true, probe: false }).out;
|
|
5442
|
+
const degrade = (source, reason) => {
|
|
5443
|
+
lineageDegraded = true;
|
|
5444
|
+
frozenSrcEnd = 0;
|
|
5445
|
+
frozenOut = "";
|
|
5446
|
+
onDegrade?.(reason);
|
|
5447
|
+
return commit(source, legacyWhole(source));
|
|
5448
|
+
};
|
|
5158
5449
|
return function incrementalPreprocessLaTeX(source) {
|
|
5159
5450
|
if (source === prevSource) return prevOutput;
|
|
5160
5451
|
const isAppend = source.length > prevSource.length && source.startsWith(prevSource);
|
|
@@ -5163,16 +5454,20 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5163
5454
|
frozenOut = "";
|
|
5164
5455
|
triggered = false;
|
|
5165
5456
|
nextAttemptLen = 0;
|
|
5457
|
+
lineageDegraded = false;
|
|
5458
|
+
presence.reset();
|
|
5459
|
+
presence.add(source, 0);
|
|
5460
|
+
} else {
|
|
5461
|
+
presence.add(source, prevSource.length);
|
|
5166
5462
|
}
|
|
5167
5463
|
if (!triggered) {
|
|
5168
5464
|
const checkFrom = isAppend ? Math.max(0, prevSource.length - 1) : 0;
|
|
5169
|
-
if (!hasLatexTrigger(source.slice(checkFrom)))
|
|
5170
|
-
prevSource = source;
|
|
5171
|
-
prevOutput = source;
|
|
5172
|
-
return source;
|
|
5173
|
-
}
|
|
5465
|
+
if (!hasLatexTrigger(source.slice(checkFrom))) return commit(source, source);
|
|
5174
5466
|
triggered = true;
|
|
5175
5467
|
}
|
|
5468
|
+
if (lineageDegraded) return commit(source, legacyWhole(source));
|
|
5469
|
+
const mask = presence.select();
|
|
5470
|
+
if (mask === null) return degrade(source, "mask-exhausted");
|
|
5176
5471
|
let active = source.slice(frozenSrcEnd);
|
|
5177
5472
|
if (active.length > freezeThreshold && active.length >= nextAttemptLen) {
|
|
5178
5473
|
const activeLength = active.length;
|
|
@@ -5187,18 +5482,20 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5187
5482
|
};
|
|
5188
5483
|
const cut = findRawSafeCut(active);
|
|
5189
5484
|
if (cut > 0) {
|
|
5190
|
-
const candidate = processSlice(active.slice(0, cut));
|
|
5485
|
+
const candidate = processSlice(active.slice(0, cut), { probe: true, mask });
|
|
5486
|
+
if (candidate.degradedReason !== null) {
|
|
5487
|
+
onAttempt?.({ activeLength, frozenBytes: 0 });
|
|
5488
|
+
return degrade(source, candidate.degradedReason);
|
|
5489
|
+
}
|
|
5191
5490
|
if (candidate.quiescent) freeze(cut, candidate);
|
|
5192
5491
|
}
|
|
5193
5492
|
nextAttemptLen = advanced || !backoff ? 0 : active.length * 2;
|
|
5194
5493
|
onAttempt?.({ activeLength, frozenBytes });
|
|
5195
5494
|
}
|
|
5196
|
-
const tail = processSlice(active, false);
|
|
5495
|
+
const tail = processSlice(active, { probe: false, mask });
|
|
5496
|
+
if (tail.degradedReason !== null) return degrade(source, tail.degradedReason);
|
|
5197
5497
|
const head = tail.truncatedAtSeamStart ? frozenOut.replace(/\s+$/, "") : frozenOut;
|
|
5198
|
-
|
|
5199
|
-
prevSource = source;
|
|
5200
|
-
prevOutput = out;
|
|
5201
|
-
return out;
|
|
5498
|
+
return commit(source, head + tail.out);
|
|
5202
5499
|
};
|
|
5203
5500
|
}
|
|
5204
5501
|
|
|
@@ -5224,6 +5521,8 @@ function createRemendPreprocessor(options) {
|
|
|
5224
5521
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5225
5522
|
0 && (module.exports = {
|
|
5226
5523
|
DEFAULT_PAYLOAD,
|
|
5524
|
+
ENGINE_PLACEHOLDER_TAGS,
|
|
5525
|
+
ENGINE_PROVENANCE_PROPERTY,
|
|
5227
5526
|
PIPELINE_STAGES,
|
|
5228
5527
|
SENTINEL_FN_CONTENT,
|
|
5229
5528
|
SENTINEL_LINK_URL,
|
|
@@ -5268,6 +5567,7 @@ function createRemendPreprocessor(options) {
|
|
|
5268
5567
|
preprocessLaTeX,
|
|
5269
5568
|
rehypeFooterAdorn,
|
|
5270
5569
|
rehypeRebaseHashLinks,
|
|
5570
|
+
rehypeVerifyEngineTags,
|
|
5271
5571
|
removeComments,
|
|
5272
5572
|
sanitizeCrossChunkUrl,
|
|
5273
5573
|
sanitizeSchema,
|