@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/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,20 +5069,22 @@ function escapeLatexPipesInUnclosed(text) {
|
|
|
5007
5069
|
const tail = text.substring(unclosedStart + delimLen);
|
|
5008
5070
|
return before + delim + replaceUnescapedPipes(tail);
|
|
5009
5071
|
}
|
|
5010
|
-
function opensMathFlow(text, pos) {
|
|
5072
|
+
function opensMathFlow(text, pos, runStartsAtLineStart) {
|
|
5011
5073
|
let i = pos;
|
|
5012
5074
|
let spaces = 0;
|
|
5013
|
-
while (i > 0
|
|
5075
|
+
while (i > 0) {
|
|
5076
|
+
const prev = text[i - 1];
|
|
5077
|
+
if (prev === "\n" || prev === "\r") return true;
|
|
5014
5078
|
i -= 1;
|
|
5015
5079
|
if (text[i] !== " ") return false;
|
|
5016
5080
|
spaces += 1;
|
|
5017
5081
|
if (spaces > 3) return false;
|
|
5018
5082
|
}
|
|
5019
|
-
return
|
|
5083
|
+
return runStartsAtLineStart;
|
|
5020
5084
|
}
|
|
5021
|
-
function truncateUnclosedLatexBlock(text, unclosedStart = findUnclosedDelimiterStart(text, "double-only")) {
|
|
5085
|
+
function truncateUnclosedLatexBlock(text, runStartsAtLineStart, unclosedStart = findUnclosedDelimiterStart(text, "double-only")) {
|
|
5022
5086
|
if (unclosedStart === -1) return text;
|
|
5023
|
-
if (!opensMathFlow(text, unclosedStart)) return text;
|
|
5087
|
+
if (!opensMathFlow(text, unclosedStart, runStartsAtLineStart)) return text;
|
|
5024
5088
|
return text.substring(0, unclosedStart).trimEnd();
|
|
5025
5089
|
}
|
|
5026
5090
|
function escapeTextUnderscores(text) {
|
|
@@ -5065,7 +5129,8 @@ function convertSingleToDoubleDollar(text) {
|
|
|
5065
5129
|
}
|
|
5066
5130
|
function preprocessLaTeX(str) {
|
|
5067
5131
|
if (!hasLatexTrigger(str)) return str;
|
|
5068
|
-
|
|
5132
|
+
const mask = selectMask(str);
|
|
5133
|
+
return (mask === null ? processSlice(str, { legacy: true, probe: false }) : processSlice(str, { probe: false, mask })).out;
|
|
5069
5134
|
}
|
|
5070
5135
|
function hasLatexTrigger(str) {
|
|
5071
5136
|
return str.includes("$") || str.includes("\\[") || str.includes("\\(");
|
|
@@ -5094,42 +5159,240 @@ function hasUnclosedTextCommand(text) {
|
|
|
5094
5159
|
}
|
|
5095
5160
|
var RESIDUAL_OPEN_BRACKET_RE = /(?<!!)\\\[/;
|
|
5096
5161
|
var LEADING_DOUBLE_DOLLAR_RE = /^\s*\$\$/;
|
|
5097
|
-
|
|
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) {
|
|
5098
5230
|
const segments = splitByProtectedRegions(slice);
|
|
5099
5231
|
const parts = [];
|
|
5100
5232
|
let quiescent = true;
|
|
5101
5233
|
let truncatedAtSeamStart = false;
|
|
5102
5234
|
for (let index = 0; index < segments.length; index++) {
|
|
5103
5235
|
const segment = segments[index];
|
|
5104
|
-
if (segment.
|
|
5236
|
+
if (segment.kind !== "text") {
|
|
5105
5237
|
parts.push(segment.text);
|
|
5106
5238
|
continue;
|
|
5107
5239
|
}
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
|
|
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 });
|
|
5126
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 });
|
|
5127
5287
|
}
|
|
5288
|
+
continue;
|
|
5128
5289
|
}
|
|
5129
|
-
|
|
5130
|
-
|
|
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
|
+
);
|
|
5131
5349
|
}
|
|
5132
|
-
|
|
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);
|
|
5133
5396
|
}
|
|
5134
5397
|
function isBlankRawLine(text, from, to) {
|
|
5135
5398
|
for (let i = from; i < to; i++) {
|
|
@@ -5145,7 +5408,7 @@ function findRawSafeCut(active) {
|
|
|
5145
5408
|
let backtickHazard = false;
|
|
5146
5409
|
let latentLt = false;
|
|
5147
5410
|
for (const segment of segments) {
|
|
5148
|
-
if (segment.
|
|
5411
|
+
if (segment.kind !== "text") {
|
|
5149
5412
|
if (segment.text.includes(">")) latentLt = false;
|
|
5150
5413
|
offset += segment.text.length;
|
|
5151
5414
|
continue;
|
|
@@ -5180,12 +5443,28 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5180
5443
|
const freezeThreshold = options?.freezeThreshold ?? DEFAULT_FREEZE_ATTEMPT_THRESHOLD;
|
|
5181
5444
|
const onAttempt = options?.onAttempt;
|
|
5182
5445
|
const backoff = options?.backoff ?? true;
|
|
5446
|
+
const onDegrade = options?.onDegrade;
|
|
5183
5447
|
let prevSource = "";
|
|
5184
5448
|
let prevOutput = "";
|
|
5185
5449
|
let frozenSrcEnd = 0;
|
|
5186
5450
|
let frozenOut = "";
|
|
5187
5451
|
let triggered = false;
|
|
5188
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
|
+
};
|
|
5189
5468
|
return function incrementalPreprocessLaTeX(source) {
|
|
5190
5469
|
if (source === prevSource) return prevOutput;
|
|
5191
5470
|
const isAppend = source.length > prevSource.length && source.startsWith(prevSource);
|
|
@@ -5194,16 +5473,20 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5194
5473
|
frozenOut = "";
|
|
5195
5474
|
triggered = false;
|
|
5196
5475
|
nextAttemptLen = 0;
|
|
5476
|
+
lineageDegraded = false;
|
|
5477
|
+
presence.reset();
|
|
5478
|
+
presence.add(source, 0);
|
|
5479
|
+
} else {
|
|
5480
|
+
presence.add(source, prevSource.length);
|
|
5197
5481
|
}
|
|
5198
5482
|
if (!triggered) {
|
|
5199
5483
|
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
|
-
}
|
|
5484
|
+
if (!hasLatexTrigger(source.slice(checkFrom))) return commit(source, source);
|
|
5205
5485
|
triggered = true;
|
|
5206
5486
|
}
|
|
5487
|
+
if (lineageDegraded) return commit(source, legacyWhole(source));
|
|
5488
|
+
const mask = presence.select();
|
|
5489
|
+
if (mask === null) return degrade(source, "mask-exhausted");
|
|
5207
5490
|
let active = source.slice(frozenSrcEnd);
|
|
5208
5491
|
if (active.length > freezeThreshold && active.length >= nextAttemptLen) {
|
|
5209
5492
|
const activeLength = active.length;
|
|
@@ -5218,18 +5501,20 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5218
5501
|
};
|
|
5219
5502
|
const cut = findRawSafeCut(active);
|
|
5220
5503
|
if (cut > 0) {
|
|
5221
|
-
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
|
+
}
|
|
5222
5509
|
if (candidate.quiescent) freeze(cut, candidate);
|
|
5223
5510
|
}
|
|
5224
5511
|
nextAttemptLen = advanced || !backoff ? 0 : active.length * 2;
|
|
5225
5512
|
onAttempt?.({ activeLength, frozenBytes });
|
|
5226
5513
|
}
|
|
5227
|
-
const tail = processSlice(active, false);
|
|
5514
|
+
const tail = processSlice(active, { probe: false, mask });
|
|
5515
|
+
if (tail.degradedReason !== null) return degrade(source, tail.degradedReason);
|
|
5228
5516
|
const head = tail.truncatedAtSeamStart ? frozenOut.replace(/\s+$/, "") : frozenOut;
|
|
5229
|
-
|
|
5230
|
-
prevSource = source;
|
|
5231
|
-
prevOutput = out;
|
|
5232
|
-
return out;
|
|
5517
|
+
return commit(source, head + tail.out);
|
|
5233
5518
|
};
|
|
5234
5519
|
}
|
|
5235
5520
|
|
|
@@ -5255,6 +5540,8 @@ function createRemendPreprocessor(options) {
|
|
|
5255
5540
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5256
5541
|
0 && (module.exports = {
|
|
5257
5542
|
DEFAULT_PAYLOAD,
|
|
5543
|
+
ENGINE_PLACEHOLDER_TAGS,
|
|
5544
|
+
ENGINE_PROVENANCE_PROPERTY,
|
|
5258
5545
|
PIPELINE_STAGES,
|
|
5259
5546
|
SENTINEL_FN_CONTENT,
|
|
5260
5547
|
SENTINEL_LINK_URL,
|
|
@@ -5299,6 +5586,7 @@ function createRemendPreprocessor(options) {
|
|
|
5299
5586
|
preprocessLaTeX,
|
|
5300
5587
|
rehypeFooterAdorn,
|
|
5301
5588
|
rehypeRebaseHashLinks,
|
|
5589
|
+
rehypeVerifyEngineTags,
|
|
5302
5590
|
removeComments,
|
|
5303
5591
|
sanitizeCrossChunkUrl,
|
|
5304
5592
|
sanitizeSchema,
|