@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/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,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,
|
|
@@ -2797,6 +2800,44 @@ function rehypeUnwrapCrossChunkImages() {
|
|
|
2797
2800
|
|
|
2798
2801
|
// src/components/pluginChain.ts
|
|
2799
2802
|
var import_rehype_sanitize = __toESM(require("rehype-sanitize"), 1);
|
|
2803
|
+
|
|
2804
|
+
// src/components/rehypeVerifyEngineTags.ts
|
|
2805
|
+
var ENGINE_PLACEHOLDER_TAGS = /* @__PURE__ */ new Set([
|
|
2806
|
+
"footnote-sup",
|
|
2807
|
+
"cross-chunk-link",
|
|
2808
|
+
"cross-chunk-image"
|
|
2809
|
+
]);
|
|
2810
|
+
var ENGINE_PROVENANCE_PROPERTY = "engineProvenance";
|
|
2811
|
+
function walk(parent, provenance) {
|
|
2812
|
+
const children = parent.children;
|
|
2813
|
+
let i = 0;
|
|
2814
|
+
while (i < children.length) {
|
|
2815
|
+
const node = children[i];
|
|
2816
|
+
if (node.type === "element" && ENGINE_PLACEHOLDER_TAGS.has(node.tagName)) {
|
|
2817
|
+
const props = node.properties ?? {};
|
|
2818
|
+
const stamped = props[ENGINE_PROVENANCE_PROPERTY];
|
|
2819
|
+
const genuine = provenance !== "" && typeof stamped === "string" && stamped === provenance;
|
|
2820
|
+
if (genuine) {
|
|
2821
|
+
delete props[ENGINE_PROVENANCE_PROPERTY];
|
|
2822
|
+
walk(node, provenance);
|
|
2823
|
+
i += 1;
|
|
2824
|
+
} else {
|
|
2825
|
+
children.splice(i, 1, ...node.children);
|
|
2826
|
+
}
|
|
2827
|
+
continue;
|
|
2828
|
+
}
|
|
2829
|
+
if (node.type === "element") walk(node, provenance);
|
|
2830
|
+
i += 1;
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
function rehypeVerifyEngineTags(options) {
|
|
2834
|
+
const provenance = options?.provenance ?? "";
|
|
2835
|
+
return function transformer(tree) {
|
|
2836
|
+
walk(tree, provenance);
|
|
2837
|
+
};
|
|
2838
|
+
}
|
|
2839
|
+
|
|
2840
|
+
// src/components/pluginChain.ts
|
|
2800
2841
|
var import_remark_breaks = __toESM(require("remark-breaks"), 1);
|
|
2801
2842
|
var import_remark_cjk_friendly = __toESM(require("remark-cjk-friendly"), 1);
|
|
2802
2843
|
var import_remark_cjk_friendly_gfm_strikethrough = __toESM(require("remark-cjk-friendly-gfm-strikethrough"), 1);
|
|
@@ -2902,10 +2943,13 @@ function buildCoreRemarkPlugins(enginePlugins) {
|
|
|
2902
2943
|
...DISPLAY_OPTIMIZE_CHAIN.filter(([name]) => selected.has(name)).map(([, plugin]) => plugin)
|
|
2903
2944
|
];
|
|
2904
2945
|
}
|
|
2905
|
-
function buildCoreRehypePlugins(sanitizeSchema2, clobberPrefix) {
|
|
2946
|
+
function buildCoreRehypePlugins(sanitizeSchema2, clobberPrefix, options) {
|
|
2906
2947
|
return [
|
|
2907
2948
|
// Allow raw HTML through so rehype-sanitize can handle it.
|
|
2908
2949
|
[import_rehype_raw.default, { passThrough: [] }],
|
|
2950
|
+
// Unwrap forged engine placeholders BEFORE sanitize admits their tag
|
|
2951
|
+
// names. Only when the caller holds a credential (see the option's doc).
|
|
2952
|
+
...options ? [[rehypeVerifyEngineTags, { provenance: options.provenance }]] : [],
|
|
2909
2953
|
// Sanitize HTML while allowing <mark> (highlight), KaTeX class names,
|
|
2910
2954
|
// and any extra protocols the caller permitted via the `sanitizeSchema`
|
|
2911
2955
|
// prop. Override `clobberPrefix` with the instance-scoped value — the
|
|
@@ -2945,6 +2989,10 @@ function buildCoreRemarkRehypeOptions(enableDefinitionList) {
|
|
|
2945
2989
|
}
|
|
2946
2990
|
|
|
2947
2991
|
// src/components/customMdastHandlers.ts
|
|
2992
|
+
function provenanceProps(s) {
|
|
2993
|
+
const provenance = s.options.provenance;
|
|
2994
|
+
return typeof provenance === "string" ? { engineProvenance: provenance } : {};
|
|
2995
|
+
}
|
|
2948
2996
|
function localDefProps(s, id) {
|
|
2949
2997
|
const def = s.definitionById.get(id);
|
|
2950
2998
|
if (!def || typeof def.url !== "string" || def.url === SENTINEL_LINK_URL) return {};
|
|
@@ -2983,7 +3031,8 @@ function buildCrossChunkHandlers() {
|
|
|
2983
3031
|
label: node.label ?? node.identifier,
|
|
2984
3032
|
referenceType: node.referenceType,
|
|
2985
3033
|
documentId: s.options.documentId,
|
|
2986
|
-
...localDefProps(s, id)
|
|
3034
|
+
...localDefProps(s, id),
|
|
3035
|
+
...provenanceProps(s)
|
|
2987
3036
|
},
|
|
2988
3037
|
children: s.all(node)
|
|
2989
3038
|
};
|
|
@@ -3001,7 +3050,8 @@ function buildCrossChunkHandlers() {
|
|
|
3001
3050
|
referenceType: node.referenceType,
|
|
3002
3051
|
alt: node.alt ?? "",
|
|
3003
3052
|
documentId: s.options.documentId,
|
|
3004
|
-
...localDefProps(s, id)
|
|
3053
|
+
...localDefProps(s, id),
|
|
3054
|
+
...provenanceProps(s)
|
|
3005
3055
|
},
|
|
3006
3056
|
children: []
|
|
3007
3057
|
};
|
|
@@ -3018,7 +3068,8 @@ function buildCrossChunkHandlers() {
|
|
|
3018
3068
|
properties: {
|
|
3019
3069
|
label: node.identifier,
|
|
3020
3070
|
localOccurrence,
|
|
3021
|
-
documentId: s.options.documentId
|
|
3071
|
+
documentId: s.options.documentId,
|
|
3072
|
+
...provenanceProps(s)
|
|
3022
3073
|
},
|
|
3023
3074
|
children: []
|
|
3024
3075
|
};
|
|
@@ -3036,7 +3087,8 @@ function buildCrossChunkHandlers() {
|
|
|
3036
3087
|
// first client frame), where the local synthetic footer is what
|
|
3037
3088
|
// renders, so marks and footer agree (core-render-02).
|
|
3038
3089
|
localNumber: s.footnoteOrder.indexOf(id) + 1,
|
|
3039
|
-
documentId: s.options.documentId
|
|
3090
|
+
documentId: s.options.documentId,
|
|
3091
|
+
...provenanceProps(s)
|
|
3040
3092
|
},
|
|
3041
3093
|
children: []
|
|
3042
3094
|
};
|
|
@@ -4708,6 +4760,12 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4708
4760
|
};
|
|
4709
4761
|
|
|
4710
4762
|
// src/preprocessors/latex.ts
|
|
4763
|
+
function isHardBoundary(kind) {
|
|
4764
|
+
return kind === "code" || kind === "literal" || kind === "multilineTag";
|
|
4765
|
+
}
|
|
4766
|
+
function hasLineEnding(text) {
|
|
4767
|
+
return text.includes("\n") || text.includes("\r");
|
|
4768
|
+
}
|
|
4711
4769
|
function getRepeatedMarkerLength(content, start, marker) {
|
|
4712
4770
|
let end = start;
|
|
4713
4771
|
while (end < content.length && content[end] === marker) {
|
|
@@ -4775,11 +4833,11 @@ function splitByProtectedRegions(content) {
|
|
|
4775
4833
|
let multilineFenceMarker = null;
|
|
4776
4834
|
let multilineFenceLength = 0;
|
|
4777
4835
|
let multilineFenceIndent = 0;
|
|
4778
|
-
function pushProtected(start, end) {
|
|
4836
|
+
function pushProtected(start, end, kind) {
|
|
4779
4837
|
if (start > lastIndex) {
|
|
4780
|
-
segments.push({ text: content.substring(lastIndex, start)
|
|
4838
|
+
segments.push({ kind: "text", text: content.substring(lastIndex, start) });
|
|
4781
4839
|
}
|
|
4782
|
-
segments.push({ text: content.substring(start, end)
|
|
4840
|
+
segments.push({ kind, text: content.substring(start, end) });
|
|
4783
4841
|
lastIndex = end;
|
|
4784
4842
|
}
|
|
4785
4843
|
let i = 0;
|
|
@@ -4790,7 +4848,7 @@ function splitByProtectedRegions(content) {
|
|
|
4790
4848
|
const runLen = getRepeatedMarkerLength(content, i, multilineFenceMarker);
|
|
4791
4849
|
const closerIndent = lineIndentBefore(content, i);
|
|
4792
4850
|
if (runLen >= multilineFenceLength && closerIndent !== -1 && closerIndent <= multilineFenceIndent + 3 && restOfLineIsBlank(content, i + runLen)) {
|
|
4793
|
-
pushProtected(multilineStart, i + runLen);
|
|
4851
|
+
pushProtected(multilineStart, i + runLen, "code");
|
|
4794
4852
|
multilineStart = -1;
|
|
4795
4853
|
multilineFenceMarker = null;
|
|
4796
4854
|
multilineFenceLength = 0;
|
|
@@ -4817,7 +4875,7 @@ function splitByProtectedRegions(content) {
|
|
|
4817
4875
|
if (char === "`") {
|
|
4818
4876
|
const closeIdx = findClosingBacktickRun(content, i + runLen, runLen);
|
|
4819
4877
|
if (closeIdx !== -1) {
|
|
4820
|
-
pushProtected(i, closeIdx + runLen);
|
|
4878
|
+
pushProtected(i, closeIdx + runLen, "code");
|
|
4821
4879
|
i = closeIdx + runLen;
|
|
4822
4880
|
continue;
|
|
4823
4881
|
}
|
|
@@ -4842,7 +4900,11 @@ function splitByProtectedRegions(content) {
|
|
|
4842
4900
|
endIndex = content.length;
|
|
4843
4901
|
}
|
|
4844
4902
|
}
|
|
4845
|
-
pushProtected(
|
|
4903
|
+
pushProtected(
|
|
4904
|
+
i,
|
|
4905
|
+
endIndex,
|
|
4906
|
+
isOpeningPairedTag ? "literal" : hasLineEnding(content.substring(i, endIndex)) ? "multilineTag" : "tag"
|
|
4907
|
+
);
|
|
4846
4908
|
i = endIndex;
|
|
4847
4909
|
continue;
|
|
4848
4910
|
}
|
|
@@ -4850,10 +4912,10 @@ function splitByProtectedRegions(content) {
|
|
|
4850
4912
|
i += 1;
|
|
4851
4913
|
}
|
|
4852
4914
|
if (multilineStart !== -1) {
|
|
4853
|
-
pushProtected(multilineStart, content.length);
|
|
4915
|
+
pushProtected(multilineStart, content.length, "code");
|
|
4854
4916
|
}
|
|
4855
4917
|
if (lastIndex < content.length) {
|
|
4856
|
-
segments.push({ text: content.substring(lastIndex)
|
|
4918
|
+
segments.push({ kind: "text", text: content.substring(lastIndex) });
|
|
4857
4919
|
}
|
|
4858
4920
|
return segments;
|
|
4859
4921
|
}
|
|
@@ -5007,8 +5069,22 @@ function escapeLatexPipesInUnclosed(text) {
|
|
|
5007
5069
|
const tail = text.substring(unclosedStart + delimLen);
|
|
5008
5070
|
return before + delim + replaceUnescapedPipes(tail);
|
|
5009
5071
|
}
|
|
5010
|
-
function
|
|
5072
|
+
function opensMathFlow(text, pos, runStartsAtLineStart) {
|
|
5073
|
+
let i = pos;
|
|
5074
|
+
let spaces = 0;
|
|
5075
|
+
while (i > 0) {
|
|
5076
|
+
const prev = text[i - 1];
|
|
5077
|
+
if (prev === "\n" || prev === "\r") return true;
|
|
5078
|
+
i -= 1;
|
|
5079
|
+
if (text[i] !== " ") return false;
|
|
5080
|
+
spaces += 1;
|
|
5081
|
+
if (spaces > 3) return false;
|
|
5082
|
+
}
|
|
5083
|
+
return runStartsAtLineStart;
|
|
5084
|
+
}
|
|
5085
|
+
function truncateUnclosedLatexBlock(text, runStartsAtLineStart, unclosedStart = findUnclosedDelimiterStart(text, "double-only")) {
|
|
5011
5086
|
if (unclosedStart === -1) return text;
|
|
5087
|
+
if (!opensMathFlow(text, unclosedStart, runStartsAtLineStart)) return text;
|
|
5012
5088
|
return text.substring(0, unclosedStart).trimEnd();
|
|
5013
5089
|
}
|
|
5014
5090
|
function escapeTextUnderscores(text) {
|
|
@@ -5053,7 +5129,8 @@ function convertSingleToDoubleDollar(text) {
|
|
|
5053
5129
|
}
|
|
5054
5130
|
function preprocessLaTeX(str) {
|
|
5055
5131
|
if (!hasLatexTrigger(str)) return str;
|
|
5056
|
-
|
|
5132
|
+
const mask = selectMask(str);
|
|
5133
|
+
return (mask === null ? processSlice(str, { legacy: true, probe: false }) : processSlice(str, { probe: false, mask })).out;
|
|
5057
5134
|
}
|
|
5058
5135
|
function hasLatexTrigger(str) {
|
|
5059
5136
|
return str.includes("$") || str.includes("\\[") || str.includes("\\(");
|
|
@@ -5082,42 +5159,240 @@ function hasUnclosedTextCommand(text) {
|
|
|
5082
5159
|
}
|
|
5083
5160
|
var RESIDUAL_OPEN_BRACKET_RE = /(?<!!)\\\[/;
|
|
5084
5161
|
var LEADING_DOUBLE_DOLLAR_RE = /^\s*\$\$/;
|
|
5085
|
-
|
|
5162
|
+
var PUA_START = 57344;
|
|
5163
|
+
var PUA_END = 63743;
|
|
5164
|
+
var PUA_SIZE = PUA_END - PUA_START + 1;
|
|
5165
|
+
function selectMask(source) {
|
|
5166
|
+
const first = String.fromCharCode(PUA_START);
|
|
5167
|
+
if (source.indexOf(first) === -1) return first;
|
|
5168
|
+
const seen = new Uint8Array(PUA_SIZE);
|
|
5169
|
+
for (let i = 0; i < source.length; i++) {
|
|
5170
|
+
const c = source.charCodeAt(i);
|
|
5171
|
+
if (c >= PUA_START && c <= PUA_END) seen[c - PUA_START] = 1;
|
|
5172
|
+
}
|
|
5173
|
+
for (let k = 0; k < PUA_SIZE; k++) if (seen[k] === 0) return String.fromCharCode(PUA_START + k);
|
|
5174
|
+
return null;
|
|
5175
|
+
}
|
|
5176
|
+
var PuaPresence = class {
|
|
5177
|
+
bits = new Uint8Array(PUA_SIZE);
|
|
5178
|
+
distinct = 0;
|
|
5179
|
+
reset() {
|
|
5180
|
+
this.bits.fill(0);
|
|
5181
|
+
this.distinct = 0;
|
|
5182
|
+
}
|
|
5183
|
+
add(text, from) {
|
|
5184
|
+
for (let i = from; i < text.length; i++) {
|
|
5185
|
+
const c = text.charCodeAt(i);
|
|
5186
|
+
if (c >= PUA_START && c <= PUA_END) {
|
|
5187
|
+
const k = c - PUA_START;
|
|
5188
|
+
if (this.bits[k] === 0) {
|
|
5189
|
+
this.bits[k] = 1;
|
|
5190
|
+
this.distinct += 1;
|
|
5191
|
+
}
|
|
5192
|
+
}
|
|
5193
|
+
}
|
|
5194
|
+
}
|
|
5195
|
+
select() {
|
|
5196
|
+
if (this.distinct === 0) return String.fromCharCode(PUA_START);
|
|
5197
|
+
if (this.distinct >= PUA_SIZE) return null;
|
|
5198
|
+
for (let k = 0; k < PUA_SIZE; k++) if (this.bits[k] === 0) return String.fromCharCode(PUA_START + k);
|
|
5199
|
+
return null;
|
|
5200
|
+
}
|
|
5201
|
+
};
|
|
5202
|
+
function transformRun(input, probe, runStartsAtLineStart, seamEligible) {
|
|
5203
|
+
let text = input;
|
|
5204
|
+
let tailSensitive = false;
|
|
5205
|
+
let truncatedAtSeamStart = false;
|
|
5206
|
+
text = escapeMhchemCommands(text);
|
|
5207
|
+
text = escapeCurrencyDollarSigns(text);
|
|
5208
|
+
text = convertLatexDelimiters(text);
|
|
5209
|
+
if (probe && RESIDUAL_OPEN_BRACKET_RE.test(text)) tailSensitive = true;
|
|
5210
|
+
text = escapeLatexPipes(text);
|
|
5211
|
+
if (probe && findUnclosedDelimiterStart(text, "both") !== -1) tailSensitive = true;
|
|
5212
|
+
text = escapeLatexPipesInUnclosed(text);
|
|
5213
|
+
if (probe && hasUnclosedTextCommand(text)) tailSensitive = true;
|
|
5214
|
+
text = escapeTextUnderscores(text);
|
|
5215
|
+
text = convertSingleToDoubleDollar(text);
|
|
5216
|
+
let unclosedDouble;
|
|
5217
|
+
if (probe || seamEligible && LEADING_DOUBLE_DOLLAR_RE.test(text)) {
|
|
5218
|
+
unclosedDouble = findUnclosedDelimiterStart(text, "double-only");
|
|
5219
|
+
if (unclosedDouble !== -1) {
|
|
5220
|
+
tailSensitive = true;
|
|
5221
|
+
if (seamEligible && opensMathFlow(text, unclosedDouble, runStartsAtLineStart) && text.slice(0, unclosedDouble).trim() === "") {
|
|
5222
|
+
truncatedAtSeamStart = true;
|
|
5223
|
+
}
|
|
5224
|
+
}
|
|
5225
|
+
}
|
|
5226
|
+
text = truncateUnclosedLatexBlock(text, runStartsAtLineStart, unclosedDouble);
|
|
5227
|
+
return { out: text, tailSensitive, truncatedAtSeamStart };
|
|
5228
|
+
}
|
|
5229
|
+
function processSliceLegacy(slice, probe) {
|
|
5086
5230
|
const segments = splitByProtectedRegions(slice);
|
|
5087
5231
|
const parts = [];
|
|
5088
5232
|
let quiescent = true;
|
|
5089
5233
|
let truncatedAtSeamStart = false;
|
|
5090
5234
|
for (let index = 0; index < segments.length; index++) {
|
|
5091
5235
|
const segment = segments[index];
|
|
5092
|
-
if (segment.
|
|
5236
|
+
if (segment.kind !== "text") {
|
|
5093
5237
|
parts.push(segment.text);
|
|
5094
5238
|
continue;
|
|
5095
5239
|
}
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5240
|
+
const r = transformRun(segment.text, probe, true, index === 0);
|
|
5241
|
+
if (r.tailSensitive) quiescent = false;
|
|
5242
|
+
if (r.truncatedAtSeamStart) truncatedAtSeamStart = true;
|
|
5243
|
+
parts.push(r.out);
|
|
5244
|
+
}
|
|
5245
|
+
return { out: parts.join(""), quiescent, truncatedAtSeamStart, degradedReason: null };
|
|
5246
|
+
}
|
|
5247
|
+
var SCOPE_DEPTH_CAP = 8;
|
|
5248
|
+
var VOID_TAGS2 = /* @__PURE__ */ new Set(["br", "hr", "img", "wbr", "input", "source"]);
|
|
5249
|
+
var TAG_NAME_RE = /^<(\/?)([A-Za-z][A-Za-z0-9]*)/;
|
|
5250
|
+
function tagInfo(tag) {
|
|
5251
|
+
const m = TAG_NAME_RE.exec(tag);
|
|
5252
|
+
const closing = m?.[1] === "/";
|
|
5253
|
+
const name = (m?.[2] ?? "").toLowerCase();
|
|
5254
|
+
const opensScope = !closing && !tag.endsWith("/>") && !VOID_TAGS2.has(name);
|
|
5255
|
+
return { name, closing, opensScope };
|
|
5256
|
+
}
|
|
5257
|
+
function buildRunTree(segments) {
|
|
5258
|
+
const root2 = [];
|
|
5259
|
+
const stack = [];
|
|
5260
|
+
const current = () => stack.length > 0 ? stack[stack.length - 1].children : root2;
|
|
5261
|
+
const unwind = () => {
|
|
5262
|
+
while (stack.length > 0) {
|
|
5263
|
+
const frame = stack.pop();
|
|
5264
|
+
current().push({ type: "atom", text: frame.open }, ...frame.children);
|
|
5265
|
+
}
|
|
5266
|
+
};
|
|
5267
|
+
for (const segment of segments) {
|
|
5268
|
+
if (segment.kind === "tag") {
|
|
5269
|
+
const info = tagInfo(segment.text);
|
|
5270
|
+
if (info.closing) {
|
|
5271
|
+
const top = stack[stack.length - 1];
|
|
5272
|
+
if (top !== void 0 && top.name === info.name) {
|
|
5273
|
+
stack.pop();
|
|
5274
|
+
const parent = current();
|
|
5275
|
+
if (top.suppressed) {
|
|
5276
|
+
parent.push({ type: "atom", text: top.open }, ...top.children, { type: "atom", text: segment.text });
|
|
5277
|
+
} else {
|
|
5278
|
+
parent.push({ type: "scope", open: top.open, close: segment.text, children: top.children });
|
|
5279
|
+
}
|
|
5280
|
+
} else {
|
|
5281
|
+
current().push({ type: "atom", text: segment.text });
|
|
5114
5282
|
}
|
|
5283
|
+
} else if (info.opensScope) {
|
|
5284
|
+
stack.push({ name: info.name, open: segment.text, suppressed: stack.length >= SCOPE_DEPTH_CAP, children: [] });
|
|
5285
|
+
} else {
|
|
5286
|
+
current().push({ type: "atom", text: segment.text });
|
|
5115
5287
|
}
|
|
5288
|
+
continue;
|
|
5116
5289
|
}
|
|
5117
|
-
|
|
5118
|
-
|
|
5290
|
+
const t = segment.text;
|
|
5291
|
+
let start = 0;
|
|
5292
|
+
for (let i = 0; i < t.length; i++) {
|
|
5293
|
+
const c = t.charCodeAt(i);
|
|
5294
|
+
if (c !== 10 && c !== 13) continue;
|
|
5295
|
+
if (i > start) current().push({ type: "text", text: t.slice(start, i) });
|
|
5296
|
+
const end = c === 13 && t.charCodeAt(i + 1) === 10 ? i + 2 : i + 1;
|
|
5297
|
+
unwind();
|
|
5298
|
+
root2.push({ type: "text", text: t.slice(i, end) });
|
|
5299
|
+
start = end;
|
|
5300
|
+
i = end - 1;
|
|
5301
|
+
}
|
|
5302
|
+
if (start < t.length) current().push({ type: "text", text: t.slice(start) });
|
|
5303
|
+
}
|
|
5304
|
+
unwind();
|
|
5305
|
+
return root2;
|
|
5306
|
+
}
|
|
5307
|
+
var restoreFailureInjector = null;
|
|
5308
|
+
function restore(out, atoms, mask) {
|
|
5309
|
+
if (restoreFailureInjector !== null && restoreFailureInjector(atoms)) return null;
|
|
5310
|
+
let result = "";
|
|
5311
|
+
let k = 0;
|
|
5312
|
+
let last = 0;
|
|
5313
|
+
for (; ; ) {
|
|
5314
|
+
const idx = out.indexOf(mask, last);
|
|
5315
|
+
if (idx === -1) break;
|
|
5316
|
+
if (k >= atoms.length) return null;
|
|
5317
|
+
result += out.slice(last, idx) + atoms[k];
|
|
5318
|
+
k += 1;
|
|
5319
|
+
last = idx + 1;
|
|
5320
|
+
}
|
|
5321
|
+
return result + out.slice(last);
|
|
5322
|
+
}
|
|
5323
|
+
function emitRun(nodes, mask) {
|
|
5324
|
+
let text = "";
|
|
5325
|
+
const atoms = [];
|
|
5326
|
+
for (const node of nodes) {
|
|
5327
|
+
if (node.type === "text") {
|
|
5328
|
+
text += node.text;
|
|
5329
|
+
} else if (node.type === "atom") {
|
|
5330
|
+
atoms.push(node.text);
|
|
5331
|
+
text += mask;
|
|
5332
|
+
} else {
|
|
5333
|
+
const inner = emitRun(node.children, mask);
|
|
5334
|
+
if (inner === null) return null;
|
|
5335
|
+
const transformed = transformRun(inner.text, false, false, false);
|
|
5336
|
+
const restored = restore(transformed.out, inner.atoms, mask);
|
|
5337
|
+
if (restored === null) return null;
|
|
5338
|
+
atoms.push(node.open + restored + node.close);
|
|
5339
|
+
text += mask;
|
|
5340
|
+
}
|
|
5341
|
+
}
|
|
5342
|
+
return { text, atoms };
|
|
5343
|
+
}
|
|
5344
|
+
function reportRestoreViolation() {
|
|
5345
|
+
if (true) {
|
|
5346
|
+
console.error(
|
|
5347
|
+
"[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."
|
|
5348
|
+
);
|
|
5119
5349
|
}
|
|
5120
|
-
|
|
5350
|
+
}
|
|
5351
|
+
function processSliceDefault(slice, probe, mask) {
|
|
5352
|
+
const segments = splitByProtectedRegions(slice);
|
|
5353
|
+
const parts = [];
|
|
5354
|
+
let quiescent = true;
|
|
5355
|
+
let truncatedAtSeamStart = false;
|
|
5356
|
+
let offset = 0;
|
|
5357
|
+
let i = 0;
|
|
5358
|
+
while (i < segments.length) {
|
|
5359
|
+
const segment = segments[i];
|
|
5360
|
+
if (isHardBoundary(segment.kind)) {
|
|
5361
|
+
parts.push(segment.text);
|
|
5362
|
+
offset += segment.text.length;
|
|
5363
|
+
i += 1;
|
|
5364
|
+
continue;
|
|
5365
|
+
}
|
|
5366
|
+
const runStart = offset;
|
|
5367
|
+
const runSegments = [];
|
|
5368
|
+
while (i < segments.length && !isHardBoundary(segments[i].kind)) {
|
|
5369
|
+
runSegments.push(segments[i]);
|
|
5370
|
+
offset += segments[i].text.length;
|
|
5371
|
+
i += 1;
|
|
5372
|
+
}
|
|
5373
|
+
const before = runStart === 0 ? -1 : slice.charCodeAt(runStart - 1);
|
|
5374
|
+
const runStartsAtLineStart = before === -1 || before === 10 || before === 13;
|
|
5375
|
+
const seamEligible = runStart === 0;
|
|
5376
|
+
const emitted = emitRun(buildRunTree(runSegments), mask);
|
|
5377
|
+
if (emitted === null) {
|
|
5378
|
+
reportRestoreViolation();
|
|
5379
|
+
return { ...processSliceLegacy(slice, probe), degradedReason: "restore-invariant" };
|
|
5380
|
+
}
|
|
5381
|
+
const r = transformRun(emitted.text, probe, runStartsAtLineStart, seamEligible);
|
|
5382
|
+
const restored = restore(r.out, emitted.atoms, mask);
|
|
5383
|
+
if (restored === null) {
|
|
5384
|
+
reportRestoreViolation();
|
|
5385
|
+
return { ...processSliceLegacy(slice, probe), degradedReason: "restore-invariant" };
|
|
5386
|
+
}
|
|
5387
|
+
if (r.tailSensitive) quiescent = false;
|
|
5388
|
+
if (r.truncatedAtSeamStart) truncatedAtSeamStart = true;
|
|
5389
|
+
parts.push(restored);
|
|
5390
|
+
}
|
|
5391
|
+
return { out: parts.join(""), quiescent, truncatedAtSeamStart, degradedReason: null };
|
|
5392
|
+
}
|
|
5393
|
+
function processSlice(slice, options) {
|
|
5394
|
+
if (options.legacy === true) return processSliceLegacy(slice, options.probe);
|
|
5395
|
+
return processSliceDefault(slice, options.probe, options.mask);
|
|
5121
5396
|
}
|
|
5122
5397
|
function isBlankRawLine(text, from, to) {
|
|
5123
5398
|
for (let i = from; i < to; i++) {
|
|
@@ -5133,7 +5408,7 @@ function findRawSafeCut(active) {
|
|
|
5133
5408
|
let backtickHazard = false;
|
|
5134
5409
|
let latentLt = false;
|
|
5135
5410
|
for (const segment of segments) {
|
|
5136
|
-
if (segment.
|
|
5411
|
+
if (segment.kind !== "text") {
|
|
5137
5412
|
if (segment.text.includes(">")) latentLt = false;
|
|
5138
5413
|
offset += segment.text.length;
|
|
5139
5414
|
continue;
|
|
@@ -5168,12 +5443,28 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5168
5443
|
const freezeThreshold = options?.freezeThreshold ?? DEFAULT_FREEZE_ATTEMPT_THRESHOLD;
|
|
5169
5444
|
const onAttempt = options?.onAttempt;
|
|
5170
5445
|
const backoff = options?.backoff ?? true;
|
|
5446
|
+
const onDegrade = options?.onDegrade;
|
|
5171
5447
|
let prevSource = "";
|
|
5172
5448
|
let prevOutput = "";
|
|
5173
5449
|
let frozenSrcEnd = 0;
|
|
5174
5450
|
let frozenOut = "";
|
|
5175
5451
|
let triggered = false;
|
|
5176
5452
|
let nextAttemptLen = 0;
|
|
5453
|
+
let lineageDegraded = false;
|
|
5454
|
+
const presence = new PuaPresence();
|
|
5455
|
+
const commit = (source, out) => {
|
|
5456
|
+
prevSource = source;
|
|
5457
|
+
prevOutput = out;
|
|
5458
|
+
return out;
|
|
5459
|
+
};
|
|
5460
|
+
const legacyWhole = (source) => processSlice(source, { legacy: true, probe: false }).out;
|
|
5461
|
+
const degrade = (source, reason) => {
|
|
5462
|
+
lineageDegraded = true;
|
|
5463
|
+
frozenSrcEnd = 0;
|
|
5464
|
+
frozenOut = "";
|
|
5465
|
+
onDegrade?.(reason);
|
|
5466
|
+
return commit(source, legacyWhole(source));
|
|
5467
|
+
};
|
|
5177
5468
|
return function incrementalPreprocessLaTeX(source) {
|
|
5178
5469
|
if (source === prevSource) return prevOutput;
|
|
5179
5470
|
const isAppend = source.length > prevSource.length && source.startsWith(prevSource);
|
|
@@ -5182,16 +5473,20 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5182
5473
|
frozenOut = "";
|
|
5183
5474
|
triggered = false;
|
|
5184
5475
|
nextAttemptLen = 0;
|
|
5476
|
+
lineageDegraded = false;
|
|
5477
|
+
presence.reset();
|
|
5478
|
+
presence.add(source, 0);
|
|
5479
|
+
} else {
|
|
5480
|
+
presence.add(source, prevSource.length);
|
|
5185
5481
|
}
|
|
5186
5482
|
if (!triggered) {
|
|
5187
5483
|
const checkFrom = isAppend ? Math.max(0, prevSource.length - 1) : 0;
|
|
5188
|
-
if (!hasLatexTrigger(source.slice(checkFrom)))
|
|
5189
|
-
prevSource = source;
|
|
5190
|
-
prevOutput = source;
|
|
5191
|
-
return source;
|
|
5192
|
-
}
|
|
5484
|
+
if (!hasLatexTrigger(source.slice(checkFrom))) return commit(source, source);
|
|
5193
5485
|
triggered = true;
|
|
5194
5486
|
}
|
|
5487
|
+
if (lineageDegraded) return commit(source, legacyWhole(source));
|
|
5488
|
+
const mask = presence.select();
|
|
5489
|
+
if (mask === null) return degrade(source, "mask-exhausted");
|
|
5195
5490
|
let active = source.slice(frozenSrcEnd);
|
|
5196
5491
|
if (active.length > freezeThreshold && active.length >= nextAttemptLen) {
|
|
5197
5492
|
const activeLength = active.length;
|
|
@@ -5206,18 +5501,20 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5206
5501
|
};
|
|
5207
5502
|
const cut = findRawSafeCut(active);
|
|
5208
5503
|
if (cut > 0) {
|
|
5209
|
-
const candidate = processSlice(active.slice(0, cut));
|
|
5504
|
+
const candidate = processSlice(active.slice(0, cut), { probe: true, mask });
|
|
5505
|
+
if (candidate.degradedReason !== null) {
|
|
5506
|
+
onAttempt?.({ activeLength, frozenBytes: 0 });
|
|
5507
|
+
return degrade(source, candidate.degradedReason);
|
|
5508
|
+
}
|
|
5210
5509
|
if (candidate.quiescent) freeze(cut, candidate);
|
|
5211
5510
|
}
|
|
5212
5511
|
nextAttemptLen = advanced || !backoff ? 0 : active.length * 2;
|
|
5213
5512
|
onAttempt?.({ activeLength, frozenBytes });
|
|
5214
5513
|
}
|
|
5215
|
-
const tail = processSlice(active, false);
|
|
5514
|
+
const tail = processSlice(active, { probe: false, mask });
|
|
5515
|
+
if (tail.degradedReason !== null) return degrade(source, tail.degradedReason);
|
|
5216
5516
|
const head = tail.truncatedAtSeamStart ? frozenOut.replace(/\s+$/, "") : frozenOut;
|
|
5217
|
-
|
|
5218
|
-
prevSource = source;
|
|
5219
|
-
prevOutput = out;
|
|
5220
|
-
return out;
|
|
5517
|
+
return commit(source, head + tail.out);
|
|
5221
5518
|
};
|
|
5222
5519
|
}
|
|
5223
5520
|
|
|
@@ -5243,6 +5540,8 @@ function createRemendPreprocessor(options) {
|
|
|
5243
5540
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5244
5541
|
0 && (module.exports = {
|
|
5245
5542
|
DEFAULT_PAYLOAD,
|
|
5543
|
+
ENGINE_PLACEHOLDER_TAGS,
|
|
5544
|
+
ENGINE_PROVENANCE_PROPERTY,
|
|
5246
5545
|
PIPELINE_STAGES,
|
|
5247
5546
|
SENTINEL_FN_CONTENT,
|
|
5248
5547
|
SENTINEL_LINK_URL,
|
|
@@ -5287,6 +5586,7 @@ function createRemendPreprocessor(options) {
|
|
|
5287
5586
|
preprocessLaTeX,
|
|
5288
5587
|
rehypeFooterAdorn,
|
|
5289
5588
|
rehypeRebaseHashLinks,
|
|
5589
|
+
rehypeVerifyEngineTags,
|
|
5290
5590
|
removeComments,
|
|
5291
5591
|
sanitizeCrossChunkUrl,
|
|
5292
5592
|
sanitizeSchema,
|