@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.js
CHANGED
|
@@ -2701,6 +2701,44 @@ function rehypeUnwrapCrossChunkImages() {
|
|
|
2701
2701
|
|
|
2702
2702
|
// src/components/pluginChain.ts
|
|
2703
2703
|
import rehypeSanitize from "rehype-sanitize";
|
|
2704
|
+
|
|
2705
|
+
// src/components/rehypeVerifyEngineTags.ts
|
|
2706
|
+
var ENGINE_PLACEHOLDER_TAGS = /* @__PURE__ */ new Set([
|
|
2707
|
+
"footnote-sup",
|
|
2708
|
+
"cross-chunk-link",
|
|
2709
|
+
"cross-chunk-image"
|
|
2710
|
+
]);
|
|
2711
|
+
var ENGINE_PROVENANCE_PROPERTY = "engineProvenance";
|
|
2712
|
+
function walk(parent, provenance) {
|
|
2713
|
+
const children = parent.children;
|
|
2714
|
+
let i = 0;
|
|
2715
|
+
while (i < children.length) {
|
|
2716
|
+
const node = children[i];
|
|
2717
|
+
if (node.type === "element" && ENGINE_PLACEHOLDER_TAGS.has(node.tagName)) {
|
|
2718
|
+
const props = node.properties ?? {};
|
|
2719
|
+
const stamped = props[ENGINE_PROVENANCE_PROPERTY];
|
|
2720
|
+
const genuine = provenance !== "" && typeof stamped === "string" && stamped === provenance;
|
|
2721
|
+
if (genuine) {
|
|
2722
|
+
delete props[ENGINE_PROVENANCE_PROPERTY];
|
|
2723
|
+
walk(node, provenance);
|
|
2724
|
+
i += 1;
|
|
2725
|
+
} else {
|
|
2726
|
+
children.splice(i, 1, ...node.children);
|
|
2727
|
+
}
|
|
2728
|
+
continue;
|
|
2729
|
+
}
|
|
2730
|
+
if (node.type === "element") walk(node, provenance);
|
|
2731
|
+
i += 1;
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2734
|
+
function rehypeVerifyEngineTags(options) {
|
|
2735
|
+
const provenance = options?.provenance ?? "";
|
|
2736
|
+
return function transformer(tree) {
|
|
2737
|
+
walk(tree, provenance);
|
|
2738
|
+
};
|
|
2739
|
+
}
|
|
2740
|
+
|
|
2741
|
+
// src/components/pluginChain.ts
|
|
2704
2742
|
import remarkBreaks from "remark-breaks";
|
|
2705
2743
|
import remarkCjkFriendly from "remark-cjk-friendly";
|
|
2706
2744
|
import remarkCjkFriendlyGfmStrikethrough from "remark-cjk-friendly-gfm-strikethrough";
|
|
@@ -2806,10 +2844,13 @@ function buildCoreRemarkPlugins(enginePlugins) {
|
|
|
2806
2844
|
...DISPLAY_OPTIMIZE_CHAIN.filter(([name]) => selected.has(name)).map(([, plugin]) => plugin)
|
|
2807
2845
|
];
|
|
2808
2846
|
}
|
|
2809
|
-
function buildCoreRehypePlugins(sanitizeSchema2, clobberPrefix) {
|
|
2847
|
+
function buildCoreRehypePlugins(sanitizeSchema2, clobberPrefix, options) {
|
|
2810
2848
|
return [
|
|
2811
2849
|
// Allow raw HTML through so rehype-sanitize can handle it.
|
|
2812
2850
|
[rehypeRaw, { passThrough: [] }],
|
|
2851
|
+
// Unwrap forged engine placeholders BEFORE sanitize admits their tag
|
|
2852
|
+
// names. Only when the caller holds a credential (see the option's doc).
|
|
2853
|
+
...options ? [[rehypeVerifyEngineTags, { provenance: options.provenance }]] : [],
|
|
2813
2854
|
// Sanitize HTML while allowing <mark> (highlight), KaTeX class names,
|
|
2814
2855
|
// and any extra protocols the caller permitted via the `sanitizeSchema`
|
|
2815
2856
|
// prop. Override `clobberPrefix` with the instance-scoped value — the
|
|
@@ -2849,6 +2890,10 @@ function buildCoreRemarkRehypeOptions(enableDefinitionList) {
|
|
|
2849
2890
|
}
|
|
2850
2891
|
|
|
2851
2892
|
// src/components/customMdastHandlers.ts
|
|
2893
|
+
function provenanceProps(s) {
|
|
2894
|
+
const provenance = s.options.provenance;
|
|
2895
|
+
return typeof provenance === "string" ? { engineProvenance: provenance } : {};
|
|
2896
|
+
}
|
|
2852
2897
|
function localDefProps(s, id) {
|
|
2853
2898
|
const def = s.definitionById.get(id);
|
|
2854
2899
|
if (!def || typeof def.url !== "string" || def.url === SENTINEL_LINK_URL) return {};
|
|
@@ -2887,7 +2932,8 @@ function buildCrossChunkHandlers() {
|
|
|
2887
2932
|
label: node.label ?? node.identifier,
|
|
2888
2933
|
referenceType: node.referenceType,
|
|
2889
2934
|
documentId: s.options.documentId,
|
|
2890
|
-
...localDefProps(s, id)
|
|
2935
|
+
...localDefProps(s, id),
|
|
2936
|
+
...provenanceProps(s)
|
|
2891
2937
|
},
|
|
2892
2938
|
children: s.all(node)
|
|
2893
2939
|
};
|
|
@@ -2905,7 +2951,8 @@ function buildCrossChunkHandlers() {
|
|
|
2905
2951
|
referenceType: node.referenceType,
|
|
2906
2952
|
alt: node.alt ?? "",
|
|
2907
2953
|
documentId: s.options.documentId,
|
|
2908
|
-
...localDefProps(s, id)
|
|
2954
|
+
...localDefProps(s, id),
|
|
2955
|
+
...provenanceProps(s)
|
|
2909
2956
|
},
|
|
2910
2957
|
children: []
|
|
2911
2958
|
};
|
|
@@ -2922,7 +2969,8 @@ function buildCrossChunkHandlers() {
|
|
|
2922
2969
|
properties: {
|
|
2923
2970
|
label: node.identifier,
|
|
2924
2971
|
localOccurrence,
|
|
2925
|
-
documentId: s.options.documentId
|
|
2972
|
+
documentId: s.options.documentId,
|
|
2973
|
+
...provenanceProps(s)
|
|
2926
2974
|
},
|
|
2927
2975
|
children: []
|
|
2928
2976
|
};
|
|
@@ -2940,7 +2988,8 @@ function buildCrossChunkHandlers() {
|
|
|
2940
2988
|
// first client frame), where the local synthetic footer is what
|
|
2941
2989
|
// renders, so marks and footer agree (core-render-02).
|
|
2942
2990
|
localNumber: s.footnoteOrder.indexOf(id) + 1,
|
|
2943
|
-
documentId: s.options.documentId
|
|
2991
|
+
documentId: s.options.documentId,
|
|
2992
|
+
...provenanceProps(s)
|
|
2944
2993
|
},
|
|
2945
2994
|
children: []
|
|
2946
2995
|
};
|
|
@@ -4600,6 +4649,12 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4600
4649
|
};
|
|
4601
4650
|
|
|
4602
4651
|
// src/preprocessors/latex.ts
|
|
4652
|
+
function isHardBoundary(kind) {
|
|
4653
|
+
return kind === "code" || kind === "literal" || kind === "multilineTag";
|
|
4654
|
+
}
|
|
4655
|
+
function hasLineEnding(text) {
|
|
4656
|
+
return text.includes("\n") || text.includes("\r");
|
|
4657
|
+
}
|
|
4603
4658
|
function getRepeatedMarkerLength(content, start, marker) {
|
|
4604
4659
|
let end = start;
|
|
4605
4660
|
while (end < content.length && content[end] === marker) {
|
|
@@ -4667,11 +4722,11 @@ function splitByProtectedRegions(content) {
|
|
|
4667
4722
|
let multilineFenceMarker = null;
|
|
4668
4723
|
let multilineFenceLength = 0;
|
|
4669
4724
|
let multilineFenceIndent = 0;
|
|
4670
|
-
function pushProtected(start, end) {
|
|
4725
|
+
function pushProtected(start, end, kind) {
|
|
4671
4726
|
if (start > lastIndex) {
|
|
4672
|
-
segments.push({ text: content.substring(lastIndex, start)
|
|
4727
|
+
segments.push({ kind: "text", text: content.substring(lastIndex, start) });
|
|
4673
4728
|
}
|
|
4674
|
-
segments.push({ text: content.substring(start, end)
|
|
4729
|
+
segments.push({ kind, text: content.substring(start, end) });
|
|
4675
4730
|
lastIndex = end;
|
|
4676
4731
|
}
|
|
4677
4732
|
let i = 0;
|
|
@@ -4682,7 +4737,7 @@ function splitByProtectedRegions(content) {
|
|
|
4682
4737
|
const runLen = getRepeatedMarkerLength(content, i, multilineFenceMarker);
|
|
4683
4738
|
const closerIndent = lineIndentBefore(content, i);
|
|
4684
4739
|
if (runLen >= multilineFenceLength && closerIndent !== -1 && closerIndent <= multilineFenceIndent + 3 && restOfLineIsBlank(content, i + runLen)) {
|
|
4685
|
-
pushProtected(multilineStart, i + runLen);
|
|
4740
|
+
pushProtected(multilineStart, i + runLen, "code");
|
|
4686
4741
|
multilineStart = -1;
|
|
4687
4742
|
multilineFenceMarker = null;
|
|
4688
4743
|
multilineFenceLength = 0;
|
|
@@ -4709,7 +4764,7 @@ function splitByProtectedRegions(content) {
|
|
|
4709
4764
|
if (char === "`") {
|
|
4710
4765
|
const closeIdx = findClosingBacktickRun(content, i + runLen, runLen);
|
|
4711
4766
|
if (closeIdx !== -1) {
|
|
4712
|
-
pushProtected(i, closeIdx + runLen);
|
|
4767
|
+
pushProtected(i, closeIdx + runLen, "code");
|
|
4713
4768
|
i = closeIdx + runLen;
|
|
4714
4769
|
continue;
|
|
4715
4770
|
}
|
|
@@ -4734,7 +4789,11 @@ function splitByProtectedRegions(content) {
|
|
|
4734
4789
|
endIndex = content.length;
|
|
4735
4790
|
}
|
|
4736
4791
|
}
|
|
4737
|
-
pushProtected(
|
|
4792
|
+
pushProtected(
|
|
4793
|
+
i,
|
|
4794
|
+
endIndex,
|
|
4795
|
+
isOpeningPairedTag ? "literal" : hasLineEnding(content.substring(i, endIndex)) ? "multilineTag" : "tag"
|
|
4796
|
+
);
|
|
4738
4797
|
i = endIndex;
|
|
4739
4798
|
continue;
|
|
4740
4799
|
}
|
|
@@ -4742,10 +4801,10 @@ function splitByProtectedRegions(content) {
|
|
|
4742
4801
|
i += 1;
|
|
4743
4802
|
}
|
|
4744
4803
|
if (multilineStart !== -1) {
|
|
4745
|
-
pushProtected(multilineStart, content.length);
|
|
4804
|
+
pushProtected(multilineStart, content.length, "code");
|
|
4746
4805
|
}
|
|
4747
4806
|
if (lastIndex < content.length) {
|
|
4748
|
-
segments.push({ text: content.substring(lastIndex)
|
|
4807
|
+
segments.push({ kind: "text", text: content.substring(lastIndex) });
|
|
4749
4808
|
}
|
|
4750
4809
|
return segments;
|
|
4751
4810
|
}
|
|
@@ -4899,8 +4958,22 @@ function escapeLatexPipesInUnclosed(text) {
|
|
|
4899
4958
|
const tail = text.substring(unclosedStart + delimLen);
|
|
4900
4959
|
return before + delim + replaceUnescapedPipes(tail);
|
|
4901
4960
|
}
|
|
4902
|
-
function
|
|
4961
|
+
function opensMathFlow(text, pos, runStartsAtLineStart) {
|
|
4962
|
+
let i = pos;
|
|
4963
|
+
let spaces = 0;
|
|
4964
|
+
while (i > 0) {
|
|
4965
|
+
const prev = text[i - 1];
|
|
4966
|
+
if (prev === "\n" || prev === "\r") return true;
|
|
4967
|
+
i -= 1;
|
|
4968
|
+
if (text[i] !== " ") return false;
|
|
4969
|
+
spaces += 1;
|
|
4970
|
+
if (spaces > 3) return false;
|
|
4971
|
+
}
|
|
4972
|
+
return runStartsAtLineStart;
|
|
4973
|
+
}
|
|
4974
|
+
function truncateUnclosedLatexBlock(text, runStartsAtLineStart, unclosedStart = findUnclosedDelimiterStart(text, "double-only")) {
|
|
4903
4975
|
if (unclosedStart === -1) return text;
|
|
4976
|
+
if (!opensMathFlow(text, unclosedStart, runStartsAtLineStart)) return text;
|
|
4904
4977
|
return text.substring(0, unclosedStart).trimEnd();
|
|
4905
4978
|
}
|
|
4906
4979
|
function escapeTextUnderscores(text) {
|
|
@@ -4945,7 +5018,8 @@ function convertSingleToDoubleDollar(text) {
|
|
|
4945
5018
|
}
|
|
4946
5019
|
function preprocessLaTeX(str) {
|
|
4947
5020
|
if (!hasLatexTrigger(str)) return str;
|
|
4948
|
-
|
|
5021
|
+
const mask = selectMask(str);
|
|
5022
|
+
return (mask === null ? processSlice(str, { legacy: true, probe: false }) : processSlice(str, { probe: false, mask })).out;
|
|
4949
5023
|
}
|
|
4950
5024
|
function hasLatexTrigger(str) {
|
|
4951
5025
|
return str.includes("$") || str.includes("\\[") || str.includes("\\(");
|
|
@@ -4974,42 +5048,240 @@ function hasUnclosedTextCommand(text) {
|
|
|
4974
5048
|
}
|
|
4975
5049
|
var RESIDUAL_OPEN_BRACKET_RE = /(?<!!)\\\[/;
|
|
4976
5050
|
var LEADING_DOUBLE_DOLLAR_RE = /^\s*\$\$/;
|
|
4977
|
-
|
|
5051
|
+
var PUA_START = 57344;
|
|
5052
|
+
var PUA_END = 63743;
|
|
5053
|
+
var PUA_SIZE = PUA_END - PUA_START + 1;
|
|
5054
|
+
function selectMask(source) {
|
|
5055
|
+
const first = String.fromCharCode(PUA_START);
|
|
5056
|
+
if (source.indexOf(first) === -1) return first;
|
|
5057
|
+
const seen = new Uint8Array(PUA_SIZE);
|
|
5058
|
+
for (let i = 0; i < source.length; i++) {
|
|
5059
|
+
const c = source.charCodeAt(i);
|
|
5060
|
+
if (c >= PUA_START && c <= PUA_END) seen[c - PUA_START] = 1;
|
|
5061
|
+
}
|
|
5062
|
+
for (let k = 0; k < PUA_SIZE; k++) if (seen[k] === 0) return String.fromCharCode(PUA_START + k);
|
|
5063
|
+
return null;
|
|
5064
|
+
}
|
|
5065
|
+
var PuaPresence = class {
|
|
5066
|
+
bits = new Uint8Array(PUA_SIZE);
|
|
5067
|
+
distinct = 0;
|
|
5068
|
+
reset() {
|
|
5069
|
+
this.bits.fill(0);
|
|
5070
|
+
this.distinct = 0;
|
|
5071
|
+
}
|
|
5072
|
+
add(text, from) {
|
|
5073
|
+
for (let i = from; i < text.length; i++) {
|
|
5074
|
+
const c = text.charCodeAt(i);
|
|
5075
|
+
if (c >= PUA_START && c <= PUA_END) {
|
|
5076
|
+
const k = c - PUA_START;
|
|
5077
|
+
if (this.bits[k] === 0) {
|
|
5078
|
+
this.bits[k] = 1;
|
|
5079
|
+
this.distinct += 1;
|
|
5080
|
+
}
|
|
5081
|
+
}
|
|
5082
|
+
}
|
|
5083
|
+
}
|
|
5084
|
+
select() {
|
|
5085
|
+
if (this.distinct === 0) return String.fromCharCode(PUA_START);
|
|
5086
|
+
if (this.distinct >= PUA_SIZE) return null;
|
|
5087
|
+
for (let k = 0; k < PUA_SIZE; k++) if (this.bits[k] === 0) return String.fromCharCode(PUA_START + k);
|
|
5088
|
+
return null;
|
|
5089
|
+
}
|
|
5090
|
+
};
|
|
5091
|
+
function transformRun(input, probe, runStartsAtLineStart, seamEligible) {
|
|
5092
|
+
let text = input;
|
|
5093
|
+
let tailSensitive = false;
|
|
5094
|
+
let truncatedAtSeamStart = false;
|
|
5095
|
+
text = escapeMhchemCommands(text);
|
|
5096
|
+
text = escapeCurrencyDollarSigns(text);
|
|
5097
|
+
text = convertLatexDelimiters(text);
|
|
5098
|
+
if (probe && RESIDUAL_OPEN_BRACKET_RE.test(text)) tailSensitive = true;
|
|
5099
|
+
text = escapeLatexPipes(text);
|
|
5100
|
+
if (probe && findUnclosedDelimiterStart(text, "both") !== -1) tailSensitive = true;
|
|
5101
|
+
text = escapeLatexPipesInUnclosed(text);
|
|
5102
|
+
if (probe && hasUnclosedTextCommand(text)) tailSensitive = true;
|
|
5103
|
+
text = escapeTextUnderscores(text);
|
|
5104
|
+
text = convertSingleToDoubleDollar(text);
|
|
5105
|
+
let unclosedDouble;
|
|
5106
|
+
if (probe || seamEligible && LEADING_DOUBLE_DOLLAR_RE.test(text)) {
|
|
5107
|
+
unclosedDouble = findUnclosedDelimiterStart(text, "double-only");
|
|
5108
|
+
if (unclosedDouble !== -1) {
|
|
5109
|
+
tailSensitive = true;
|
|
5110
|
+
if (seamEligible && opensMathFlow(text, unclosedDouble, runStartsAtLineStart) && text.slice(0, unclosedDouble).trim() === "") {
|
|
5111
|
+
truncatedAtSeamStart = true;
|
|
5112
|
+
}
|
|
5113
|
+
}
|
|
5114
|
+
}
|
|
5115
|
+
text = truncateUnclosedLatexBlock(text, runStartsAtLineStart, unclosedDouble);
|
|
5116
|
+
return { out: text, tailSensitive, truncatedAtSeamStart };
|
|
5117
|
+
}
|
|
5118
|
+
function processSliceLegacy(slice, probe) {
|
|
4978
5119
|
const segments = splitByProtectedRegions(slice);
|
|
4979
5120
|
const parts = [];
|
|
4980
5121
|
let quiescent = true;
|
|
4981
5122
|
let truncatedAtSeamStart = false;
|
|
4982
5123
|
for (let index = 0; index < segments.length; index++) {
|
|
4983
5124
|
const segment = segments[index];
|
|
4984
|
-
if (segment.
|
|
5125
|
+
if (segment.kind !== "text") {
|
|
4985
5126
|
parts.push(segment.text);
|
|
4986
5127
|
continue;
|
|
4987
5128
|
}
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5129
|
+
const r = transformRun(segment.text, probe, true, index === 0);
|
|
5130
|
+
if (r.tailSensitive) quiescent = false;
|
|
5131
|
+
if (r.truncatedAtSeamStart) truncatedAtSeamStart = true;
|
|
5132
|
+
parts.push(r.out);
|
|
5133
|
+
}
|
|
5134
|
+
return { out: parts.join(""), quiescent, truncatedAtSeamStart, degradedReason: null };
|
|
5135
|
+
}
|
|
5136
|
+
var SCOPE_DEPTH_CAP = 8;
|
|
5137
|
+
var VOID_TAGS2 = /* @__PURE__ */ new Set(["br", "hr", "img", "wbr", "input", "source"]);
|
|
5138
|
+
var TAG_NAME_RE = /^<(\/?)([A-Za-z][A-Za-z0-9]*)/;
|
|
5139
|
+
function tagInfo(tag) {
|
|
5140
|
+
const m = TAG_NAME_RE.exec(tag);
|
|
5141
|
+
const closing = m?.[1] === "/";
|
|
5142
|
+
const name = (m?.[2] ?? "").toLowerCase();
|
|
5143
|
+
const opensScope = !closing && !tag.endsWith("/>") && !VOID_TAGS2.has(name);
|
|
5144
|
+
return { name, closing, opensScope };
|
|
5145
|
+
}
|
|
5146
|
+
function buildRunTree(segments) {
|
|
5147
|
+
const root2 = [];
|
|
5148
|
+
const stack = [];
|
|
5149
|
+
const current = () => stack.length > 0 ? stack[stack.length - 1].children : root2;
|
|
5150
|
+
const unwind = () => {
|
|
5151
|
+
while (stack.length > 0) {
|
|
5152
|
+
const frame = stack.pop();
|
|
5153
|
+
current().push({ type: "atom", text: frame.open }, ...frame.children);
|
|
5154
|
+
}
|
|
5155
|
+
};
|
|
5156
|
+
for (const segment of segments) {
|
|
5157
|
+
if (segment.kind === "tag") {
|
|
5158
|
+
const info = tagInfo(segment.text);
|
|
5159
|
+
if (info.closing) {
|
|
5160
|
+
const top = stack[stack.length - 1];
|
|
5161
|
+
if (top !== void 0 && top.name === info.name) {
|
|
5162
|
+
stack.pop();
|
|
5163
|
+
const parent = current();
|
|
5164
|
+
if (top.suppressed) {
|
|
5165
|
+
parent.push({ type: "atom", text: top.open }, ...top.children, { type: "atom", text: segment.text });
|
|
5166
|
+
} else {
|
|
5167
|
+
parent.push({ type: "scope", open: top.open, close: segment.text, children: top.children });
|
|
5168
|
+
}
|
|
5169
|
+
} else {
|
|
5170
|
+
current().push({ type: "atom", text: segment.text });
|
|
5006
5171
|
}
|
|
5172
|
+
} else if (info.opensScope) {
|
|
5173
|
+
stack.push({ name: info.name, open: segment.text, suppressed: stack.length >= SCOPE_DEPTH_CAP, children: [] });
|
|
5174
|
+
} else {
|
|
5175
|
+
current().push({ type: "atom", text: segment.text });
|
|
5007
5176
|
}
|
|
5177
|
+
continue;
|
|
5008
5178
|
}
|
|
5009
|
-
|
|
5010
|
-
|
|
5179
|
+
const t = segment.text;
|
|
5180
|
+
let start = 0;
|
|
5181
|
+
for (let i = 0; i < t.length; i++) {
|
|
5182
|
+
const c = t.charCodeAt(i);
|
|
5183
|
+
if (c !== 10 && c !== 13) continue;
|
|
5184
|
+
if (i > start) current().push({ type: "text", text: t.slice(start, i) });
|
|
5185
|
+
const end = c === 13 && t.charCodeAt(i + 1) === 10 ? i + 2 : i + 1;
|
|
5186
|
+
unwind();
|
|
5187
|
+
root2.push({ type: "text", text: t.slice(i, end) });
|
|
5188
|
+
start = end;
|
|
5189
|
+
i = end - 1;
|
|
5190
|
+
}
|
|
5191
|
+
if (start < t.length) current().push({ type: "text", text: t.slice(start) });
|
|
5192
|
+
}
|
|
5193
|
+
unwind();
|
|
5194
|
+
return root2;
|
|
5195
|
+
}
|
|
5196
|
+
var restoreFailureInjector = null;
|
|
5197
|
+
function restore(out, atoms, mask) {
|
|
5198
|
+
if (restoreFailureInjector !== null && restoreFailureInjector(atoms)) return null;
|
|
5199
|
+
let result = "";
|
|
5200
|
+
let k = 0;
|
|
5201
|
+
let last = 0;
|
|
5202
|
+
for (; ; ) {
|
|
5203
|
+
const idx = out.indexOf(mask, last);
|
|
5204
|
+
if (idx === -1) break;
|
|
5205
|
+
if (k >= atoms.length) return null;
|
|
5206
|
+
result += out.slice(last, idx) + atoms[k];
|
|
5207
|
+
k += 1;
|
|
5208
|
+
last = idx + 1;
|
|
5209
|
+
}
|
|
5210
|
+
return result + out.slice(last);
|
|
5211
|
+
}
|
|
5212
|
+
function emitRun(nodes, mask) {
|
|
5213
|
+
let text = "";
|
|
5214
|
+
const atoms = [];
|
|
5215
|
+
for (const node of nodes) {
|
|
5216
|
+
if (node.type === "text") {
|
|
5217
|
+
text += node.text;
|
|
5218
|
+
} else if (node.type === "atom") {
|
|
5219
|
+
atoms.push(node.text);
|
|
5220
|
+
text += mask;
|
|
5221
|
+
} else {
|
|
5222
|
+
const inner = emitRun(node.children, mask);
|
|
5223
|
+
if (inner === null) return null;
|
|
5224
|
+
const transformed = transformRun(inner.text, false, false, false);
|
|
5225
|
+
const restored = restore(transformed.out, inner.atoms, mask);
|
|
5226
|
+
if (restored === null) return null;
|
|
5227
|
+
atoms.push(node.open + restored + node.close);
|
|
5228
|
+
text += mask;
|
|
5229
|
+
}
|
|
5230
|
+
}
|
|
5231
|
+
return { text, atoms };
|
|
5232
|
+
}
|
|
5233
|
+
function reportRestoreViolation() {
|
|
5234
|
+
if (false) {
|
|
5235
|
+
console.error(
|
|
5236
|
+
"[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."
|
|
5237
|
+
);
|
|
5011
5238
|
}
|
|
5012
|
-
|
|
5239
|
+
}
|
|
5240
|
+
function processSliceDefault(slice, probe, mask) {
|
|
5241
|
+
const segments = splitByProtectedRegions(slice);
|
|
5242
|
+
const parts = [];
|
|
5243
|
+
let quiescent = true;
|
|
5244
|
+
let truncatedAtSeamStart = false;
|
|
5245
|
+
let offset = 0;
|
|
5246
|
+
let i = 0;
|
|
5247
|
+
while (i < segments.length) {
|
|
5248
|
+
const segment = segments[i];
|
|
5249
|
+
if (isHardBoundary(segment.kind)) {
|
|
5250
|
+
parts.push(segment.text);
|
|
5251
|
+
offset += segment.text.length;
|
|
5252
|
+
i += 1;
|
|
5253
|
+
continue;
|
|
5254
|
+
}
|
|
5255
|
+
const runStart = offset;
|
|
5256
|
+
const runSegments = [];
|
|
5257
|
+
while (i < segments.length && !isHardBoundary(segments[i].kind)) {
|
|
5258
|
+
runSegments.push(segments[i]);
|
|
5259
|
+
offset += segments[i].text.length;
|
|
5260
|
+
i += 1;
|
|
5261
|
+
}
|
|
5262
|
+
const before = runStart === 0 ? -1 : slice.charCodeAt(runStart - 1);
|
|
5263
|
+
const runStartsAtLineStart = before === -1 || before === 10 || before === 13;
|
|
5264
|
+
const seamEligible = runStart === 0;
|
|
5265
|
+
const emitted = emitRun(buildRunTree(runSegments), mask);
|
|
5266
|
+
if (emitted === null) {
|
|
5267
|
+
reportRestoreViolation();
|
|
5268
|
+
return { ...processSliceLegacy(slice, probe), degradedReason: "restore-invariant" };
|
|
5269
|
+
}
|
|
5270
|
+
const r = transformRun(emitted.text, probe, runStartsAtLineStart, seamEligible);
|
|
5271
|
+
const restored = restore(r.out, emitted.atoms, mask);
|
|
5272
|
+
if (restored === null) {
|
|
5273
|
+
reportRestoreViolation();
|
|
5274
|
+
return { ...processSliceLegacy(slice, probe), degradedReason: "restore-invariant" };
|
|
5275
|
+
}
|
|
5276
|
+
if (r.tailSensitive) quiescent = false;
|
|
5277
|
+
if (r.truncatedAtSeamStart) truncatedAtSeamStart = true;
|
|
5278
|
+
parts.push(restored);
|
|
5279
|
+
}
|
|
5280
|
+
return { out: parts.join(""), quiescent, truncatedAtSeamStart, degradedReason: null };
|
|
5281
|
+
}
|
|
5282
|
+
function processSlice(slice, options) {
|
|
5283
|
+
if (options.legacy === true) return processSliceLegacy(slice, options.probe);
|
|
5284
|
+
return processSliceDefault(slice, options.probe, options.mask);
|
|
5013
5285
|
}
|
|
5014
5286
|
function isBlankRawLine(text, from, to) {
|
|
5015
5287
|
for (let i = from; i < to; i++) {
|
|
@@ -5025,7 +5297,7 @@ function findRawSafeCut(active) {
|
|
|
5025
5297
|
let backtickHazard = false;
|
|
5026
5298
|
let latentLt = false;
|
|
5027
5299
|
for (const segment of segments) {
|
|
5028
|
-
if (segment.
|
|
5300
|
+
if (segment.kind !== "text") {
|
|
5029
5301
|
if (segment.text.includes(">")) latentLt = false;
|
|
5030
5302
|
offset += segment.text.length;
|
|
5031
5303
|
continue;
|
|
@@ -5060,12 +5332,28 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5060
5332
|
const freezeThreshold = options?.freezeThreshold ?? DEFAULT_FREEZE_ATTEMPT_THRESHOLD;
|
|
5061
5333
|
const onAttempt = options?.onAttempt;
|
|
5062
5334
|
const backoff = options?.backoff ?? true;
|
|
5335
|
+
const onDegrade = options?.onDegrade;
|
|
5063
5336
|
let prevSource = "";
|
|
5064
5337
|
let prevOutput = "";
|
|
5065
5338
|
let frozenSrcEnd = 0;
|
|
5066
5339
|
let frozenOut = "";
|
|
5067
5340
|
let triggered = false;
|
|
5068
5341
|
let nextAttemptLen = 0;
|
|
5342
|
+
let lineageDegraded = false;
|
|
5343
|
+
const presence = new PuaPresence();
|
|
5344
|
+
const commit = (source, out) => {
|
|
5345
|
+
prevSource = source;
|
|
5346
|
+
prevOutput = out;
|
|
5347
|
+
return out;
|
|
5348
|
+
};
|
|
5349
|
+
const legacyWhole = (source) => processSlice(source, { legacy: true, probe: false }).out;
|
|
5350
|
+
const degrade = (source, reason) => {
|
|
5351
|
+
lineageDegraded = true;
|
|
5352
|
+
frozenSrcEnd = 0;
|
|
5353
|
+
frozenOut = "";
|
|
5354
|
+
onDegrade?.(reason);
|
|
5355
|
+
return commit(source, legacyWhole(source));
|
|
5356
|
+
};
|
|
5069
5357
|
return function incrementalPreprocessLaTeX(source) {
|
|
5070
5358
|
if (source === prevSource) return prevOutput;
|
|
5071
5359
|
const isAppend = source.length > prevSource.length && source.startsWith(prevSource);
|
|
@@ -5074,16 +5362,20 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5074
5362
|
frozenOut = "";
|
|
5075
5363
|
triggered = false;
|
|
5076
5364
|
nextAttemptLen = 0;
|
|
5365
|
+
lineageDegraded = false;
|
|
5366
|
+
presence.reset();
|
|
5367
|
+
presence.add(source, 0);
|
|
5368
|
+
} else {
|
|
5369
|
+
presence.add(source, prevSource.length);
|
|
5077
5370
|
}
|
|
5078
5371
|
if (!triggered) {
|
|
5079
5372
|
const checkFrom = isAppend ? Math.max(0, prevSource.length - 1) : 0;
|
|
5080
|
-
if (!hasLatexTrigger(source.slice(checkFrom)))
|
|
5081
|
-
prevSource = source;
|
|
5082
|
-
prevOutput = source;
|
|
5083
|
-
return source;
|
|
5084
|
-
}
|
|
5373
|
+
if (!hasLatexTrigger(source.slice(checkFrom))) return commit(source, source);
|
|
5085
5374
|
triggered = true;
|
|
5086
5375
|
}
|
|
5376
|
+
if (lineageDegraded) return commit(source, legacyWhole(source));
|
|
5377
|
+
const mask = presence.select();
|
|
5378
|
+
if (mask === null) return degrade(source, "mask-exhausted");
|
|
5087
5379
|
let active = source.slice(frozenSrcEnd);
|
|
5088
5380
|
if (active.length > freezeThreshold && active.length >= nextAttemptLen) {
|
|
5089
5381
|
const activeLength = active.length;
|
|
@@ -5098,18 +5390,20 @@ function createIncrementalLatexPreprocessor(options) {
|
|
|
5098
5390
|
};
|
|
5099
5391
|
const cut = findRawSafeCut(active);
|
|
5100
5392
|
if (cut > 0) {
|
|
5101
|
-
const candidate = processSlice(active.slice(0, cut));
|
|
5393
|
+
const candidate = processSlice(active.slice(0, cut), { probe: true, mask });
|
|
5394
|
+
if (candidate.degradedReason !== null) {
|
|
5395
|
+
onAttempt?.({ activeLength, frozenBytes: 0 });
|
|
5396
|
+
return degrade(source, candidate.degradedReason);
|
|
5397
|
+
}
|
|
5102
5398
|
if (candidate.quiescent) freeze(cut, candidate);
|
|
5103
5399
|
}
|
|
5104
5400
|
nextAttemptLen = advanced || !backoff ? 0 : active.length * 2;
|
|
5105
5401
|
onAttempt?.({ activeLength, frozenBytes });
|
|
5106
5402
|
}
|
|
5107
|
-
const tail = processSlice(active, false);
|
|
5403
|
+
const tail = processSlice(active, { probe: false, mask });
|
|
5404
|
+
if (tail.degradedReason !== null) return degrade(source, tail.degradedReason);
|
|
5108
5405
|
const head = tail.truncatedAtSeamStart ? frozenOut.replace(/\s+$/, "") : frozenOut;
|
|
5109
|
-
|
|
5110
|
-
prevSource = source;
|
|
5111
|
-
prevOutput = out;
|
|
5112
|
-
return out;
|
|
5406
|
+
return commit(source, head + tail.out);
|
|
5113
5407
|
};
|
|
5114
5408
|
}
|
|
5115
5409
|
|
|
@@ -5134,6 +5428,8 @@ function createRemendPreprocessor(options) {
|
|
|
5134
5428
|
}
|
|
5135
5429
|
export {
|
|
5136
5430
|
DEFAULT_PAYLOAD,
|
|
5431
|
+
ENGINE_PLACEHOLDER_TAGS,
|
|
5432
|
+
ENGINE_PROVENANCE_PROPERTY,
|
|
5137
5433
|
PIPELINE_STAGES,
|
|
5138
5434
|
SENTINEL_FN_CONTENT,
|
|
5139
5435
|
SENTINEL_LINK_URL,
|
|
@@ -5178,6 +5474,7 @@ export {
|
|
|
5178
5474
|
preprocessLaTeX,
|
|
5179
5475
|
rehypeFooterAdorn,
|
|
5180
5476
|
rehypeRebaseHashLinks_default as rehypeRebaseHashLinks,
|
|
5477
|
+
rehypeVerifyEngineTags,
|
|
5181
5478
|
removeComments,
|
|
5182
5479
|
sanitizeCrossChunkUrl,
|
|
5183
5480
|
sanitizeSchema,
|