@ai-react-markdown/engine 2.10.1 → 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 +342 -54
- 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 +342 -54
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +339 -54
- package/dist/index.dev.js.map +1 -1
- package/dist/index.js +339 -54
- 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,20 +5050,22 @@ function escapeLatexPipesInUnclosed(text) {
|
|
|
4988
5050
|
const tail = text.substring(unclosedStart + delimLen);
|
|
4989
5051
|
return before + delim + replaceUnescapedPipes(tail);
|
|
4990
5052
|
}
|
|
4991
|
-
function opensMathFlow(text, pos) {
|
|
5053
|
+
function opensMathFlow(text, pos, runStartsAtLineStart) {
|
|
4992
5054
|
let i = pos;
|
|
4993
5055
|
let spaces = 0;
|
|
4994
|
-
while (i > 0
|
|
5056
|
+
while (i > 0) {
|
|
5057
|
+
const prev = text[i - 1];
|
|
5058
|
+
if (prev === "\n" || prev === "\r") return true;
|
|
4995
5059
|
i -= 1;
|
|
4996
5060
|
if (text[i] !== " ") return false;
|
|
4997
5061
|
spaces += 1;
|
|
4998
5062
|
if (spaces > 3) return false;
|
|
4999
5063
|
}
|
|
5000
|
-
return
|
|
5064
|
+
return runStartsAtLineStart;
|
|
5001
5065
|
}
|
|
5002
|
-
function truncateUnclosedLatexBlock(text, unclosedStart = findUnclosedDelimiterStart(text, "double-only")) {
|
|
5066
|
+
function truncateUnclosedLatexBlock(text, runStartsAtLineStart, unclosedStart = findUnclosedDelimiterStart(text, "double-only")) {
|
|
5003
5067
|
if (unclosedStart === -1) return text;
|
|
5004
|
-
if (!opensMathFlow(text, unclosedStart)) return text;
|
|
5068
|
+
if (!opensMathFlow(text, unclosedStart, runStartsAtLineStart)) return text;
|
|
5005
5069
|
return text.substring(0, unclosedStart).trimEnd();
|
|
5006
5070
|
}
|
|
5007
5071
|
function escapeTextUnderscores(text) {
|
|
@@ -5046,7 +5110,8 @@ function convertSingleToDoubleDollar(text) {
|
|
|
5046
5110
|
}
|
|
5047
5111
|
function preprocessLaTeX(str) {
|
|
5048
5112
|
if (!hasLatexTrigger(str)) return str;
|
|
5049
|
-
|
|
5113
|
+
const mask = selectMask(str);
|
|
5114
|
+
return (mask === null ? processSlice(str, { legacy: true, probe: false }) : processSlice(str, { probe: false, mask })).out;
|
|
5050
5115
|
}
|
|
5051
5116
|
function hasLatexTrigger(str) {
|
|
5052
5117
|
return str.includes("$") || str.includes("\\[") || str.includes("\\(");
|
|
@@ -5075,42 +5140,240 @@ function hasUnclosedTextCommand(text) {
|
|
|
5075
5140
|
}
|
|
5076
5141
|
var RESIDUAL_OPEN_BRACKET_RE = /(?<!!)\\\[/;
|
|
5077
5142
|
var LEADING_DOUBLE_DOLLAR_RE = /^\s*\$\$/;
|
|
5078
|
-
|
|
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) {
|
|
5079
5211
|
const segments = splitByProtectedRegions(slice);
|
|
5080
5212
|
const parts = [];
|
|
5081
5213
|
let quiescent = true;
|
|
5082
5214
|
let truncatedAtSeamStart = false;
|
|
5083
5215
|
for (let index = 0; index < segments.length; index++) {
|
|
5084
5216
|
const segment = segments[index];
|
|
5085
|
-
if (segment.
|
|
5217
|
+
if (segment.kind !== "text") {
|
|
5086
5218
|
parts.push(segment.text);
|
|
5087
5219
|
continue;
|
|
5088
5220
|
}
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
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 });
|
|
5107
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 });
|
|
5108
5268
|
}
|
|
5269
|
+
continue;
|
|
5109
5270
|
}
|
|
5110
|
-
|
|
5111
|
-
|
|
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
|
+
);
|
|
5112
5330
|
}
|
|
5113
|
-
|
|
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);
|
|
5114
5377
|
}
|
|
5115
5378
|
function isBlankRawLine(text, from, to) {
|
|
5116
5379
|
for (let i = from; i < to; i++) {
|
|
@@ -5126,7 +5389,7 @@ function findRawSafeCut(active) {
|
|
|
5126
5389
|
let backtickHazard = false;
|
|
5127
5390
|
let latentLt = false;
|
|
5128
5391
|
for (const segment of segments) {
|
|
5129
|
-
if (segment.
|
|
5392
|
+
if (segment.kind !== "text") {
|
|
5130
5393
|
if (segment.text.includes(">")) latentLt = false;
|
|
5131
5394
|
offset += segment.text.length;
|
|
5132
5395
|
continue;
|
|
@@ -5161,12 +5424,28 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5161
5424
|
const freezeThreshold = options?.freezeThreshold ?? DEFAULT_FREEZE_ATTEMPT_THRESHOLD;
|
|
5162
5425
|
const onAttempt = options?.onAttempt;
|
|
5163
5426
|
const backoff = options?.backoff ?? true;
|
|
5427
|
+
const onDegrade = options?.onDegrade;
|
|
5164
5428
|
let prevSource = "";
|
|
5165
5429
|
let prevOutput = "";
|
|
5166
5430
|
let frozenSrcEnd = 0;
|
|
5167
5431
|
let frozenOut = "";
|
|
5168
5432
|
let triggered = false;
|
|
5169
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
|
+
};
|
|
5170
5449
|
return function incrementalPreprocessLaTeX(source) {
|
|
5171
5450
|
if (source === prevSource) return prevOutput;
|
|
5172
5451
|
const isAppend = source.length > prevSource.length && source.startsWith(prevSource);
|
|
@@ -5175,16 +5454,20 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5175
5454
|
frozenOut = "";
|
|
5176
5455
|
triggered = false;
|
|
5177
5456
|
nextAttemptLen = 0;
|
|
5457
|
+
lineageDegraded = false;
|
|
5458
|
+
presence.reset();
|
|
5459
|
+
presence.add(source, 0);
|
|
5460
|
+
} else {
|
|
5461
|
+
presence.add(source, prevSource.length);
|
|
5178
5462
|
}
|
|
5179
5463
|
if (!triggered) {
|
|
5180
5464
|
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
|
-
}
|
|
5465
|
+
if (!hasLatexTrigger(source.slice(checkFrom))) return commit(source, source);
|
|
5186
5466
|
triggered = true;
|
|
5187
5467
|
}
|
|
5468
|
+
if (lineageDegraded) return commit(source, legacyWhole(source));
|
|
5469
|
+
const mask = presence.select();
|
|
5470
|
+
if (mask === null) return degrade(source, "mask-exhausted");
|
|
5188
5471
|
let active = source.slice(frozenSrcEnd);
|
|
5189
5472
|
if (active.length > freezeThreshold && active.length >= nextAttemptLen) {
|
|
5190
5473
|
const activeLength = active.length;
|
|
@@ -5199,18 +5482,20 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5199
5482
|
};
|
|
5200
5483
|
const cut = findRawSafeCut(active);
|
|
5201
5484
|
if (cut > 0) {
|
|
5202
|
-
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
|
+
}
|
|
5203
5490
|
if (candidate.quiescent) freeze(cut, candidate);
|
|
5204
5491
|
}
|
|
5205
5492
|
nextAttemptLen = advanced || !backoff ? 0 : active.length * 2;
|
|
5206
5493
|
onAttempt?.({ activeLength, frozenBytes });
|
|
5207
5494
|
}
|
|
5208
|
-
const tail = processSlice(active, false);
|
|
5495
|
+
const tail = processSlice(active, { probe: false, mask });
|
|
5496
|
+
if (tail.degradedReason !== null) return degrade(source, tail.degradedReason);
|
|
5209
5497
|
const head = tail.truncatedAtSeamStart ? frozenOut.replace(/\s+$/, "") : frozenOut;
|
|
5210
|
-
|
|
5211
|
-
prevSource = source;
|
|
5212
|
-
prevOutput = out;
|
|
5213
|
-
return out;
|
|
5498
|
+
return commit(source, head + tail.out);
|
|
5214
5499
|
};
|
|
5215
5500
|
}
|
|
5216
5501
|
|
|
@@ -5236,6 +5521,8 @@ function createRemendPreprocessor(options) {
|
|
|
5236
5521
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5237
5522
|
0 && (module.exports = {
|
|
5238
5523
|
DEFAULT_PAYLOAD,
|
|
5524
|
+
ENGINE_PLACEHOLDER_TAGS,
|
|
5525
|
+
ENGINE_PROVENANCE_PROPERTY,
|
|
5239
5526
|
PIPELINE_STAGES,
|
|
5240
5527
|
SENTINEL_FN_CONTENT,
|
|
5241
5528
|
SENTINEL_LINK_URL,
|
|
@@ -5280,6 +5567,7 @@ function createRemendPreprocessor(options) {
|
|
|
5280
5567
|
preprocessLaTeX,
|
|
5281
5568
|
rehypeFooterAdorn,
|
|
5282
5569
|
rehypeRebaseHashLinks,
|
|
5570
|
+
rehypeVerifyEngineTags,
|
|
5283
5571
|
removeComments,
|
|
5284
5572
|
sanitizeCrossChunkUrl,
|
|
5285
5573
|
sanitizeSchema,
|