@ai-matrx/content-ir 0.12.0 → 0.14.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/dist/source.d.cts CHANGED
@@ -51,12 +51,25 @@ type BlockIslandType =
51
51
  | "anchor"
52
52
  /** `$$ … $$` display math on its own lines. */
53
53
  | "math_block"
54
- /** YAML front matter at the start of the text. */
54
+ /** YAML (`---`) or TOML (`+++`) front matter at the start of the text (meta.format). */
55
55
  | "front_matter"
56
56
  /** A box-drawing tree diagram. */
57
- | "tree";
57
+ | "tree"
58
+ /**
59
+ * A generic-directive container `:::name[label]{attrs}` … `:::` (tabs,
60
+ * columns, details, figures, callouts, TOC — meta.name), a leaf directive
61
+ * `::name` on its own line (meta.leaf), or a MkDocs admonition
62
+ * `!!! type "Title"` / `??? type` with its indented body (meta.syntax "mkdocs").
63
+ */
64
+ | "directive"
65
+ /** A GitHub alert / Obsidian callout: a blockquote opening `> [!TYPE]` (meta.name). */
66
+ | "callout"
67
+ /** A footnote definition `[^id]: …` with its indented continuation lines (meta.id). */
68
+ | "footnote_def";
58
69
  /** Island types that live inside a prose block. */
59
- type InlineIslandType = "variable" | "cite" | "math_inline" | "html_tag" | "xml_tag" | "xml_inline" | "html_comment" | "anchor" | "kind_json" | "media_ref";
70
+ type InlineIslandType = "variable" | "cite" | "math_inline" | "html_tag" | "xml_tag" | "xml_inline" | "html_comment" | "anchor" | "kind_json" | "media_ref"
71
+ /** `[[Page]]`, `[[Page|alias]]` (meta.target) — or `![[Page]]` (meta.embed). */
72
+ | "wikilink";
60
73
  type IslandType = BlockIslandType | InlineIslandType;
61
74
  type IslandMeta = Readonly<Record<string, string | number | boolean>>;
62
75
  interface SourceSpan {
@@ -92,7 +105,16 @@ interface SourceBlock extends SourceSpan {
92
105
  * Cut `text` into blocks whose raw concatenation is exactly `text`.
93
106
  * Never throws; unclosed constructs are islands with `complete: false`.
94
107
  */
95
- declare function tokenizeSource(text: string): SourceBlock[];
108
+ interface TokenizeOptions {
109
+ /**
110
+ * The text is a prefix of a message still arriving. The final line (no
111
+ * terminator yet) can still grow — a bare ``` there may become ```bash — so
112
+ * it closes no fence until its newline arrives (verify-RC-B3 residual R2).
113
+ * Omit for stored text: a complete document's last line is final.
114
+ */
115
+ readonly streaming?: boolean;
116
+ }
117
+ declare function tokenizeSource(text: string, options?: TokenizeOptions): SourceBlock[];
96
118
  /** The exact source the blocks were cut from. */
97
119
  declare function joinSource(blocks: readonly SourceBlock[]): string;
98
120
  /** Every island — block-level and inline — in document order. */
@@ -114,20 +136,30 @@ declare function blockAt(blocks: readonly SourceBlock[], offset: number): Source
114
136
  * uses to carry every live anchor through the save
115
137
  * (STORE-DESIGN §3.19 — the ProseMirror / Google Docs position-mapping
116
138
  * model), and
117
- * - an integrity report: every island outside the edited ranges must still
139
+ * - an integrity guarantee: every island not explicitly replaced must still
118
140
  * be the same island, at its mapped position, in the new text. An edit
119
- * that opens an unclosed fence and swallows a kind below it is caught
120
- * here instead of being saved silently.
141
+ * that opens an unclosed fence and swallows a kind below it is REFUSED.
142
+ *
143
+ * ISLANDS CHANGE ONLY THROUGH `islandEdit`. A prose/range edit must hand back
144
+ * every island inside its range byte-identical and in order (a visual editor
145
+ * holds them as atoms); if one is altered or dropped the save throws
146
+ * `SourceSpliceError("island_edit")` naming the island. A kind editor or code
147
+ * view changes an island with `islandEdit(island, newRaw)`.
121
148
  *
122
149
  * A no-edit save (or edits whose text equals the original block) returns the
123
150
  * original string itself — byte-identical, zero changes.
124
151
  */
125
152
 
126
- /** Replace `[start, end)` (UTF-16, on block boundaries) of the original with `text`. */
153
+ /**
154
+ * Replace `[start, end)` (UTF-16) of the original with `text`. A plain edit
155
+ * starts and ends on block boundaries; an island edit (`island: true`, made by
156
+ * `islandEdit`) names exactly one island's span.
157
+ */
127
158
  interface SourceEdit {
128
159
  readonly start: number;
129
160
  readonly end: number;
130
161
  readonly text: string;
162
+ readonly island?: boolean;
131
163
  }
132
164
  interface SourceChange {
133
165
  /** The block-aligned range the edit named, in the ORIGINAL text. */
@@ -168,7 +200,7 @@ interface SpliceResult {
168
200
  /** Tokenization of the new text. */
169
201
  readonly blocks: readonly SourceBlock[];
170
202
  }
171
- type SourceSpliceErrorCode = "out_of_range" | "misaligned" | "overlap" | "stale_blocks" | "integrity";
203
+ type SourceSpliceErrorCode = "out_of_range" | "misaligned" | "overlap" | "stale_blocks" | "island_edit" | "integrity";
172
204
  declare class SourceSpliceError extends Error {
173
205
  readonly code: SourceSpliceErrorCode;
174
206
  constructor(code: SourceSpliceErrorCode, message: string);
@@ -176,11 +208,21 @@ declare class SourceSpliceError extends Error {
176
208
  interface SpliceOptions {
177
209
  /** The tokenization of `original`, when the caller already holds it. */
178
210
  readonly blocks?: readonly SourceBlock[];
179
- /** Throw `SourceSpliceError("integrity")` instead of reporting a disturbed island. */
211
+ /**
212
+ * Default `true`: a save that disturbs any island it did not explicitly
213
+ * replace throws `SourceSpliceError("integrity")`. `false` is for TOOLING
214
+ * ONLY (diagnostic scripts that want the report instead of the refusal) —
215
+ * no editor or persistence path may pass it.
216
+ */
180
217
  readonly requireIntegrity?: boolean;
181
218
  }
182
219
  /** An edit that replaces one block's raw text. */
183
220
  declare function blockEdit(block: SourceBlock, text: string): SourceEdit;
221
+ /** The one door that changes an island: replace exactly its span with `text`. */
222
+ declare function islandEdit(island: {
223
+ readonly start: number;
224
+ readonly end: number;
225
+ }, text: string): SourceEdit;
184
226
  /** An edit that replaces a contiguous run of blocks `[first, last]`. */
185
227
  declare function blockRangeEdit(first: SourceBlock, last: SourceBlock, text: string): SourceEdit;
186
228
  /**
@@ -252,8 +294,9 @@ declare function toUtf16Offset(text: string, codePoint: number): number;
252
294
  *
253
295
  * Pandoc's rule — the opening `$` is not followed by whitespace, the closing
254
296
  * `$` is not preceded by whitespace and not followed by a digit — plus a math
255
- * signal: a TeX command or operator (`\alpha`, `^`, `_`, `{`, `=`, …), or a
256
- * lone variable (`$x$`, `$n$`, `$x'$`). Content that opens with a digit needs
297
+ * signal: a TeX command or operator (`\alpha`, `^`, `_`, `{`, `=`, …), a
298
+ * lone variable (`$x$`, `$n$`, `$x'$`), or a single-letter math shape
299
+ * (`$f(g(x))$`, `$u v$`, `$f'(x)$` — see `isMathShape`). Content that opens with a digit needs
257
300
  * a real TeX signal, so a price range can never read as math.
258
301
  */
259
302
  declare function isSingleDollarMath(content: string, after: string | undefined): boolean;
@@ -286,7 +329,12 @@ interface ReadXmlTag {
286
329
  value: string;
287
330
  }>;
288
331
  }
289
- declare function readXmlTag(content: string, start: number): ReadXmlTag | null;
332
+ /**
333
+ * `find(needle, from)` must behave like `content.indexOf(needle, from)`; the
334
+ * tokenizer passes a cached occurrence index so a text full of unclosed
335
+ * attribute quotes stays linear. Behaviour is identical either way.
336
+ */
337
+ declare function readXmlTag(content: string, start: number, find?: (needle: string, from: number) => number): ReadXmlTag | null;
290
338
  /**
291
339
  * Balances ONE unknown root tag line by line, ignoring lookalike tags inside
292
340
  * fenced code, inline code spans, comments and CDATA. `consumeLine` returns
@@ -303,4 +351,60 @@ declare class XmlContainerTracker {
303
351
  consumeLine(line: string, startOffset?: number): number | null;
304
352
  }
305
353
 
306
- export { type BlockIslandType, type CodePointIndex, type DisturbedIsland, type InlineIslandType, type IslandMeta, type IslandType, type MapOptions, type MappedPosition, type MappedRange, type ReadXmlTag, type SourceBlock, type SourceBlockKind, type SourceChange, type SourceEdit, type SourceIsland, type SourceSpan, SourceSpliceError, type SourceSpliceErrorCode, type SpliceIntegrity, type SpliceOptions, type SpliceResult, XmlContainerTracker, blockAt, blockEdit, blockRangeEdit, buildCodePointIndex, isSingleDollarMath, joinSource, listIslands, mapPosition, mapRange, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource };
354
+ /** Fence languages whose body is itself a markdown document. */
355
+ declare const NESTING_FENCE_LANGUAGES: ReadonlySet<string>;
356
+ /** True when a fence opened with this info-string language nests inner fences. */
357
+ declare function fenceNestsInnerFences(language: string | undefined | null): boolean;
358
+ type InnerFenceLine =
359
+ /** Not a fence line — ordinary content of the outer fence. */
360
+ "content"
361
+ /** ```lang inside a markdown fence — content, and one level deeper. */
362
+ | "open-nested"
363
+ /** Bare ``` that closes the innermost nested fence — content, one level up. */
364
+ | "close-nested"
365
+ /** Bare ``` that closes the OUTER fence. */
366
+ | "close-outer";
367
+ /**
368
+ * Classify one line inside an open backtick fence, already trimmed with
369
+ * {@link trimFenceLine} (never a language's own `trim()`).
370
+ *
371
+ * @param trimmed the line with surrounding whitespace removed
372
+ * @param openTicks backtick count of the outer fence's opener
373
+ * @param nests whether the outer fence follows the nesting rule
374
+ * @param nestedDepth how many nested fences are open right now
375
+ */
376
+ /**
377
+ * The whitespace a fence line may carry around its backticks and info string:
378
+ * CommonMark's ASCII whitespace — space, tab, LF, CR, form feed, vertical tab.
379
+ * Defined HERE, not by a language's `trim()`: JavaScript's `trim()` also strips
380
+ * U+FEFF, U+00A0 and the Unicode spaces, while Python's `strip()` also strips
381
+ * U+0085 and U+001C–U+001F — which made the two twins disagree on lines such
382
+ * as ```` ```\uFEFF ```` (verify-RC-B3 residual R4). Every caller trims a line
383
+ * with `trimFenceLine` before classifying it; the Python twin mirrors both.
384
+ */
385
+ declare const FENCE_WHITESPACE = " \t\n\r\f\v";
386
+ /** Strip {@link FENCE_WHITESPACE} (and nothing else) from both ends of a line. */
387
+ declare function trimFenceLine(line: string): string;
388
+ declare function classifyInnerFenceLine(trimmed: string, openTicks: number, nests: boolean, nestedDepth: number): InnerFenceLine;
389
+
390
+ /**
391
+ * `$$` pairing — the core's rule for which `$$` delimiters are real math.
392
+ *
393
+ * Ported from `@ai-matrx/kit/delimiter-guard` (`guardMathDelimiters`), which
394
+ * every math-capable renderer runs before remark-math. Its decisions:
395
+ * - `$$` tokens outside code (``` / ~~~ fences, `inline code`) pair in
396
+ * document order, open → close;
397
+ * - a pair whose inside reads as prose or carries markdown structure is NOT
398
+ * math: the renderer neutralizes its opener and the closer is retried as
399
+ * the next opener;
400
+ * - an unpaired `$$` is inert — it renders as literal text.
401
+ * So the tokenizer protects exactly the pairs the renderer shows as math, and
402
+ * a lone `$$` (a stray closer, or an opener that never closed) never locks
403
+ * anything. Linear time: one regex pass per code shape, one sweep.
404
+ */
405
+ /** The guard's `looksLikeMath`, verbatim. */
406
+ declare function looksLikeDisplayMath(inner: string): boolean;
407
+ /** Map of `$$` opener offset → closer offset for every pair the renderer shows as math. */
408
+ declare function pairDisplayMath(text: string): Map<number, number>;
409
+
410
+ export { type BlockIslandType, type CodePointIndex, type DisturbedIsland, FENCE_WHITESPACE, type InlineIslandType, type InnerFenceLine, type IslandMeta, type IslandType, type MapOptions, type MappedPosition, type MappedRange, NESTING_FENCE_LANGUAGES, type ReadXmlTag, type SourceBlock, type SourceBlockKind, type SourceChange, type SourceEdit, type SourceIsland, type SourceSpan, SourceSpliceError, type SourceSpliceErrorCode, type SpliceIntegrity, type SpliceOptions, type SpliceResult, type TokenizeOptions, XmlContainerTracker, blockAt, blockEdit, blockRangeEdit, buildCodePointIndex, classifyInnerFenceLine, fenceNestsInnerFences, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, mapPosition, mapRange, pairDisplayMath, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };
package/dist/source.d.ts CHANGED
@@ -51,12 +51,25 @@ type BlockIslandType =
51
51
  | "anchor"
52
52
  /** `$$ … $$` display math on its own lines. */
53
53
  | "math_block"
54
- /** YAML front matter at the start of the text. */
54
+ /** YAML (`---`) or TOML (`+++`) front matter at the start of the text (meta.format). */
55
55
  | "front_matter"
56
56
  /** A box-drawing tree diagram. */
57
- | "tree";
57
+ | "tree"
58
+ /**
59
+ * A generic-directive container `:::name[label]{attrs}` … `:::` (tabs,
60
+ * columns, details, figures, callouts, TOC — meta.name), a leaf directive
61
+ * `::name` on its own line (meta.leaf), or a MkDocs admonition
62
+ * `!!! type "Title"` / `??? type` with its indented body (meta.syntax "mkdocs").
63
+ */
64
+ | "directive"
65
+ /** A GitHub alert / Obsidian callout: a blockquote opening `> [!TYPE]` (meta.name). */
66
+ | "callout"
67
+ /** A footnote definition `[^id]: …` with its indented continuation lines (meta.id). */
68
+ | "footnote_def";
58
69
  /** Island types that live inside a prose block. */
59
- type InlineIslandType = "variable" | "cite" | "math_inline" | "html_tag" | "xml_tag" | "xml_inline" | "html_comment" | "anchor" | "kind_json" | "media_ref";
70
+ type InlineIslandType = "variable" | "cite" | "math_inline" | "html_tag" | "xml_tag" | "xml_inline" | "html_comment" | "anchor" | "kind_json" | "media_ref"
71
+ /** `[[Page]]`, `[[Page|alias]]` (meta.target) — or `![[Page]]` (meta.embed). */
72
+ | "wikilink";
60
73
  type IslandType = BlockIslandType | InlineIslandType;
61
74
  type IslandMeta = Readonly<Record<string, string | number | boolean>>;
62
75
  interface SourceSpan {
@@ -92,7 +105,16 @@ interface SourceBlock extends SourceSpan {
92
105
  * Cut `text` into blocks whose raw concatenation is exactly `text`.
93
106
  * Never throws; unclosed constructs are islands with `complete: false`.
94
107
  */
95
- declare function tokenizeSource(text: string): SourceBlock[];
108
+ interface TokenizeOptions {
109
+ /**
110
+ * The text is a prefix of a message still arriving. The final line (no
111
+ * terminator yet) can still grow — a bare ``` there may become ```bash — so
112
+ * it closes no fence until its newline arrives (verify-RC-B3 residual R2).
113
+ * Omit for stored text: a complete document's last line is final.
114
+ */
115
+ readonly streaming?: boolean;
116
+ }
117
+ declare function tokenizeSource(text: string, options?: TokenizeOptions): SourceBlock[];
96
118
  /** The exact source the blocks were cut from. */
97
119
  declare function joinSource(blocks: readonly SourceBlock[]): string;
98
120
  /** Every island — block-level and inline — in document order. */
@@ -114,20 +136,30 @@ declare function blockAt(blocks: readonly SourceBlock[], offset: number): Source
114
136
  * uses to carry every live anchor through the save
115
137
  * (STORE-DESIGN §3.19 — the ProseMirror / Google Docs position-mapping
116
138
  * model), and
117
- * - an integrity report: every island outside the edited ranges must still
139
+ * - an integrity guarantee: every island not explicitly replaced must still
118
140
  * be the same island, at its mapped position, in the new text. An edit
119
- * that opens an unclosed fence and swallows a kind below it is caught
120
- * here instead of being saved silently.
141
+ * that opens an unclosed fence and swallows a kind below it is REFUSED.
142
+ *
143
+ * ISLANDS CHANGE ONLY THROUGH `islandEdit`. A prose/range edit must hand back
144
+ * every island inside its range byte-identical and in order (a visual editor
145
+ * holds them as atoms); if one is altered or dropped the save throws
146
+ * `SourceSpliceError("island_edit")` naming the island. A kind editor or code
147
+ * view changes an island with `islandEdit(island, newRaw)`.
121
148
  *
122
149
  * A no-edit save (or edits whose text equals the original block) returns the
123
150
  * original string itself — byte-identical, zero changes.
124
151
  */
125
152
 
126
- /** Replace `[start, end)` (UTF-16, on block boundaries) of the original with `text`. */
153
+ /**
154
+ * Replace `[start, end)` (UTF-16) of the original with `text`. A plain edit
155
+ * starts and ends on block boundaries; an island edit (`island: true`, made by
156
+ * `islandEdit`) names exactly one island's span.
157
+ */
127
158
  interface SourceEdit {
128
159
  readonly start: number;
129
160
  readonly end: number;
130
161
  readonly text: string;
162
+ readonly island?: boolean;
131
163
  }
132
164
  interface SourceChange {
133
165
  /** The block-aligned range the edit named, in the ORIGINAL text. */
@@ -168,7 +200,7 @@ interface SpliceResult {
168
200
  /** Tokenization of the new text. */
169
201
  readonly blocks: readonly SourceBlock[];
170
202
  }
171
- type SourceSpliceErrorCode = "out_of_range" | "misaligned" | "overlap" | "stale_blocks" | "integrity";
203
+ type SourceSpliceErrorCode = "out_of_range" | "misaligned" | "overlap" | "stale_blocks" | "island_edit" | "integrity";
172
204
  declare class SourceSpliceError extends Error {
173
205
  readonly code: SourceSpliceErrorCode;
174
206
  constructor(code: SourceSpliceErrorCode, message: string);
@@ -176,11 +208,21 @@ declare class SourceSpliceError extends Error {
176
208
  interface SpliceOptions {
177
209
  /** The tokenization of `original`, when the caller already holds it. */
178
210
  readonly blocks?: readonly SourceBlock[];
179
- /** Throw `SourceSpliceError("integrity")` instead of reporting a disturbed island. */
211
+ /**
212
+ * Default `true`: a save that disturbs any island it did not explicitly
213
+ * replace throws `SourceSpliceError("integrity")`. `false` is for TOOLING
214
+ * ONLY (diagnostic scripts that want the report instead of the refusal) —
215
+ * no editor or persistence path may pass it.
216
+ */
180
217
  readonly requireIntegrity?: boolean;
181
218
  }
182
219
  /** An edit that replaces one block's raw text. */
183
220
  declare function blockEdit(block: SourceBlock, text: string): SourceEdit;
221
+ /** The one door that changes an island: replace exactly its span with `text`. */
222
+ declare function islandEdit(island: {
223
+ readonly start: number;
224
+ readonly end: number;
225
+ }, text: string): SourceEdit;
184
226
  /** An edit that replaces a contiguous run of blocks `[first, last]`. */
185
227
  declare function blockRangeEdit(first: SourceBlock, last: SourceBlock, text: string): SourceEdit;
186
228
  /**
@@ -252,8 +294,9 @@ declare function toUtf16Offset(text: string, codePoint: number): number;
252
294
  *
253
295
  * Pandoc's rule — the opening `$` is not followed by whitespace, the closing
254
296
  * `$` is not preceded by whitespace and not followed by a digit — plus a math
255
- * signal: a TeX command or operator (`\alpha`, `^`, `_`, `{`, `=`, …), or a
256
- * lone variable (`$x$`, `$n$`, `$x'$`). Content that opens with a digit needs
297
+ * signal: a TeX command or operator (`\alpha`, `^`, `_`, `{`, `=`, …), a
298
+ * lone variable (`$x$`, `$n$`, `$x'$`), or a single-letter math shape
299
+ * (`$f(g(x))$`, `$u v$`, `$f'(x)$` — see `isMathShape`). Content that opens with a digit needs
257
300
  * a real TeX signal, so a price range can never read as math.
258
301
  */
259
302
  declare function isSingleDollarMath(content: string, after: string | undefined): boolean;
@@ -286,7 +329,12 @@ interface ReadXmlTag {
286
329
  value: string;
287
330
  }>;
288
331
  }
289
- declare function readXmlTag(content: string, start: number): ReadXmlTag | null;
332
+ /**
333
+ * `find(needle, from)` must behave like `content.indexOf(needle, from)`; the
334
+ * tokenizer passes a cached occurrence index so a text full of unclosed
335
+ * attribute quotes stays linear. Behaviour is identical either way.
336
+ */
337
+ declare function readXmlTag(content: string, start: number, find?: (needle: string, from: number) => number): ReadXmlTag | null;
290
338
  /**
291
339
  * Balances ONE unknown root tag line by line, ignoring lookalike tags inside
292
340
  * fenced code, inline code spans, comments and CDATA. `consumeLine` returns
@@ -303,4 +351,60 @@ declare class XmlContainerTracker {
303
351
  consumeLine(line: string, startOffset?: number): number | null;
304
352
  }
305
353
 
306
- export { type BlockIslandType, type CodePointIndex, type DisturbedIsland, type InlineIslandType, type IslandMeta, type IslandType, type MapOptions, type MappedPosition, type MappedRange, type ReadXmlTag, type SourceBlock, type SourceBlockKind, type SourceChange, type SourceEdit, type SourceIsland, type SourceSpan, SourceSpliceError, type SourceSpliceErrorCode, type SpliceIntegrity, type SpliceOptions, type SpliceResult, XmlContainerTracker, blockAt, blockEdit, blockRangeEdit, buildCodePointIndex, isSingleDollarMath, joinSource, listIslands, mapPosition, mapRange, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource };
354
+ /** Fence languages whose body is itself a markdown document. */
355
+ declare const NESTING_FENCE_LANGUAGES: ReadonlySet<string>;
356
+ /** True when a fence opened with this info-string language nests inner fences. */
357
+ declare function fenceNestsInnerFences(language: string | undefined | null): boolean;
358
+ type InnerFenceLine =
359
+ /** Not a fence line — ordinary content of the outer fence. */
360
+ "content"
361
+ /** ```lang inside a markdown fence — content, and one level deeper. */
362
+ | "open-nested"
363
+ /** Bare ``` that closes the innermost nested fence — content, one level up. */
364
+ | "close-nested"
365
+ /** Bare ``` that closes the OUTER fence. */
366
+ | "close-outer";
367
+ /**
368
+ * Classify one line inside an open backtick fence, already trimmed with
369
+ * {@link trimFenceLine} (never a language's own `trim()`).
370
+ *
371
+ * @param trimmed the line with surrounding whitespace removed
372
+ * @param openTicks backtick count of the outer fence's opener
373
+ * @param nests whether the outer fence follows the nesting rule
374
+ * @param nestedDepth how many nested fences are open right now
375
+ */
376
+ /**
377
+ * The whitespace a fence line may carry around its backticks and info string:
378
+ * CommonMark's ASCII whitespace — space, tab, LF, CR, form feed, vertical tab.
379
+ * Defined HERE, not by a language's `trim()`: JavaScript's `trim()` also strips
380
+ * U+FEFF, U+00A0 and the Unicode spaces, while Python's `strip()` also strips
381
+ * U+0085 and U+001C–U+001F — which made the two twins disagree on lines such
382
+ * as ```` ```\uFEFF ```` (verify-RC-B3 residual R4). Every caller trims a line
383
+ * with `trimFenceLine` before classifying it; the Python twin mirrors both.
384
+ */
385
+ declare const FENCE_WHITESPACE = " \t\n\r\f\v";
386
+ /** Strip {@link FENCE_WHITESPACE} (and nothing else) from both ends of a line. */
387
+ declare function trimFenceLine(line: string): string;
388
+ declare function classifyInnerFenceLine(trimmed: string, openTicks: number, nests: boolean, nestedDepth: number): InnerFenceLine;
389
+
390
+ /**
391
+ * `$$` pairing — the core's rule for which `$$` delimiters are real math.
392
+ *
393
+ * Ported from `@ai-matrx/kit/delimiter-guard` (`guardMathDelimiters`), which
394
+ * every math-capable renderer runs before remark-math. Its decisions:
395
+ * - `$$` tokens outside code (``` / ~~~ fences, `inline code`) pair in
396
+ * document order, open → close;
397
+ * - a pair whose inside reads as prose or carries markdown structure is NOT
398
+ * math: the renderer neutralizes its opener and the closer is retried as
399
+ * the next opener;
400
+ * - an unpaired `$$` is inert — it renders as literal text.
401
+ * So the tokenizer protects exactly the pairs the renderer shows as math, and
402
+ * a lone `$$` (a stray closer, or an opener that never closed) never locks
403
+ * anything. Linear time: one regex pass per code shape, one sweep.
404
+ */
405
+ /** The guard's `looksLikeMath`, verbatim. */
406
+ declare function looksLikeDisplayMath(inner: string): boolean;
407
+ /** Map of `$$` opener offset → closer offset for every pair the renderer shows as math. */
408
+ declare function pairDisplayMath(text: string): Map<number, number>;
409
+
410
+ export { type BlockIslandType, type CodePointIndex, type DisturbedIsland, FENCE_WHITESPACE, type InlineIslandType, type InnerFenceLine, type IslandMeta, type IslandType, type MapOptions, type MappedPosition, type MappedRange, NESTING_FENCE_LANGUAGES, type ReadXmlTag, type SourceBlock, type SourceBlockKind, type SourceChange, type SourceEdit, type SourceIsland, type SourceSpan, SourceSpliceError, type SourceSpliceErrorCode, type SpliceIntegrity, type SpliceOptions, type SpliceResult, type TokenizeOptions, XmlContainerTracker, blockAt, blockEdit, blockRangeEdit, buildCodePointIndex, classifyInnerFenceLine, fenceNestsInnerFences, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, mapPosition, mapRange, pairDisplayMath, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };