@ai-matrx/content-ir 0.16.2 → 0.17.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
@@ -420,6 +420,30 @@ declare function parseFenceOpener(line: string): {
420
420
  } | null;
421
421
  declare function classifyInnerFenceLine(trimmed: string, openTicks: number, nests: boolean, nestedDepth: number): InnerFenceLine;
422
422
 
423
+ interface CodeRange {
424
+ /** UTF-16 offset of the first character (the fence line start, or the opening backtick run). */
425
+ start: number;
426
+ /** Offset just past the closing fence line's last character / closing backtick run (end of text when unclosed). */
427
+ end: number;
428
+ kind: "fence" | "span";
429
+ }
430
+ /**
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.
444
+ */
445
+ declare function findCodeRanges(text: string): CodeRange[];
446
+
423
447
  /**
424
448
  * `$$...$$`, `$$…$$`, `$$ · $$`: a PLACEHOLDER — prose describing the syntax,
425
449
  * never a formula. The pair is consumed whole as literal text (neither `$$`
@@ -433,7 +457,7 @@ declare function isMathPlaceholder(inner: string): boolean;
433
457
  * pairing with the next paragraph's formula.
434
458
  */
435
459
  declare function looksLikeDisplayMath(inner: string, flow?: boolean): boolean;
436
- /** Map of `$$` opener offset → closer offset for every pair the renderer shows as math. */
460
+
437
461
  /**
438
462
  * STREAMING: the last `$$` token that is still unpaired AND could still pair
439
463
  * with a `$$` not yet arrived — its span so far is short enough, carries no
@@ -442,6 +466,7 @@ declare function looksLikeDisplayMath(inner: string, flow?: boolean): boolean;
442
466
  * streaming tokenizer treats it as provisional. -1 when there is none.
443
467
  */
444
468
  declare function pendingDisplayMathOpener(text: string): number;
469
+ /** Map of `$$` opener offset → closer offset for every pair the renderer shows as math. */
445
470
  declare function pairDisplayMath(text: string): Map<number, number>;
446
471
 
447
- export { type BlockIslandType, CALLOUT_NAMES, type CodePointIndex, 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, isMathPlaceholder, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, mapPosition, mapRange, pairDisplayMath, parseFenceOpener, pendingDisplayMathOpener, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };
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 };
package/dist/source.d.ts CHANGED
@@ -420,6 +420,30 @@ declare function parseFenceOpener(line: string): {
420
420
  } | null;
421
421
  declare function classifyInnerFenceLine(trimmed: string, openTicks: number, nests: boolean, nestedDepth: number): InnerFenceLine;
422
422
 
423
+ interface CodeRange {
424
+ /** UTF-16 offset of the first character (the fence line start, or the opening backtick run). */
425
+ start: number;
426
+ /** Offset just past the closing fence line's last character / closing backtick run (end of text when unclosed). */
427
+ end: number;
428
+ kind: "fence" | "span";
429
+ }
430
+ /**
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.
444
+ */
445
+ declare function findCodeRanges(text: string): CodeRange[];
446
+
423
447
  /**
424
448
  * `$$...$$`, `$$…$$`, `$$ · $$`: a PLACEHOLDER — prose describing the syntax,
425
449
  * never a formula. The pair is consumed whole as literal text (neither `$$`
@@ -433,7 +457,7 @@ declare function isMathPlaceholder(inner: string): boolean;
433
457
  * pairing with the next paragraph's formula.
434
458
  */
435
459
  declare function looksLikeDisplayMath(inner: string, flow?: boolean): boolean;
436
- /** Map of `$$` opener offset → closer offset for every pair the renderer shows as math. */
460
+
437
461
  /**
438
462
  * STREAMING: the last `$$` token that is still unpaired AND could still pair
439
463
  * with a `$$` not yet arrived — its span so far is short enough, carries no
@@ -442,6 +466,7 @@ declare function looksLikeDisplayMath(inner: string, flow?: boolean): boolean;
442
466
  * streaming tokenizer treats it as provisional. -1 when there is none.
443
467
  */
444
468
  declare function pendingDisplayMathOpener(text: string): number;
469
+ /** Map of `$$` opener offset → closer offset for every pair the renderer shows as math. */
445
470
  declare function pairDisplayMath(text: string): Map<number, number>;
446
471
 
447
- export { type BlockIslandType, CALLOUT_NAMES, type CodePointIndex, 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, isMathPlaceholder, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, mapPosition, mapRange, pairDisplayMath, parseFenceOpener, pendingDisplayMathOpener, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };
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 };
package/dist/source.js CHANGED
@@ -313,32 +313,8 @@ function singleDollarMathEnd(text, open, limit = text.length) {
313
313
  return isSingleDollarMath(content, text[close + 1]) ? close + 1 : -1;
314
314
  }
315
315
 
316
- // source/math-pairs.ts
317
- var MAX_MATH_SPAN = 600;
318
- var STRUCTURAL_MARKDOWN = /\]\(|https?:\/\/|\*\*|(?:^|\n)[ \t]{0,3}#{1,6}[ \t]|(?:^|\n)[ \t]*[-*+][ \t]+|(?:^|\n)[ \t]*\d+[.)][ \t]/;
319
- var LATEX_COMMAND = /\\[a-zA-Z]/;
320
- var PROSE_WORD = /[A-Za-z]{3,}/g;
321
- var PROSE_WORD_LIMIT = 6;
322
- function isMathPlaceholder(inner) {
323
- return /^[\s.…·⋯_-]*$/.test(inner) && /[.…·⋯]/.test(inner);
324
- }
325
- function opensFlowBlock(text, open) {
326
- for (let k = open - 1; k >= 0 && text[k] !== "\n"; k--) if (text[k] !== " " && text[k] !== " ") return false;
327
- for (let k = open + 2; k < text.length && text[k] !== "\n"; k++) if (text[k] !== " " && text[k] !== " " && text[k] !== "\r") return false;
328
- return true;
329
- }
330
- function looksLikeDisplayMath(inner, flow = false) {
331
- const s = inner.trim();
332
- if (!s) return false;
333
- if (STRUCTURAL_MARKDOWN.test(s)) return false;
334
- if (s.length > MAX_MATH_SPAN) return false;
335
- if (!flow && /\n[ \t]*\n/.test(inner)) return false;
336
- if (LATEX_COMMAND.test(s)) {
337
- return (s.match(PROSE_WORD) ?? []).length < PROSE_WORD_LIMIT * 3;
338
- }
339
- return (s.match(PROSE_WORD) ?? []).length < PROSE_WORD_LIMIT;
340
- }
341
- function codeRanges(text) {
316
+ // source/code-ranges.ts
317
+ function findCodeRanges(text) {
342
318
  const ranges = [];
343
319
  const n = text.length;
344
320
  let fence = null;
@@ -370,7 +346,7 @@ function codeRanges(text) {
370
346
  }
371
347
  const [s0] = runs[r];
372
348
  const [s1, l1] = runs[j];
373
- ranges.push([s0, s1 + l1]);
349
+ ranges.push({ start: s0, end: s1 + l1, kind: "span" });
374
350
  r = j + 1;
375
351
  }
376
352
  };
@@ -396,7 +372,7 @@ function codeRanges(text) {
396
372
  closes = indent <= 3 && t >= fence.len && trimFenceLine(trimmed.slice(t)) === "";
397
373
  }
398
374
  if (closes) {
399
- ranges.push([fence.start, lineEnd]);
375
+ ranges.push({ start: fence.start, end: lineEnd, kind: "fence" });
400
376
  fence = null;
401
377
  }
402
378
  } else {
@@ -416,9 +392,106 @@ function codeRanges(text) {
416
392
  if (nl === -1) break;
417
393
  pos = nl + 1;
418
394
  }
419
- if (fence) ranges.push([fence.start, n]);
395
+ if (fence) ranges.push({ start: fence.start, end: n, kind: "fence" });
420
396
  else if (para !== -1) spans(para, n);
421
- return ranges.sort((a, b) => a[0] - b[0]);
397
+ return ranges.sort((a, b) => a.start - b.start);
398
+ }
399
+ function pendingCodeSpanStart(text) {
400
+ const n = text.length;
401
+ if (n === 0 || /\n[ \t]*\n[ \t]*$/.test(text)) return -1;
402
+ let fence = null;
403
+ let para = -1;
404
+ let pos = 0;
405
+ while (pos <= n) {
406
+ const nl = text.indexOf("\n", pos);
407
+ const lineEnd = nl === -1 ? n : nl;
408
+ const line = text.slice(pos, lineEnd);
409
+ let indent = 0;
410
+ while (indent < line.length && line[indent] === " ") indent++;
411
+ const body = line.slice(indent);
412
+ if (fence) {
413
+ const trimmed = trimFenceLine(line);
414
+ let closes = false;
415
+ if (fence.char === "`") {
416
+ const kind = classifyInnerFenceLine(trimmed, fence.len, fence.nests, fence.depth);
417
+ if (kind === "open-nested") fence.depth++;
418
+ else if (kind === "close-nested") fence.depth--;
419
+ else if (kind === "close-outer") closes = indent <= 3;
420
+ } else {
421
+ let t = 0;
422
+ while (t < trimmed.length && trimmed[t] === "~") t++;
423
+ closes = indent <= 3 && t >= fence.len && trimFenceLine(trimmed.slice(t)) === "";
424
+ }
425
+ if (closes) fence = null;
426
+ } else {
427
+ const opener = indent <= 3 ? /^(`{3,}|~{3,})(.*)$/.exec(body) : null;
428
+ const info = opener ? opener[2] : "";
429
+ if (opener && !(opener[1][0] === "`" && info.includes("`"))) {
430
+ para = -1;
431
+ const char = opener[1][0];
432
+ const parsed = char === "`" ? parseFenceOpener(line) : null;
433
+ fence = { char, len: opener[1].length, nests: fenceNestsInnerFences(parsed?.lang), depth: 0 };
434
+ } else if (body.trim() === "") {
435
+ if (!(nl === -1 && line === "")) para = -1;
436
+ } else if (para === -1) para = pos;
437
+ }
438
+ if (nl === -1) break;
439
+ pos = nl + 1;
440
+ }
441
+ if (fence || para === -1) return -1;
442
+ const runs = [];
443
+ for (let k = para; k < n; ) {
444
+ if (text.charCodeAt(k) !== 96) {
445
+ k++;
446
+ continue;
447
+ }
448
+ let len = 1;
449
+ while (k + len < n && text.charCodeAt(k + len) === 96) len++;
450
+ runs.push([k, len]);
451
+ k += len;
452
+ }
453
+ const growing = (r) => {
454
+ const [start, len] = runs[r];
455
+ return start + len === n;
456
+ };
457
+ for (let r = 0; r < runs.length; ) {
458
+ if (growing(r)) return runs[r][0];
459
+ const len = runs[r][1];
460
+ let j = r + 1;
461
+ while (j < runs.length && (runs[j][1] !== len || growing(j))) j++;
462
+ if (j >= runs.length) return runs[r][0];
463
+ r = j + 1;
464
+ }
465
+ return -1;
466
+ }
467
+
468
+ // source/math-pairs.ts
469
+ var MAX_MATH_SPAN = 600;
470
+ var STRUCTURAL_MARKDOWN = /\]\(|https?:\/\/|\*\*|(?:^|\n)[ \t]{0,3}#{1,6}[ \t]|(?:^|\n)[ \t]*[-*+][ \t]+|(?:^|\n)[ \t]*\d+[.)][ \t]/;
471
+ var LATEX_COMMAND = /\\[a-zA-Z]/;
472
+ var PROSE_WORD = /[A-Za-z]{3,}/g;
473
+ var PROSE_WORD_LIMIT = 6;
474
+ function isMathPlaceholder(inner) {
475
+ return /^[\s.…·⋯_-]*$/.test(inner) && /[.…·⋯]/.test(inner);
476
+ }
477
+ function opensFlowBlock(text, open) {
478
+ for (let k = open - 1; k >= 0 && text[k] !== "\n"; k--) if (text[k] !== " " && text[k] !== " ") return false;
479
+ for (let k = open + 2; k < text.length && text[k] !== "\n"; k++) if (text[k] !== " " && text[k] !== " " && text[k] !== "\r") return false;
480
+ return true;
481
+ }
482
+ function looksLikeDisplayMath(inner, flow = false) {
483
+ const s = inner.trim();
484
+ if (!s) return false;
485
+ if (STRUCTURAL_MARKDOWN.test(s)) return false;
486
+ if (s.length > MAX_MATH_SPAN) return false;
487
+ if (!flow && /\n[ \t]*\n/.test(inner)) return false;
488
+ if (LATEX_COMMAND.test(s)) {
489
+ return (s.match(PROSE_WORD) ?? []).length < PROSE_WORD_LIMIT * 3;
490
+ }
491
+ return (s.match(PROSE_WORD) ?? []).length < PROSE_WORD_LIMIT;
492
+ }
493
+ function codeRanges(text) {
494
+ return findCodeRanges(text).map((r) => [r.start, r.end]);
422
495
  }
423
496
  function pendingDisplayMathOpener(text) {
424
497
  if (!text.includes("$$")) return -1;
@@ -830,6 +903,14 @@ var Tokenizer = class {
830
903
  this.provisionalFrom = streaming ? pendingDisplayMathOpener(text) : -1;
831
904
  if (this.provisionalFrom === -1) this.provisionalFrom = Number.POSITIVE_INFINITY;
832
905
  if (streaming && text.includes("$$")) {
906
+ const span = pendingCodeSpanStart(text);
907
+ if (span !== -1) {
908
+ const firstToken = text.indexOf("$$", span);
909
+ if (firstToken !== -1) this.provisionalFrom = Math.min(this.provisionalFrom, firstToken);
910
+ for (const [open, close] of this.mathPairs) {
911
+ if (close >= span) this.provisionalFrom = Math.min(this.provisionalFrom, open);
912
+ }
913
+ }
833
914
  for (const pad of ["`", "``", "```", "~~~"]) {
834
915
  const alt = pairDisplayMath(text + pad);
835
916
  for (const [open, close] of this.mathPairs) {
@@ -1185,8 +1266,8 @@ var Tokenizer = class {
1185
1266
  last = k;
1186
1267
  continue;
1187
1268
  }
1188
- if (FOOTNOTE_DEF.test(line.trimStart()) || this.detectBlock(this.lineStarts[k], k, false)) break;
1189
1269
  if (this.isOpenTail(k)) return this.heldFootnote(p, open[1]);
1270
+ if (FOOTNOTE_DEF.test(line.trimStart()) || this.detectBlock(this.lineStarts[k], k, false)) break;
1190
1271
  last = k;
1191
1272
  }
1192
1273
  const end = this.contentEnds[last];
@@ -2173,6 +2254,6 @@ function mapRange(changes, start, end, unit = "utf16") {
2173
2254
  return { start: newStart, end: newEnd, touched, collapsed: newEnd === newStart && end > start };
2174
2255
  }
2175
2256
 
2176
- export { CALLOUT_NAMES, FENCE_OPENER_WHITESPACE, FENCE_WHITESPACE, NESTING_FENCE_LANGUAGES, SourceSpliceError, XmlContainerTracker, blockAt, blockEdit, blockRangeEdit, buildCodePointIndex, classifyInnerFenceLine, fenceNestsInnerFences, isMathPlaceholder, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, mapPosition, mapRange, pairDisplayMath, parseFenceOpener, pendingDisplayMathOpener, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };
2257
+ export { CALLOUT_NAMES, FENCE_OPENER_WHITESPACE, FENCE_WHITESPACE, NESTING_FENCE_LANGUAGES, SourceSpliceError, 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 };
2177
2258
  //# sourceMappingURL=source.js.map
2178
2259
  //# sourceMappingURL=source.js.map