@ai-matrx/content-ir 0.18.0 → 0.18.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,49 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.18.2 — 2026-09-25
4
+
5
+ **Carries: RC-B10 only.** Three helpers on THE one code-range rule, so every
6
+ consumer strips or reads code in one line instead of a private regex:
7
+ `mapCodeRanges(text, fn)` (rewrite each fence/span, prose kept byte for
8
+ byte), `codeSpanText(raw)` (CommonMark span text: runs off, one padding space
9
+ each side), `fenceParts(raw)` (opener, body, closed — list-marker line,
10
+ blockquote and the renderer's line-end closer handled).
11
+ - Consumer action: none — refresh to latest.
12
+
13
+ ## 0.18.1 — 2026-09-25
14
+
15
+ **Carries: RC-B10 only** (the one code-range rule). No RC-B3 work is pending
16
+ after the 0.18.0 tag; 0.18.0 itself (RC-B3's single-dollar release) ALSO
17
+ carried RC-B10 stages a and b, swept onto main before that tag — recorded
18
+ here because its entry does not mention them.
19
+
20
+ **`/source`: THE one code-range rule is the renderer's rule** (RC-B10 ruling,
21
+ REGISTER rulings ledger). `source/code-ranges.ts` owns it: a backtick fence
22
+ opens where a line's trimmed text starts with ``` at ANY indent (list items at
23
+ any depth), after stripping blockquote `>` prefixes; a tilde fence opens at
24
+ ≤ 3 spaces relative to its container (list content column); a backtick fence
25
+ closes by the nested-fence rule (with the strict retry) or the renderer's
26
+ line-end closer (`code````), and inside ```json a backtick run in a JSON
27
+ string is text; a blockquoted fence ends with its quote. Strict CommonMark's
28
+ "4+ spaces is not a fence" is rejected on purpose — users see what the
29
+ renderer's splitter draws. Phases follow the renderer: the splitter's
30
+ any-indent backtick fences first, then remark inside each prose segment
31
+ (blockquote, list-marker-line and tilde fences, code spans).
32
+ - New exports: `fenceOpenerOf`, `closeFence`, `FenceReader` (the streaming
33
+ closer), `BacktickRuns` (the code-span pairing table), `fenceLineKinds`
34
+ (per-line prose/open/body/close), types `FenceOpener`, `FenceLines`,
35
+ `FenceEnd`, `FenceLineKind`.
36
+ - The tokenizer (0.18.0) and `XmlContainerTracker` (this release) read fences
37
+ only through these; their private copies are deleted.
38
+ - Corpus: 136,662/136,662 byte-identical; every tokenizer backtick-fence
39
+ island (17,518) is exactly one `findCodeRanges` fence (the 0.17 rule missed
40
+ 92); display-math pairing unchanged on every row. Renderer blocks ⊆
41
+ tokenizer islands (matrx-frontend `source-covers-renderer`, container
42
+ fences added). Vectors: `__tests__/fixtures/code-range-vectors.json` (25,
43
+ incl. stored-row shapes with every word replaced) and the Python twin's
44
+ `fence-nesting-vectors.json` (container + stored-row documents).
45
+ - Consumer action: none — refresh to latest.
46
+
3
47
  ## 0.18.0 — 2026-09-25
4
48
 
5
49
  **`/source` `isSingleDollarMath`: `$FC$` is math.** (RC-B9 verifier, RC-B3.)
package/dist/index.cjs CHANGED
@@ -5367,7 +5367,7 @@ function scan(text) {
5367
5367
  }
5368
5368
  const count = starts.length;
5369
5369
  const raw = (k) => text.slice(starts[k], ends[k]);
5370
- const out = { ranges: [], paragraphs: [], endsInFence: false, pendingPara: -1 };
5370
+ const out = { ranges: [], fences: [], paragraphs: [], endsInFence: false, pendingPara: -1 };
5371
5371
  const rawLines = { count, line: raw };
5372
5372
  let segment = 0;
5373
5373
  for (let k = 0; k < count; k++) {
@@ -5376,6 +5376,7 @@ function scan(text) {
5376
5376
  prose(text, starts, ends, raw, segment, k, out);
5377
5377
  const end = closeFence(rawLines, k, opener);
5378
5378
  out.ranges.push({ start: starts[k], end: ends[end.line], kind: "fence" });
5379
+ out.fences.push([k, end.line, end.closed]);
5379
5380
  out.pendingPara = -1;
5380
5381
  if (!end.closed && end.line === count - 1) out.endsInFence = true;
5381
5382
  k = end.line;
@@ -5441,6 +5442,7 @@ function prose(text, starts, ends, raw, from, to, out) {
5441
5442
  };
5442
5443
  const end = closeFence(src, k, opener);
5443
5444
  out.ranges.push({ start: starts[k], end: ends[end.line], kind: "fence" });
5445
+ out.fences.push([k, end.line, end.closed]);
5444
5446
  if (!end.closed && end.line === starts.length - 1) out.endsInFence = true;
5445
5447
  k = end.line;
5446
5448
  }
@@ -5504,6 +5506,45 @@ function findCodeRanges(text) {
5504
5506
  for (const [from, to] of s.paragraphs) codeSpans(text, from, to, ranges);
5505
5507
  return ranges.sort((a, b) => a.start - b.start);
5506
5508
  }
5509
+ function mapCodeRanges(text, fn) {
5510
+ let out = "";
5511
+ let at = 0;
5512
+ for (const r of findCodeRanges(text)) {
5513
+ if (r.start < at) continue;
5514
+ out += text.slice(at, r.start) + fn(r, text.slice(r.start, r.end));
5515
+ at = r.end;
5516
+ }
5517
+ return out + text.slice(at);
5518
+ }
5519
+ function codeSpanText(raw) {
5520
+ const ticks = backtickRunLength(raw, 0);
5521
+ const inner = raw.slice(ticks, raw.length - ticks);
5522
+ return inner.length >= 2 && inner.startsWith(" ") && inner.endsWith(" ") && inner.trim() !== "" ? inner.slice(1, -1) : inner;
5523
+ }
5524
+ function fenceParts(raw) {
5525
+ const lines = raw.split("\n").map((l) => l.endsWith("\r") ? l.slice(0, -1) : l);
5526
+ const { offset } = quotePrefix(lines[0] ?? "");
5527
+ const opener = fenceOpenerOf((lines[0] ?? "").slice(offset).replace(/^ *(?:[-*+]|\d{1,9}[.)])(?= |\t|$) ?/, ""));
5528
+ if (!opener) return null;
5529
+ const rest = lines.slice(1);
5530
+ const closed = rest.length > 0 && new FenceReader(opener, { nesting: false }).feed(rest[rest.length - 1]);
5531
+ if (!closed) return { opener, body: rest.join("\n"), closed };
5532
+ const last = rest[rest.length - 1];
5533
+ const before = trimFenceLine(last).startsWith("```") ? "" : last.slice(0, last.indexOf("```"));
5534
+ return { opener, body: [...rest.slice(0, -1), ...before.trim() ? [before] : []].join("\n"), closed };
5535
+ }
5536
+ function fenceLineKinds(text) {
5537
+ const s = scan(text);
5538
+ let count = 1;
5539
+ for (let i = text.indexOf("\n"); i !== -1; i = text.indexOf("\n", i + 1)) count++;
5540
+ const kinds = new Array(count).fill("prose");
5541
+ for (const [open, last, closed] of s.fences) {
5542
+ kinds[open] = "open";
5543
+ for (let k = open + 1; k <= last; k++) kinds[k] = "body";
5544
+ if (closed && last > open) kinds[last] = "close";
5545
+ }
5546
+ return kinds;
5547
+ }
5507
5548
  function pendingCodeSpanStart(text) {
5508
5549
  const n = text.length;
5509
5550
  if (n === 0 || /\n[ \t]*\n[ \t]*$/.test(text)) return -1;
@@ -5802,25 +5843,20 @@ var XmlContainerTracker = class {
5802
5843
  inComment = false;
5803
5844
  inCdata = false;
5804
5845
  inlineTicks = 0;
5805
- fenceMarker = null;
5846
+ /** The open fence, read by THE one closer (source/code-ranges.ts). */
5847
+ fence = null;
5806
5848
  consumeLine(line, startOffset = 0) {
5807
- const fence = /^[ \t]*(`{3,}|~{3,})(.*)$/.exec(line);
5808
- if (!this.inComment && !this.inCdata && this.inlineTicks === 0 && fence) {
5809
- const marker = fence[1];
5810
- const char = marker[0];
5811
- const suffix = fence[2];
5812
- if (marker.length >= 3) {
5813
- if (!this.fenceMarker) {
5814
- this.fenceMarker = { char, ticks: marker.length };
5815
- return null;
5816
- }
5817
- if (char === this.fenceMarker.char && marker.length >= this.fenceMarker.ticks && suffix.trim() === "") {
5818
- this.fenceMarker = null;
5819
- }
5849
+ if (this.fence) {
5850
+ if (this.fence.feed(line)) this.fence = null;
5851
+ return null;
5852
+ }
5853
+ if (!this.inComment && !this.inCdata && this.inlineTicks === 0) {
5854
+ const opener = fenceOpenerOf(line);
5855
+ if (opener) {
5856
+ this.fence = new FenceReader(opener);
5820
5857
  return null;
5821
5858
  }
5822
5859
  }
5823
- if (this.fenceMarker) return null;
5824
5860
  for (let i = startOffset; i < line.length; i++) {
5825
5861
  if (this.inlineTicks > 0) {
5826
5862
  if (line[i] === "`") {
@@ -7311,6 +7347,7 @@ function mapRange(changes, start, end, unit = "utf16") {
7311
7347
  }
7312
7348
 
7313
7349
  exports.ACTION_BY_CLASS = ACTION_BY_CLASS;
7350
+ exports.BacktickRuns = BacktickRuns;
7314
7351
  exports.CALLOUT_NAMES = CALLOUT_NAMES;
7315
7352
  exports.CAPABILITY_BY_CLASS = CAPABILITY_BY_CLASS;
7316
7353
  exports.CLASSES = CLASSES;
@@ -7318,6 +7355,7 @@ exports.DIRECTIVE_VERSION = DIRECTIVE_VERSION;
7318
7355
  exports.DirectiveDecodeError = DirectiveDecodeError;
7319
7356
  exports.FENCE_OPENER_WHITESPACE = FENCE_OPENER_WHITESPACE;
7320
7357
  exports.FENCE_WHITESPACE = FENCE_WHITESPACE;
7358
+ exports.FenceReader = FenceReader;
7321
7359
  exports.IN_CONTENT_CLASSES = IN_CONTENT_CLASSES;
7322
7360
  exports.IR_ENVELOPE_CACHE_VERSION = IR_ENVELOPE_CACHE_VERSION;
7323
7361
  exports.IR_ENVELOPE_KEY = IR_ENVELOPE_KEY;
@@ -7352,6 +7390,8 @@ exports.buildKindDirective = buildKindDirective;
7352
7390
  exports.capabilityOf = capabilityOf;
7353
7391
  exports.classifyInboundEnvelopeMetadata = classifyInboundEnvelopeMetadata;
7354
7392
  exports.classifyInnerFenceLine = classifyInnerFenceLine;
7393
+ exports.closeFence = closeFence;
7394
+ exports.codeSpanText = codeSpanText;
7355
7395
  exports.collectReferencedKinds = collectReferencedKinds;
7356
7396
  exports.collectSchemaReferencedKinds = collectSchemaReferencedKinds;
7357
7397
  exports.compareWithExistingKindSchema = compareWithExistingKindSchema;
@@ -7371,7 +7411,10 @@ exports.envelopeCacheFromEnvelopes = envelopeCacheFromEnvelopes;
7371
7411
  exports.envelopeFromCompleteValue = envelopeFromCompleteValue;
7372
7412
  exports.executesAtOutputRoot = executesAtOutputRoot;
7373
7413
  exports.fenceDiscriminator = fenceDiscriminator;
7414
+ exports.fenceLineKinds = fenceLineKinds;
7374
7415
  exports.fenceNestsInnerFences = fenceNestsInnerFences;
7416
+ exports.fenceOpenerOf = fenceOpenerOf;
7417
+ exports.fenceParts = fenceParts;
7375
7418
  exports.fieldsToDbPayload = fieldsToDbPayload;
7376
7419
  exports.findCodeRanges = findCodeRanges;
7377
7420
  exports.fingerprintText = fingerprintText;
@@ -7411,6 +7454,7 @@ exports.looksLikeDirectiveHead = looksLikeDirectiveHead;
7411
7454
  exports.looksLikeDisplayMath = looksLikeDisplayMath;
7412
7455
  exports.looksLikeOpenInlineMath = looksLikeOpenInlineMath;
7413
7456
  exports.makePartialKindStalenessGate = makePartialKindStalenessGate;
7457
+ exports.mapCodeRanges = mapCodeRanges;
7414
7458
  exports.mapPosition = mapPosition;
7415
7459
  exports.mapRange = mapRange;
7416
7460
  exports.mergeResidueIntoValue = mergeResidueIntoValue;