@ai-matrx/content-ir 0.17.0 → 0.18.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
@@ -300,21 +300,48 @@ declare function toCodePointOffset(text: string, utf16: number): number;
300
300
  declare function toUtf16Offset(text: string, codePoint: number): number;
301
301
 
302
302
  /**
303
- * THE single-dollar math rule — the one predicate that decides whether
304
- * `$…$` is inline math or currency.
303
+ * THE single-dollar math rule — the one predicate that decides whether a
304
+ * CLOSED `$…$` is inline math or currency, on screen, in every export and in
305
+ * the editor's islands (the renderer's normalizer, the source tokenizer and
306
+ * print all ask it).
305
307
  *
306
- * Moved here from matrx-frontend `components/markdown-core/math-normalizer.ts`
307
- * (2026-09-23) so the renderer's normalizer and the source tokenizer can never
308
- * disagree about which bytes are math: the normalizer imports this function.
309
- *
310
- * Pandoc's rule — the opening `$` is not followed by whitespace, the closing
311
- * `$` is not preceded by whitespace and not followed by a digit — plus a math
312
- * signal: a TeX command or operator (`\alpha`, `^`, `_`, `{`, `=`, …), a
313
- * lone variable (`$x$`, `$n$`, `$x'$`), or a single-letter math shape
314
- * (`$f(g(x))$`, `$u v$`, `$f'(x)$` — see `isMathShape`). Content that opens with a digit needs
315
- * a real TeX signal, so a price range can never read as math.
308
+ * Pandoc's `tex_math_dollars` delimiters (what remark-math approximates, and
309
+ * how ChatGPT and Claude render): the opening `$` is followed by a
310
+ * non-space, the closing `$` is preceded by a non-space and not followed by a
311
+ * digit — so `$5 and $10`, `$5-$10`, `$5/$10` stay currency while `$FC$`,
312
+ * `$AB$`, `$5$` and `$(0, 0)$` are math. On top of that, content that reads as
313
+ * something other than a formula is refused — each guard is a false positive
314
+ * measured in stored answers (matrx-frontend
315
+ * `scripts/measure-single-dollar-rule.ts`, 2026-09-25: over 85k assistant
316
+ * messages and 4k notes the widening adds 128 spans, every one a formula
317
+ * (`$FC$`, `$(0, 0)$`, `$3x + 6 = 15$`), and drops 22 the old rule drew as
318
+ * math that were code, template literals, a printf or broken TeX):
319
+ * - an unescaped `%` — TeX's comment character, and a percentage
320
+ * (`$\ge$20% owners**…**$`, a printf `%1$s`);
321
+ * - a closing bracket or `/` first, or an opening bracket last
322
+ * (`[$X] plus [$Y]`, `($/SF/Yr) | High-Cost Market ($`, a regex
323
+ * `/…/, '').replace(/…$`), or a straight quote at either end (`["$", "$"]`
324
+ * in data);
325
+ * - `:` `;` `,` `/` last — a separator between two `$` words
326
+ * (`$HOME/.local/bin:$PATH`, `$AAPL/$TSLA`);
327
+ * - a number glued to a following letter (`$10$N9qo…`, a bcrypt cost);
328
+ * - a placeholder (`$...$`);
329
+ * - prose, unless a TeX command or operator says otherwise: two plain
330
+ * words (`$Tipping (fee)$`), a contraction (`$I'm$`, never `$X'Y$`), an
331
+ * abbreviation (`$e.g. (x)$`).
316
332
  */
317
333
  declare function isSingleDollarMath(content: string, after: string | undefined): boolean;
334
+ /**
335
+ * Whether an UNCLOSED `$…` already reads as a formula — for a stream that
336
+ * must decide before the closing `$` arrives (matrx-frontend `stream-heal`
337
+ * holds such a tail back instead of printing raw TeX). Stricter than
338
+ * {@link isSingleDollarMath} on purpose: with no closer there are no Pandoc
339
+ * delimiter facts yet, so it needs a math SIGNAL — a TeX command or operator
340
+ * (`\alpha`, `^`, `_`, `{`, `=`, …), a lone variable (`x`, `x'`), or a
341
+ * single-letter math shape (`f(g(x))`, `u v`). Content that opens with a digit
342
+ * needs a real TeX command, so `$35 per stop` keeps showing while it streams.
343
+ */
344
+ declare function looksLikeOpenInlineMath(partial: string): boolean;
318
345
  /**
319
346
  * Where a single-dollar math span opened at `open` (a lone `$`) closes, or -1.
320
347
  * Same scan the normalizer uses: same line, backslash-escapes skipped, the
@@ -423,24 +450,14 @@ declare function classifyInnerFenceLine(trimmed: string, openTicks: number, nest
423
450
  interface CodeRange {
424
451
  /** UTF-16 offset of the first character (the fence line start, or the opening backtick run). */
425
452
  start: number;
426
- /** Offset just past the closing fence line's last character / closing backtick run (end of text when unclosed). */
453
+ /** Offset just past the closing fence line's content / closing backtick run (the fence's last line when unclosed). */
427
454
  end: number;
428
455
  kind: "fence" | "span";
429
456
  }
430
457
  /**
431
- * Where code is, by CommonMark — THE ONE code-range rule for every package.
432
- * Math pairing (`pairDisplayMath`), the tokenizer's math islands, print's math
433
- * lifting and kit's delimiter guard all ask this function; a second copy of
434
- * code detection anywhere in `apps/shared` fails
435
- * `__tests__/one-code-range-rule.test.ts`.
436
- * - A fence opens only at the START of a line (≤ 3 spaces of indent): a
437
- * mid-sentence "```python" is text, not a fence that swallows everything
438
- * after it (verify-RC-B9: one inline ``` turned math off for the rest of
439
- * the answer). Closing follows THE ONE nested-fence rule
440
- * (`classifyInnerFenceLine`); an unclosed fence runs to the end.
441
- * - An inline code span closes only at a backtick run of the SAME length in
442
- * the same paragraph; an unmatched run is literal text.
443
- * Linear: one pass over lines, one over each paragraph's backtick runs.
458
+ * Every code range in the text — fences (by the renderer's rule above) and
459
+ * inline code spans — sorted by start. Linear: one pass over lines, one over
460
+ * each paragraph's backtick runs.
444
461
  */
445
462
  declare function findCodeRanges(text: string): CodeRange[];
446
463
 
@@ -469,4 +486,4 @@ declare function pendingDisplayMathOpener(text: string): number;
469
486
  /** Map of `$$` opener offset → closer offset for every pair the renderer shows as math. */
470
487
  declare function pairDisplayMath(text: string): Map<number, number>;
471
488
 
472
- export { type BlockIslandType, CALLOUT_NAMES, type CodePointIndex, type CodeRange, type DisturbedIsland, FENCE_OPENER_WHITESPACE, 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, findCodeRanges, isMathPlaceholder, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, mapPosition, mapRange, pairDisplayMath, parseFenceOpener, pendingDisplayMathOpener, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };
489
+ export { type BlockIslandType, CALLOUT_NAMES, type CodePointIndex, type CodeRange, type DisturbedIsland, FENCE_OPENER_WHITESPACE, 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, findCodeRanges, isMathPlaceholder, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, looksLikeOpenInlineMath, mapPosition, mapRange, pairDisplayMath, parseFenceOpener, pendingDisplayMathOpener, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };
package/dist/source.d.ts CHANGED
@@ -300,21 +300,48 @@ declare function toCodePointOffset(text: string, utf16: number): number;
300
300
  declare function toUtf16Offset(text: string, codePoint: number): number;
301
301
 
302
302
  /**
303
- * THE single-dollar math rule — the one predicate that decides whether
304
- * `$…$` is inline math or currency.
303
+ * THE single-dollar math rule — the one predicate that decides whether a
304
+ * CLOSED `$…$` is inline math or currency, on screen, in every export and in
305
+ * the editor's islands (the renderer's normalizer, the source tokenizer and
306
+ * print all ask it).
305
307
  *
306
- * Moved here from matrx-frontend `components/markdown-core/math-normalizer.ts`
307
- * (2026-09-23) so the renderer's normalizer and the source tokenizer can never
308
- * disagree about which bytes are math: the normalizer imports this function.
309
- *
310
- * Pandoc's rule — the opening `$` is not followed by whitespace, the closing
311
- * `$` is not preceded by whitespace and not followed by a digit — plus a math
312
- * signal: a TeX command or operator (`\alpha`, `^`, `_`, `{`, `=`, …), a
313
- * lone variable (`$x$`, `$n$`, `$x'$`), or a single-letter math shape
314
- * (`$f(g(x))$`, `$u v$`, `$f'(x)$` — see `isMathShape`). Content that opens with a digit needs
315
- * a real TeX signal, so a price range can never read as math.
308
+ * Pandoc's `tex_math_dollars` delimiters (what remark-math approximates, and
309
+ * how ChatGPT and Claude render): the opening `$` is followed by a
310
+ * non-space, the closing `$` is preceded by a non-space and not followed by a
311
+ * digit — so `$5 and $10`, `$5-$10`, `$5/$10` stay currency while `$FC$`,
312
+ * `$AB$`, `$5$` and `$(0, 0)$` are math. On top of that, content that reads as
313
+ * something other than a formula is refused — each guard is a false positive
314
+ * measured in stored answers (matrx-frontend
315
+ * `scripts/measure-single-dollar-rule.ts`, 2026-09-25: over 85k assistant
316
+ * messages and 4k notes the widening adds 128 spans, every one a formula
317
+ * (`$FC$`, `$(0, 0)$`, `$3x + 6 = 15$`), and drops 22 the old rule drew as
318
+ * math that were code, template literals, a printf or broken TeX):
319
+ * - an unescaped `%` — TeX's comment character, and a percentage
320
+ * (`$\ge$20% owners**…**$`, a printf `%1$s`);
321
+ * - a closing bracket or `/` first, or an opening bracket last
322
+ * (`[$X] plus [$Y]`, `($/SF/Yr) | High-Cost Market ($`, a regex
323
+ * `/…/, '').replace(/…$`), or a straight quote at either end (`["$", "$"]`
324
+ * in data);
325
+ * - `:` `;` `,` `/` last — a separator between two `$` words
326
+ * (`$HOME/.local/bin:$PATH`, `$AAPL/$TSLA`);
327
+ * - a number glued to a following letter (`$10$N9qo…`, a bcrypt cost);
328
+ * - a placeholder (`$...$`);
329
+ * - prose, unless a TeX command or operator says otherwise: two plain
330
+ * words (`$Tipping (fee)$`), a contraction (`$I'm$`, never `$X'Y$`), an
331
+ * abbreviation (`$e.g. (x)$`).
316
332
  */
317
333
  declare function isSingleDollarMath(content: string, after: string | undefined): boolean;
334
+ /**
335
+ * Whether an UNCLOSED `$…` already reads as a formula — for a stream that
336
+ * must decide before the closing `$` arrives (matrx-frontend `stream-heal`
337
+ * holds such a tail back instead of printing raw TeX). Stricter than
338
+ * {@link isSingleDollarMath} on purpose: with no closer there are no Pandoc
339
+ * delimiter facts yet, so it needs a math SIGNAL — a TeX command or operator
340
+ * (`\alpha`, `^`, `_`, `{`, `=`, …), a lone variable (`x`, `x'`), or a
341
+ * single-letter math shape (`f(g(x))`, `u v`). Content that opens with a digit
342
+ * needs a real TeX command, so `$35 per stop` keeps showing while it streams.
343
+ */
344
+ declare function looksLikeOpenInlineMath(partial: string): boolean;
318
345
  /**
319
346
  * Where a single-dollar math span opened at `open` (a lone `$`) closes, or -1.
320
347
  * Same scan the normalizer uses: same line, backslash-escapes skipped, the
@@ -423,24 +450,14 @@ declare function classifyInnerFenceLine(trimmed: string, openTicks: number, nest
423
450
  interface CodeRange {
424
451
  /** UTF-16 offset of the first character (the fence line start, or the opening backtick run). */
425
452
  start: number;
426
- /** Offset just past the closing fence line's last character / closing backtick run (end of text when unclosed). */
453
+ /** Offset just past the closing fence line's content / closing backtick run (the fence's last line when unclosed). */
427
454
  end: number;
428
455
  kind: "fence" | "span";
429
456
  }
430
457
  /**
431
- * Where code is, by CommonMark — THE ONE code-range rule for every package.
432
- * Math pairing (`pairDisplayMath`), the tokenizer's math islands, print's math
433
- * lifting and kit's delimiter guard all ask this function; a second copy of
434
- * code detection anywhere in `apps/shared` fails
435
- * `__tests__/one-code-range-rule.test.ts`.
436
- * - A fence opens only at the START of a line (≤ 3 spaces of indent): a
437
- * mid-sentence "```python" is text, not a fence that swallows everything
438
- * after it (verify-RC-B9: one inline ``` turned math off for the rest of
439
- * the answer). Closing follows THE ONE nested-fence rule
440
- * (`classifyInnerFenceLine`); an unclosed fence runs to the end.
441
- * - An inline code span closes only at a backtick run of the SAME length in
442
- * the same paragraph; an unmatched run is literal text.
443
- * Linear: one pass over lines, one over each paragraph's backtick runs.
458
+ * Every code range in the text — fences (by the renderer's rule above) and
459
+ * inline code spans — sorted by start. Linear: one pass over lines, one over
460
+ * each paragraph's backtick runs.
444
461
  */
445
462
  declare function findCodeRanges(text: string): CodeRange[];
446
463
 
@@ -469,4 +486,4 @@ declare function pendingDisplayMathOpener(text: string): number;
469
486
  /** Map of `$$` opener offset → closer offset for every pair the renderer shows as math. */
470
487
  declare function pairDisplayMath(text: string): Map<number, number>;
471
488
 
472
- export { type BlockIslandType, CALLOUT_NAMES, type CodePointIndex, type CodeRange, type DisturbedIsland, FENCE_OPENER_WHITESPACE, 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, findCodeRanges, isMathPlaceholder, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, mapPosition, mapRange, pairDisplayMath, parseFenceOpener, pendingDisplayMathOpener, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };
489
+ export { type BlockIslandType, CALLOUT_NAMES, type CodePointIndex, type CodeRange, type DisturbedIsland, FENCE_OPENER_WHITESPACE, 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, findCodeRanges, isMathPlaceholder, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, looksLikeOpenInlineMath, mapPosition, mapRange, pairDisplayMath, parseFenceOpener, pendingDisplayMathOpener, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };