@ai-matrx/content-ir 0.20.1 → 0.21.1

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/dist/source.cjs CHANGED
@@ -1208,6 +1208,8 @@ function findTableEnd(lines, start) {
1208
1208
  }
1209
1209
 
1210
1210
  // source/tokenize.ts
1211
+ var QUOTE_PREFIX = /^ {0,3}>(?: ?>)* ?/;
1212
+ var QUOTED_JSON_FENCE_LANGS = /* @__PURE__ */ new Set(["", "json", "jsonc", "json5"]);
1211
1213
  var NOT_WHITESPACE = /\S/;
1212
1214
  var DIRECTIVE_OPEN = /^(:{2,})([A-Za-z][\w-]*)/;
1213
1215
  var MKDOCS_OPEN = /^(!!!|\?\?\?\+?)[ \t]+([A-Za-z][\w-]*)/;
@@ -1697,6 +1699,8 @@ var Tokenizer = class {
1697
1699
  if (indent <= 3 && !listNested && t.startsWith(">")) {
1698
1700
  const callout = this.callout(p, li, t);
1699
1701
  if (callout) return callout;
1702
+ const lifted = this.quotedJsonFence(p, li, seg);
1703
+ if (lifted) return lifted;
1700
1704
  }
1701
1705
  if (atParaStart && indent <= 3 && t.startsWith("[^")) {
1702
1706
  const footnote = this.footnoteDefinition(p, li, t);
@@ -1892,6 +1896,42 @@ var Tokenizer = class {
1892
1896
  streaming: this.streaming
1893
1897
  };
1894
1898
  }
1899
+ /**
1900
+ * A JSON-family fence (unlabelled, json, jsonc, json5) opening on a quoted line. The renderer LIFTS it out
1901
+ * of the quote (matrx-frontend V1, never-raw law): the quote prefix is removed from every line of the
1902
+ * region, so the region is an ordinary top-level fence — drawn as code up to its own closer, which may sit on
1903
+ * a line that carries no `>` at all. The editor must lock at least what the renderer draws, so the island
1904
+ * runs from the quoted opener line to that closer (found on the lines with their quote prefix removed).
1905
+ */
1906
+ quotedJsonFence(p, li, seg) {
1907
+ const m = QUOTE_PREFIX.exec(seg);
1908
+ if (!m) return null;
1909
+ const opener = fenceOpenerOf(seg.slice(m[0].length));
1910
+ if (!opener || opener.char !== "`" || !QUOTED_JSON_FENCE_LANGS.has(opener.lang.toLowerCase())) return null;
1911
+ const base = this.fenceLines;
1912
+ const lines = {
1913
+ ...base,
1914
+ line: (k) => {
1915
+ const text = base.line(k);
1916
+ if (text === null) return null;
1917
+ const q = QUOTE_PREFIX.exec(text);
1918
+ return q ? text.slice(q[0].length) : text;
1919
+ }
1920
+ };
1921
+ let first = li;
1922
+ while (first > 0 && li - first < 400 && QUOTE_PREFIX.test(this.lineText(first - 1))) first--;
1923
+ for (let k = first; k < li; k++) {
1924
+ const o = fenceOpenerOf(lines.line(k) ?? "");
1925
+ if (!o || o.char !== "`" || QUOTED_JSON_FENCE_LANGS.has(o.lang.toLowerCase())) continue;
1926
+ const c = closeFence(lines, k, o);
1927
+ if (!c.closed || c.line >= li) return null;
1928
+ k = c.line;
1929
+ }
1930
+ const end = closeFence(lines, li, opener);
1931
+ const meta = { fence: "`", ticks: opener.ticks, lang: opener.lang };
1932
+ if (end.closed) return this.island("fence", p, this.contentEnds[end.line], true, meta);
1933
+ return this.island("fence", p, this.n, false, meta);
1934
+ }
1895
1935
  /**
1896
1936
  * Backtick fence — THE one closer (`closeFence`, source/code-ranges.ts): the
1897
1937
  * nested-fence rule for markdown fences with the strict-CommonMark retry, the
@@ -1924,44 +1964,14 @@ var Tokenizer = class {
1924
1964
  if (normalized && SPECIAL_CODE_LANGUAGES.has(normalized)) meta.special = normalized;
1925
1965
  const close = closeFence(this.fenceLines, li, opener);
1926
1966
  if (close.closed) {
1927
- const tildeEnd = this.contentEnds[close.line];
1928
- const end = this.rendererOverflow(li + 1, close.line, tildeEnd);
1929
- return this.island("fence", p, end, end === this.n ? this.overflowComplete : true, meta);
1967
+ return this.island("fence", p, this.contentEnds[close.line], true, meta);
1930
1968
  }
1931
1969
  return this.island("fence", p, this.n, false, meta);
1932
1970
  }
1933
- /** Completion of the last `rendererOverflow` that ran to the end of the text. */
1934
- overflowComplete = true;
1935
- /**
1936
- * The renderer's splitter does not know ~~~ fences: it reads the lines inside
1937
- * one as ordinary lines, so a ```` ``` ```` fence (or an XML section, a JSON
1938
- * block…) that STARTS inside the tilde fence can run past its closer. The
1939
- * editor must lock at least what the renderer draws (verify-RC-B3 residual
1940
- * R5), so a tilde island extends over every block the renderer would detect
1941
- * starting inside it. Returns the island's end.
1942
- */
1943
- rendererOverflow(firstLine, closeLine, tildeEnd) {
1944
- let end = tildeEnd;
1945
- this.overflowComplete = true;
1946
- for (let j = firstLine; j <= closeLine && j < this.lineCount; j++) {
1947
- const start = this.lineStarts[j];
1948
- if (this.lineIsBlank(j)) continue;
1949
- if (fenceOpenerOf(this.lineText(j))?.char === "~") continue;
1950
- const inner = this.detectBlockUncached(start, j, false);
1951
- if (!inner) continue;
1952
- if (this.streaming && inner.end >= tildeEnd && this.paragraphMayGrow(inner.end)) {
1953
- this.overflowComplete = false;
1954
- return this.n;
1955
- }
1956
- if (inner.end > end) {
1957
- end = inner.end;
1958
- this.overflowComplete = inner.complete;
1959
- }
1960
- const lastLine = this.lineOf(Math.max(start, inner.end - 1));
1961
- if (lastLine > j) j = lastLine;
1962
- }
1963
- return end;
1964
- }
1971
+ // A tilde island ends at its closer. The renderer's splitter treats `~~~` as a real fence since
1972
+ // matrx-frontend A4 (2026-09-30): the lines inside are code, so nothing that starts inside one runs
1973
+ // past the closer (the 0.14.2 "overflow" assumed the renderer did not know ~~~ and, kept, swallowed the
1974
+ // next fence's opener into the tilde island: a ````md block after a ~~~ block was left unlocked).
1965
1975
  /**
1966
1976
  * A line-leading `$$` that OPENS a math pair (source/math-pairs.ts — the
1967
1977
  * core's rule). A closer, an unpaired `$$`, or a prose pair is never a block:
@@ -2877,20 +2887,443 @@ function resolveReferenceLinks(fragment, defs) {
2877
2887
  return resolved.replace(new RegExp(`${PLACEHOLDER}(\\d+)${PLACEHOLDER}`, "g"), (_m, i) => spans[Number(i)] ?? "");
2878
2888
  }
2879
2889
 
2890
+ // source/code-range-edits.ts
2891
+ function unwrapCodeSpans(text) {
2892
+ if (!text.includes("`")) return text;
2893
+ return mapCodeRanges(text, (range, raw) => range.kind === "span" ? codeSpanText(raw) : raw);
2894
+ }
2895
+ function removeCodeSpans(text) {
2896
+ if (!text.includes("`")) return text;
2897
+ return mapCodeRanges(text, (range, raw) => range.kind === "span" ? "" : raw);
2898
+ }
2899
+ function replaceFences(text, fn) {
2900
+ if (!text.includes("```") && !text.includes("~~~")) return text;
2901
+ return mapCodeRanges(text, (range, raw) => {
2902
+ if (range.kind !== "fence") return raw;
2903
+ const parts = fenceParts(raw);
2904
+ return fn({ lang: parts?.opener.lang ?? "", body: parts?.body ?? raw, closed: parts?.closed ?? false, raw });
2905
+ });
2906
+ }
2907
+ function soleFence(text, options = {}) {
2908
+ const trimmed = text.trim();
2909
+ if (!trimmed.startsWith("`") && !trimmed.startsWith("~")) return null;
2910
+ const ranges = findCodeRanges(trimmed);
2911
+ const only = ranges.length === 1 ? ranges[0] : void 0;
2912
+ if (!only || only.kind !== "fence" || only.start !== 0 || only.end !== trimmed.length) return null;
2913
+ const parts = fenceParts(trimmed);
2914
+ if (!parts || !parts.closed && !options.allowUnclosed) return null;
2915
+ return { lang: parts.opener.lang, body: parts.body, closed: parts.closed };
2916
+ }
2917
+
2918
+ // source/plain-text.ts
2919
+ var INLINE_PATTERNS = [
2920
+ // [label](href) → label. Runs first so emphasis inside a label still unwraps.
2921
+ [/\[([^\]]+)\]\([^)]*\)/g, "$1"],
2922
+ [/\*\*\*(?=\S)([\s\S]*?\S)\*\*\*/g, "$1"],
2923
+ [/___(?=\S)([\s\S]*?\S)___/g, "$1"],
2924
+ [/\*\*(?=\S)([\s\S]*?\S)\*\*/g, "$1"],
2925
+ [/__(?=\S)([\s\S]*?\S)__/g, "$1"],
2926
+ [/~~(?=\S)([\s\S]*?\S)~~/g, "$1"],
2927
+ [/\*(?=\S)([^*\n]*?\S)\*/g, "$1"],
2928
+ // Underscore italics only between word boundaries: snake_case_names are not
2929
+ // emphasis, and mangling an identifier is a worse defect than a stray marker.
2930
+ [/(^|[\s(])_(?=\S)([^_\n]*?\S)_(?=[\s).,;:!?]|$)/g, "$1$2"]
2931
+ ];
2932
+ var MATH_STRUCTURAL = [
2933
+ [/\\(?:d|t)?frac\s*\{([^{}]*)\}\s*\{([^{}]*)\}/g, "$1/$2"],
2934
+ [/\\sqrt\s*\{([^{}]*)\}/g, "\u221A($1)"]
2935
+ ];
2936
+ var MATH_PATTERNS = [
2937
+ // Environments (\begin{aligned} … \end{aligned}) carry no meaning in a
2938
+ // one-line preview; drop the wrapper, keep the contents. Without this the
2939
+ // catch-all below turned them into the word "aligned" twice.
2940
+ [/\\(?:begin|end)\s*\{[^{}]*\}/g, " "],
2941
+ // A TeX line break inside a preview is just a space.
2942
+ [/\\\\/g, " "],
2943
+ // TeX spacing commands (\, \; \: thin/medium space, \! negative space).
2944
+ [/\\[,;:]/g, " "],
2945
+ [/\\!/g, ""],
2946
+ // \left\{ … \right\} — the escaped-brace forms, which the character-class
2947
+ // rule below cannot reach because the brace is preceded by a backslash.
2948
+ [/\\(?:left|right)\s*\\?([([\]|){}])/g, "$1"],
2949
+ // NOTE: every command below ends with (?![a-zA-Z]) and NOT \b. `_` is a WORD
2950
+ // character, so \b fails after `\sum_` — which silently left every
2951
+ // summation, integral and limit card reading as "sum_" / "int_".
2952
+ [/\\times(?![a-zA-Z])/g, "\xD7"],
2953
+ [/\\div(?![a-zA-Z])/g, "\xF7"],
2954
+ [/\\pm(?![a-zA-Z])/g, "\xB1"],
2955
+ [/\\cdot(?![a-zA-Z])/g, "\xB7"],
2956
+ [/\\leq(?![a-zA-Z])/g, "\u2264"],
2957
+ [/\\geq(?![a-zA-Z])/g, "\u2265"],
2958
+ [/\\neq(?![a-zA-Z])/g, "\u2260"],
2959
+ [/\\approx(?![a-zA-Z])/g, "\u2248"],
2960
+ [/\\infty(?![a-zA-Z])/g, "\u221E"],
2961
+ [/\\pi(?![a-zA-Z])/g, "\u03C0"],
2962
+ [/\\theta(?![a-zA-Z])/g, "\u03B8"],
2963
+ [/\\alpha(?![a-zA-Z])/g, "\u03B1"],
2964
+ [/\\beta(?![a-zA-Z])/g, "\u03B2"],
2965
+ [/\\Delta(?![a-zA-Z])/g, "\u0394"],
2966
+ [/\\delta(?![a-zA-Z])/g, "\u03B4"],
2967
+ [/\\sum(?![a-zA-Z])/g, "\u03A3"],
2968
+ [/\\prod(?![a-zA-Z])/g, "\u220F"],
2969
+ [/\\int(?![a-zA-Z])/g, "\u222B"],
2970
+ [/\\lim(?![a-zA-Z])/g, "lim"],
2971
+ [/\\(?:rightarrow|to)(?![a-zA-Z])/g, "\u2192"],
2972
+ // Braces that only ever grouped a script or argument: ^{2} → ^2, _{i} → _i.
2973
+ [/([_^])\s*\{([^{}]*)\}/g, "$1$2"],
2974
+ // Any remaining single-argument command: \text{x} / \mathrm{x} → x.
2975
+ [/\\[a-zA-Z]+\s*\{([^{}]*)\}/g, "$1"],
2976
+ // Bare commands we did not translate: drop the backslash, keep the word.
2977
+ [/\\([a-zA-Z]+)/g, "$1"]
2978
+ ];
2979
+ var MATH_REGIONS = [
2980
+ /\\\[([\s\S]*?)\\\]/g,
2981
+ /\\\(([\s\S]*?)\\\)/g,
2982
+ /\$\$([\s\S]*?)\$\$/g
2983
+ ];
2984
+ function mathToReadable(expression) {
2985
+ let text = expression;
2986
+ for (let pass = 0; pass < 8; pass += 1) {
2987
+ const before = text;
2988
+ for (const [pattern, replacement] of MATH_STRUCTURAL) {
2989
+ text = text.replace(pattern, replacement);
2990
+ }
2991
+ if (text === before) break;
2992
+ }
2993
+ for (const [pattern, replacement] of MATH_PATTERNS) {
2994
+ text = text.replace(pattern, replacement);
2995
+ }
2996
+ return text.trim();
2997
+ }
2998
+ function markdownToPlainText(value) {
2999
+ if (!value) return "";
3000
+ const mathChunks = [];
3001
+ let text = value;
3002
+ for (const region of MATH_REGIONS) {
3003
+ text = text.replace(region, (_match, inner) => {
3004
+ mathChunks.push(mathToReadable(inner));
3005
+ return `\uE000MATH${mathChunks.length - 1}\uE001`;
3006
+ });
3007
+ }
3008
+ for (const [pattern, replacement] of INLINE_PATTERNS) {
3009
+ text = text.replace(pattern, replacement);
3010
+ }
3011
+ text = unwrapCodeSpans(text);
3012
+ text = text.replace(
3013
+ /\uE000MATH(\d+)\uE001/g,
3014
+ (_m, index) => mathChunks[Number(index)] ?? ""
3015
+ );
3016
+ return text.replace(/[ \t]{2,}/g, " ").trim();
3017
+ }
3018
+ function unwrapKindEnvelopes(value) {
3019
+ if (!value) return "";
3020
+ if (!value.includes("<artifact")) return value;
3021
+ return tokenizeSource(value).map((block) => {
3022
+ if (block.kind !== "island" || block.islandType !== "xml_attr" && block.islandType !== "xml_container") {
3023
+ return block.raw;
3024
+ }
3025
+ const match = /^\s*<artifact\b[^>]*>([\s\S]*?)<\/artifact>\s*$/.exec(block.raw);
3026
+ return match ? (match[1] ?? "").replace(/^\n/, "").replace(/\n$/, "") : block.raw;
3027
+ }).join("");
3028
+ }
3029
+
3030
+ // source/clean-markdown.ts
3031
+ var cleanMarkdown = (text) => {
3032
+ if (!text || typeof text !== "string") return "";
3033
+ let cleanedText = text;
3034
+ const lines = cleanedText.split("\n");
3035
+ const processedLines = [];
3036
+ for (let line of lines) {
3037
+ let processedLine = line;
3038
+ if (processedLine.trim() === "") {
3039
+ processedLines.push(processedLine);
3040
+ continue;
3041
+ }
3042
+ processedLine = processedLine.replace(/^#{1,6}\s+(.+)$/, "$1");
3043
+ processedLine = processedLine.replace(/(\*\*|__)(.*?)\1/, "$2");
3044
+ processedLine = processedLine.replace(/(\*|_)(.*?)\1/, "$2");
3045
+ processedLine = unwrapCodeSpans(processedLine);
3046
+ processedLine = processedLine.replace(/\[([^\]]+)\]\(([^)]+)\)/, "$1");
3047
+ processedLine = processedLine.replace(/!\[([^\]]*)\]\(([^)]+)\)/, "$1");
3048
+ processedLine = processedLine.replace(/^>\s*(.+)$/, "$1");
3049
+ processedLine = processedLine.replace(/^(\*{3,}|-{3,}|_{3,})$/, "");
3050
+ processedLine = processedLine.replace(/^(\s*[-+*]\s+|\s*\d+\.\s+)(.+)$/, "$2");
3051
+ processedLine = processedLine.replace(/<\/?[^>]+(>|$)/g, "");
3052
+ processedLines.push(processedLine);
3053
+ }
3054
+ cleanedText = processedLines.join("\n");
3055
+ cleanedText = replaceFences(cleanedText, ({ body }) => body);
3056
+ return cleanedText;
3057
+ };
3058
+
3059
+ // source/fence-meta.ts
3060
+ var FENCE_META_KEY = "fenceMeta";
3061
+ function splitFenceInfo(info) {
3062
+ const trimmed = info.trim();
3063
+ if (!trimmed) return {};
3064
+ const firstSpace = trimmed.search(/\s/);
3065
+ let token = firstSpace === -1 ? trimmed : trimmed.slice(0, firstSpace);
3066
+ let rest = firstSpace === -1 ? "" : trimmed.slice(firstSpace).trim();
3067
+ const braceAt = token.indexOf("{");
3068
+ if (braceAt > 0) {
3069
+ rest = `${token.slice(braceAt)} ${rest}`.trim();
3070
+ token = token.slice(0, braceAt);
3071
+ }
3072
+ const colonAt = token.indexOf(":");
3073
+ if (colonAt > 0 && colonAt < token.length - 1) {
3074
+ const filename = token.slice(colonAt + 1);
3075
+ rest = `title="${filename}" ${rest}`.trim();
3076
+ token = token.slice(0, colonAt);
3077
+ }
3078
+ if (token.startsWith("{")) {
3079
+ rest = `${token} ${rest}`.trim();
3080
+ token = "";
3081
+ }
3082
+ const out = {};
3083
+ if (token) out.language = token;
3084
+ if (rest) out.meta = rest;
3085
+ return out;
3086
+ }
3087
+ var TITLE_RE = /(?:^|\s)(?:title|filename|file)=(?:"([^"]*)"|'([^']*)'|(\S+))/i;
3088
+ var RANGES_RE = /(?:^|\s)\{([\d\s,-]+)\}/;
3089
+ var LINE_NUMBERS_RE = /(?:^|\s)showLineNumbers(?:\{(\d+)\})?(?=\s|$)/;
3090
+ var MAX_HIGHLIGHT_LINES = 1e4;
3091
+ function parseFenceMeta(meta) {
3092
+ const result = { highlightLines: [] };
3093
+ if (!meta) return result;
3094
+ const title = TITLE_RE.exec(meta);
3095
+ if (title) {
3096
+ const value = (title[1] ?? title[2] ?? title[3] ?? "").trim();
3097
+ if (value) result.title = value;
3098
+ }
3099
+ const ranges = RANGES_RE.exec(meta);
3100
+ if (ranges) result.highlightLines = parseLineRanges(ranges[1] ?? "");
3101
+ const lineNumbers = LINE_NUMBERS_RE.exec(meta);
3102
+ if (lineNumbers) {
3103
+ result.showLineNumbers = true;
3104
+ if (lineNumbers[1]) {
3105
+ const start = Number.parseInt(lineNumbers[1], 10);
3106
+ if (Number.isFinite(start) && start > 0) result.startLine = start;
3107
+ }
3108
+ }
3109
+ return result;
3110
+ }
3111
+ function parseLineRanges(spec) {
3112
+ const lines = /* @__PURE__ */ new Set();
3113
+ for (const part of spec.split(",")) {
3114
+ const piece = part.trim();
3115
+ if (!piece) continue;
3116
+ const range = /^(\d+)\s*-\s*(\d+)$/.exec(piece);
3117
+ if (range) {
3118
+ const from = Number.parseInt(range[1] ?? "", 10);
3119
+ const to = Number.parseInt(range[2] ?? "", 10);
3120
+ if (from < 1 || to < from) continue;
3121
+ for (let n = from; n <= to && lines.size < MAX_HIGHLIGHT_LINES; n += 1) {
3122
+ lines.add(n);
3123
+ }
3124
+ continue;
3125
+ }
3126
+ if (/^\d+$/.test(piece)) {
3127
+ const n = Number.parseInt(piece, 10);
3128
+ if (n >= 1) lines.add(n);
3129
+ }
3130
+ }
3131
+ return [...lines].sort((a, b) => a - b);
3132
+ }
3133
+
3134
+ // source/directive-container.ts
3135
+ var DIRECTIVE_CONTAINER_OPEN = /^[ \t]{0,3}(:{3,})[A-Za-z][\w-]*/;
3136
+ var CLOSE = /^[ \t]{0,3}(:{3,})[ \t]*$/;
3137
+ var DirectiveContainerTracker = class {
3138
+ stack;
3139
+ fence = null;
3140
+ constructor(openingLine) {
3141
+ const m = DIRECTIVE_CONTAINER_OPEN.exec(openingLine);
3142
+ this.stack = [m ? m[1].length : 3];
3143
+ }
3144
+ /** Feed the next line (after the opener). True once the outermost container has closed on this line. */
3145
+ consume(line) {
3146
+ if (this.fence) {
3147
+ if (this.fence.feed(line)) this.fence = null;
3148
+ return false;
3149
+ }
3150
+ const opener = fenceOpenerOf(line);
3151
+ if (opener) {
3152
+ this.fence = new FenceReader(opener);
3153
+ return false;
3154
+ }
3155
+ const open = DIRECTIVE_CONTAINER_OPEN.exec(line);
3156
+ if (open) {
3157
+ this.stack.push(open[1].length);
3158
+ return false;
3159
+ }
3160
+ const close = CLOSE.exec(line);
3161
+ if (close && close[1].length >= (this.stack[this.stack.length - 1] ?? 3)) {
3162
+ this.stack.pop();
3163
+ return this.stack.length === 0;
3164
+ }
3165
+ return false;
3166
+ }
3167
+ };
3168
+
3169
+ // source/image-figure.ts
3170
+ var TITLED_IMAGE_LINE = /^[ \t]{0,3}!\[[^\]\n]*\]\(\s*<?[^\s)>]+>?\s+(?:"[^"\n]+"|'[^'\n]+')\s*\)[ \t]*$/;
3171
+
3172
+ // source/inline-code-span.ts
3173
+ function isInsideInlineCode(line, at) {
3174
+ let i = 0;
3175
+ while (i <= at && i < line.length) {
3176
+ if (line[i] === "\\") {
3177
+ i += 2;
3178
+ continue;
3179
+ }
3180
+ if (line[i] !== "`") {
3181
+ i += 1;
3182
+ continue;
3183
+ }
3184
+ let run = 0;
3185
+ while (line[i + run] === "`") run += 1;
3186
+ let close = -1;
3187
+ for (let j = i + run; j < line.length; ) {
3188
+ if (line[j] !== "`") {
3189
+ j += 1;
3190
+ continue;
3191
+ }
3192
+ let r = 0;
3193
+ while (line[j + r] === "`") r += 1;
3194
+ if (r === run) {
3195
+ close = j;
3196
+ break;
3197
+ }
3198
+ j += r;
3199
+ }
3200
+ if (close === -1) {
3201
+ i += run;
3202
+ continue;
3203
+ }
3204
+ if (at > i && at < close + run) return true;
3205
+ i = close + run;
3206
+ }
3207
+ return false;
3208
+ }
3209
+ function indexOutsideInlineCode(line, needle, from = 0) {
3210
+ for (let idx = line.indexOf(needle, from); idx !== -1; idx = line.indexOf(needle, idx + 1)) {
3211
+ if (!isInsideInlineCode(line, idx)) return idx;
3212
+ }
3213
+ return -1;
3214
+ }
3215
+ function hasUnclosedBacktickRun(text) {
3216
+ let i = 0;
3217
+ while (i < text.length) {
3218
+ if (text[i] === "\\") {
3219
+ i += 2;
3220
+ continue;
3221
+ }
3222
+ if (text[i] !== "`") {
3223
+ i += 1;
3224
+ continue;
3225
+ }
3226
+ let run = 0;
3227
+ while (text[i + run] === "`") run += 1;
3228
+ let close = -1;
3229
+ for (let j = i + run; j < text.length; ) {
3230
+ if (text[j] !== "`") {
3231
+ j += 1;
3232
+ continue;
3233
+ }
3234
+ let r = 0;
3235
+ while (text[j + r] === "`") r += 1;
3236
+ if (r === run) {
3237
+ close = j;
3238
+ break;
3239
+ }
3240
+ j += r;
3241
+ }
3242
+ if (close === -1) return true;
3243
+ i = close + run;
3244
+ }
3245
+ return false;
3246
+ }
3247
+
3248
+ // source/xml-tag-balance.ts
3249
+ function initialXmlBalance() {
3250
+ return { depth: 1, fence: null };
3251
+ }
3252
+ function escapeRegExp(value) {
3253
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3254
+ }
3255
+ function findBalancedXmlClose(line, tagName, state, { trackFences = true, nest = true } = {}) {
3256
+ if (state.fence) {
3257
+ if (state.fence.feed(line)) state.fence = null;
3258
+ return -1;
3259
+ }
3260
+ const opener = trackFences ? fenceOpenerOf(line) : null;
3261
+ if (opener) {
3262
+ state.fence = new FenceReader(opener);
3263
+ return -1;
3264
+ }
3265
+ const tag = new RegExp(
3266
+ `<(\\/?)${escapeRegExp(tagName)}(?=[\\s>/])[^<>]*?(\\/?)>`,
3267
+ "g"
3268
+ );
3269
+ for (const match of line.matchAll(tag)) {
3270
+ const closing = match[1] === "/";
3271
+ const selfClosing = match[2] === "/";
3272
+ if (closing) {
3273
+ state.depth -= 1;
3274
+ if (state.depth === 0) return match.index ?? -1;
3275
+ } else if (nest && !selfClosing && line.slice(0, match.index).trim() === "") {
3276
+ state.depth += 1;
3277
+ }
3278
+ }
3279
+ return -1;
3280
+ }
3281
+
3282
+ // source/gfm-table-lines.ts
3283
+ function findWholeTableStart(lines, from = 0) {
3284
+ for (let i = Math.max(0, from); i + 1 < lines.length; i += 1) if (tableStartsAt(lines, i)) return i;
3285
+ return -1;
3286
+ }
3287
+ function startsLikeTableRow(line) {
3288
+ return /^\s*\|/.test(line);
3289
+ }
3290
+ function isGrowingDelimiterRow(line) {
3291
+ return /^[\s|:-]*-[\s|:-]*$/.test(line);
3292
+ }
3293
+ function trailingTableStart(lines, end = lines.length) {
3294
+ const isTableLine = (line) => startsLikeTableRow(line) || continuesTable(line.trimStart());
3295
+ let start = end;
3296
+ while (start > 0 && isTableLine(lines[start - 1] ?? "")) start -= 1;
3297
+ if (start === end && end > 1 && isGrowingDelimiterRow(lines[end - 1] ?? "") && continuesTable((lines[end - 2] ?? "").trimStart())) {
3298
+ start = end - 1;
3299
+ while (start > 0 && isTableLine(lines[start - 1] ?? "")) start -= 1;
3300
+ }
3301
+ for (let head = start; head < end; head += 1) {
3302
+ if (startsLikeTableRow(lines[head] ?? "")) return head;
3303
+ if (end - head > 1 && isGrowingDelimiterRow(lines[head + 1] ?? "")) return head;
3304
+ }
3305
+ return end;
3306
+ }
3307
+
2880
3308
  exports.AFTER_WINDOW = AFTER_WINDOW;
2881
3309
  exports.BacktickRuns = BacktickRuns;
2882
3310
  exports.CALLOUT_NAMES = CALLOUT_NAMES;
3311
+ exports.DIRECTIVE_CONTAINER_OPEN = DIRECTIVE_CONTAINER_OPEN;
3312
+ exports.DirectiveContainerTracker = DirectiveContainerTracker;
3313
+ exports.FENCE_META_KEY = FENCE_META_KEY;
2883
3314
  exports.FENCE_OPENER_WHITESPACE = FENCE_OPENER_WHITESPACE;
2884
3315
  exports.FENCE_WHITESPACE = FENCE_WHITESPACE;
2885
3316
  exports.FenceReader = FenceReader;
2886
3317
  exports.NESTING_FENCE_LANGUAGES = NESTING_FENCE_LANGUAGES;
2887
3318
  exports.SourceSpliceError = SourceSpliceError;
3319
+ exports.TITLED_IMAGE_LINE = TITLED_IMAGE_LINE;
2888
3320
  exports.XmlContainerTracker = XmlContainerTracker;
2889
3321
  exports.blockAt = blockAt;
2890
3322
  exports.blockEdit = blockEdit;
2891
3323
  exports.blockRangeEdit = blockRangeEdit;
2892
3324
  exports.buildCodePointIndex = buildCodePointIndex;
2893
3325
  exports.classifyInnerFenceLine = classifyInnerFenceLine;
3326
+ exports.cleanMarkdown = cleanMarkdown;
2894
3327
  exports.closeFence = closeFence;
2895
3328
  exports.codeSpanText = codeSpanText;
2896
3329
  exports.collectLinkDefinitions = collectLinkDefinitions;
@@ -2899,14 +3332,21 @@ exports.fenceLineKinds = fenceLineKinds;
2899
3332
  exports.fenceNestsInnerFences = fenceNestsInnerFences;
2900
3333
  exports.fenceOpenerOf = fenceOpenerOf;
2901
3334
  exports.fenceParts = fenceParts;
3335
+ exports.findBalancedXmlClose = findBalancedXmlClose;
2902
3336
  exports.findCodeRanges = findCodeRanges;
2903
3337
  exports.findInlineCodeSpans = findInlineCodeSpans;
2904
3338
  exports.findLinkDefinitionLines = findLinkDefinitionLines;
2905
3339
  exports.findTableEnd = findTableEnd;
2906
3340
  exports.findTableStart = findTableStart;
3341
+ exports.findWholeTableStart = findWholeTableStart;
3342
+ exports.hasUnclosedBacktickRun = hasUnclosedBacktickRun;
3343
+ exports.indexOutsideInlineCode = indexOutsideInlineCode;
3344
+ exports.initialXmlBalance = initialXmlBalance;
2907
3345
  exports.isEscapedBracketMath = isEscapedBracketMath;
2908
3346
  exports.isGfmDelimiterRow = isGfmDelimiterRow;
3347
+ exports.isGrowingDelimiterRow = isGrowingDelimiterRow;
2909
3348
  exports.isHtmlBlockTagName = isHtmlBlockTagName;
3349
+ exports.isInsideInlineCode = isInsideInlineCode;
2910
3350
  exports.isMathPlaceholder = isMathPlaceholder;
2911
3351
  exports.isPipeLedRow = isPipeLedRow;
2912
3352
  exports.isSingleDollarMath = isSingleDollarMath;
@@ -2920,29 +3360,41 @@ exports.mapCodeRanges = mapCodeRanges;
2920
3360
  exports.mapInlineCodeSpans = mapInlineCodeSpans;
2921
3361
  exports.mapPosition = mapPosition;
2922
3362
  exports.mapRange = mapRange;
3363
+ exports.markdownToPlainText = markdownToPlainText;
3364
+ exports.mathToReadable = mathToReadable;
2923
3365
  exports.normalizeLinkLabel = normalizeLinkLabel;
2924
3366
  exports.opensStrippedHtmlBlock = opensStrippedHtmlBlock;
2925
3367
  exports.opensTable = opensTable;
2926
3368
  exports.pairDisplayMath = pairDisplayMath;
3369
+ exports.parseFenceMeta = parseFenceMeta;
2927
3370
  exports.parseFenceOpener = parseFenceOpener;
3371
+ exports.parseLineRanges = parseLineRanges;
2928
3372
  exports.pendingCodeSpanStart = pendingCodeSpanStart;
2929
3373
  exports.pendingDisplayMathOpener = pendingDisplayMathOpener;
2930
3374
  exports.readXmlTag = readXmlTag;
3375
+ exports.removeCodeSpans = removeCodeSpans;
3376
+ exports.replaceFences = replaceFences;
2931
3377
  exports.resolveReferenceLinks = resolveReferenceLinks;
2932
3378
  exports.rowCells = rowCells;
2933
3379
  exports.singleDollarAfter = singleDollarAfter;
2934
3380
  exports.singleDollarMathEnd = singleDollarMathEnd;
3381
+ exports.soleFence = soleFence;
2935
3382
  exports.spliceSave = spliceSave;
3383
+ exports.splitFenceInfo = splitFenceInfo;
2936
3384
  exports.splitRowSegments = splitRowSegments;
2937
3385
  exports.splitsSurrogatePair = splitsSurrogatePair;
2938
3386
  exports.startsHtmlBlock = startsHtmlBlock;
3387
+ exports.startsLikeTableRow = startsLikeTableRow;
2939
3388
  exports.startsPipelessTable = startsPipelessTable;
2940
3389
  exports.tableContainerIndent = tableContainerIndent;
2941
3390
  exports.tableStartsAt = tableStartsAt;
2942
3391
  exports.toCodePointOffset = toCodePointOffset;
2943
3392
  exports.toUtf16Offset = toUtf16Offset;
2944
3393
  exports.tokenizeSource = tokenizeSource;
3394
+ exports.trailingTableStart = trailingTableStart;
2945
3395
  exports.trimFenceLine = trimFenceLine;
2946
3396
  exports.unescapeCellPipes = unescapeCellPipes;
3397
+ exports.unwrapCodeSpans = unwrapCodeSpans;
3398
+ exports.unwrapKindEnvelopes = unwrapKindEnvelopes;
2947
3399
  //# sourceMappingURL=source.cjs.map
2948
3400
  //# sourceMappingURL=source.cjs.map