@ai-matrx/content-ir 0.16.1 → 0.16.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,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.16.2
4
+
5
+ - **Fixed (`/source` `pairDisplayMath`, `pendingDisplayMathOpener`):** a
6
+ `$$...$$` / `$$…$$` placeholder in prose was paired as display math. New
7
+ `isMathPlaceholder(inner)`; such a pair is consumed whole as literal text.
8
+ Same rule as `@ai-matrx/kit` `delimiter-guard`.
9
+ - Consumer action: none — refresh to latest.
10
+
3
11
  ## 0.16.1
4
12
 
5
13
  Automatic changed-only republish (docs/metadata drift since the last tag — see
package/dist/index.cjs CHANGED
@@ -5294,6 +5294,9 @@ var STRUCTURAL_MARKDOWN = /\]\(|https?:\/\/|\*\*|(?:^|\n)[ \t]{0,3}#{1,6}[ \t]|(
5294
5294
  var LATEX_COMMAND = /\\[a-zA-Z]/;
5295
5295
  var PROSE_WORD = /[A-Za-z]{3,}/g;
5296
5296
  var PROSE_WORD_LIMIT = 6;
5297
+ function isMathPlaceholder(inner) {
5298
+ return /^[\s.…·⋯_-]*$/.test(inner) && /[.…·⋯]/.test(inner);
5299
+ }
5297
5300
  function opensFlowBlock(text, open) {
5298
5301
  for (let k = open - 1; k >= 0 && text[k] !== "\n"; k--) if (text[k] !== " " && text[k] !== " ") return false;
5299
5302
  for (let k = open + 2; k < text.length && text[k] !== "\n"; k++) if (text[k] !== " " && text[k] !== " " && text[k] !== "\r") return false;
@@ -5312,13 +5315,84 @@ function looksLikeDisplayMath(inner, flow = false) {
5312
5315
  }
5313
5316
  function codeRanges(text) {
5314
5317
  const ranges = [];
5315
- for (const re of [/```[\s\S]*?(?:```|$)/g, /~~~[\s\S]*?(?:~~~|$)/g, /`[^`\n]*`/g]) {
5316
- let m;
5317
- while ((m = re.exec(text)) !== null) {
5318
- ranges.push([m.index, m.index + m[0].length]);
5319
- if (m[0].length === 0) re.lastIndex++;
5318
+ const n = text.length;
5319
+ let fence = null;
5320
+ let para = -1;
5321
+ const spans = (from, to) => {
5322
+ const runs = [];
5323
+ for (let k = from; k < to; ) {
5324
+ if (text.charCodeAt(k) !== 96) {
5325
+ k++;
5326
+ continue;
5327
+ }
5328
+ let len = 1;
5329
+ while (k + len < to && text.charCodeAt(k + len) === 96) len++;
5330
+ runs.push([k, len]);
5331
+ k += len;
5332
+ }
5333
+ const nextSame = new Array(runs.length).fill(-1);
5334
+ const last = /* @__PURE__ */ new Map();
5335
+ for (let r = runs.length - 1; r >= 0; r--) {
5336
+ const len = runs[r][1];
5337
+ nextSame[r] = last.get(len) ?? -1;
5338
+ last.set(len, r);
5339
+ }
5340
+ for (let r = 0; r < runs.length; ) {
5341
+ const j = nextSame[r];
5342
+ if (j === -1) {
5343
+ r++;
5344
+ continue;
5345
+ }
5346
+ const [s0] = runs[r];
5347
+ const [s1, l1] = runs[j];
5348
+ ranges.push([s0, s1 + l1]);
5349
+ r = j + 1;
5320
5350
  }
5321
- }
5351
+ };
5352
+ let pos = 0;
5353
+ while (pos <= n) {
5354
+ const nl = text.indexOf("\n", pos);
5355
+ const lineEnd = nl === -1 ? n : nl;
5356
+ const line = text.slice(pos, lineEnd);
5357
+ let indent = 0;
5358
+ while (indent < line.length && line[indent] === " ") indent++;
5359
+ const body = line.slice(indent);
5360
+ if (fence) {
5361
+ const trimmed = trimFenceLine(line);
5362
+ let closes = false;
5363
+ if (fence.char === "`") {
5364
+ const kind = classifyInnerFenceLine(trimmed, fence.len, fence.nests, fence.depth);
5365
+ if (kind === "open-nested") fence.depth++;
5366
+ else if (kind === "close-nested") fence.depth--;
5367
+ else if (kind === "close-outer") closes = indent <= 3;
5368
+ } else {
5369
+ let t = 0;
5370
+ while (t < trimmed.length && trimmed[t] === "~") t++;
5371
+ closes = indent <= 3 && t >= fence.len && trimFenceLine(trimmed.slice(t)) === "";
5372
+ }
5373
+ if (closes) {
5374
+ ranges.push([fence.start, lineEnd]);
5375
+ fence = null;
5376
+ }
5377
+ } else {
5378
+ const opener = indent <= 3 ? /^(`{3,}|~{3,})(.*)$/.exec(body) : null;
5379
+ const info = opener ? opener[2] : "";
5380
+ if (opener && !(opener[1][0] === "`" && info.includes("`"))) {
5381
+ if (para !== -1) spans(para, pos);
5382
+ para = -1;
5383
+ const char = opener[1][0];
5384
+ const parsed = char === "`" ? parseFenceOpener(line) : null;
5385
+ fence = { char, len: opener[1].length, start: pos, nests: fenceNestsInnerFences(parsed?.lang), depth: 0 };
5386
+ } else if (body.trim() === "") {
5387
+ if (para !== -1) spans(para, pos);
5388
+ para = -1;
5389
+ } else if (para === -1) para = pos;
5390
+ }
5391
+ if (nl === -1) break;
5392
+ pos = nl + 1;
5393
+ }
5394
+ if (fence) ranges.push([fence.start, n]);
5395
+ else if (para !== -1) spans(para, n);
5322
5396
  return ranges.sort((a, b) => a[0] - b[0]);
5323
5397
  }
5324
5398
  function pendingDisplayMathOpener(text) {
@@ -5341,6 +5415,10 @@ function pendingDisplayMathOpener(text) {
5341
5415
  const open = tokens[j];
5342
5416
  const close = tokens[j + 1];
5343
5417
  if (close === void 0) break;
5418
+ if (isMathPlaceholder(text.slice(open + 2, close))) {
5419
+ j += 2;
5420
+ continue;
5421
+ }
5344
5422
  if (looksLikeDisplayMath(text.slice(open + 2, close), opensFlowBlock(text, open))) {
5345
5423
  paired.add(open);
5346
5424
  paired.add(close);
@@ -5385,6 +5463,10 @@ function pairDisplayMath(text) {
5385
5463
  const open = tokens[j];
5386
5464
  const close = tokens[j + 1];
5387
5465
  if (close === void 0) break;
5466
+ if (isMathPlaceholder(text.slice(open + 2, close))) {
5467
+ j += 2;
5468
+ continue;
5469
+ }
5388
5470
  if (looksLikeDisplayMath(text.slice(open + 2, close), opensFlowBlock(text, open))) {
5389
5471
  pairs.set(open, close);
5390
5472
  j += 2;
@@ -5722,6 +5804,19 @@ var Tokenizer = class {
5722
5804
  this.mathPairs = pairDisplayMath(text);
5723
5805
  this.provisionalFrom = streaming ? pendingDisplayMathOpener(text) : -1;
5724
5806
  if (this.provisionalFrom === -1) this.provisionalFrom = Number.POSITIVE_INFINITY;
5807
+ if (streaming && text.includes("$$")) {
5808
+ for (const pad of ["`", "``", "```", "~~~"]) {
5809
+ const alt = pairDisplayMath(text + pad);
5810
+ for (const [open, close] of this.mathPairs) {
5811
+ if (alt.get(open) !== close) this.provisionalFrom = Math.min(this.provisionalFrom, open);
5812
+ }
5813
+ for (const [open, close] of alt) {
5814
+ if (close < text.length && this.mathPairs.get(open) !== close) {
5815
+ this.provisionalFrom = Math.min(this.provisionalFrom, open);
5816
+ }
5817
+ }
5818
+ }
5819
+ }
5725
5820
  let start = 0;
5726
5821
  for (let i = 0; i < text.length; i++) {
5727
5822
  if (text.charCodeAt(i) === 10) {
@@ -5762,13 +5857,17 @@ var Tokenizer = class {
5762
5857
  /**
5763
5858
  * Streaming: an open last line that begins with `{` is undecided — each new
5764
5859
  * byte can balance or unbalance its braces and flip the whole line between
5765
- * prose and a JSON island — so it is provisional until it ends (G5).
5860
+ * prose and a JSON island — and so is a line that is exactly one allowed
5861
+ * HTML tag so far; both are provisional until they end (G5).
5766
5862
  */
5767
5863
  markOpenJsonTail() {
5768
5864
  const last = this.lineStarts.length - 1;
5769
5865
  if (!this.isOpenTail(last)) return;
5770
5866
  const start = this.lineStarts[last];
5771
- if (this.lineText(last).trimStart().startsWith("{")) {
5867
+ const t = this.lineText(last).trim();
5868
+ const oneTag = t.startsWith("<") ? readXmlTag(t, 0) : null;
5869
+ const loneTag = !!oneTag && oneTag.raw === t && ALLOWED_RAW_HTML_TAGS.has(oneTag.tagName.toLowerCase());
5870
+ if (t.startsWith("{") || loneTag) {
5772
5871
  this.provisionalFrom = Math.min(this.provisionalFrom, start);
5773
5872
  }
5774
5873
  }
@@ -6062,10 +6161,16 @@ var Tokenizer = class {
6062
6161
  continue;
6063
6162
  }
6064
6163
  if (FOOTNOTE_DEF.test(line.trimStart()) || this.detectBlock(this.lineStarts[k], k, false)) break;
6065
- if (this.isOpenTail(k)) break;
6164
+ if (this.isOpenTail(k)) return this.heldFootnote(p, open[1]);
6066
6165
  last = k;
6067
6166
  }
6068
- return this.island("footnote_def", p, this.contentEnds[last], true, { id: open[1] });
6167
+ const end = this.contentEnds[last];
6168
+ if (this.paragraphMayGrow(end)) return this.heldFootnote(p, open[1]);
6169
+ return this.island("footnote_def", p, end, true, { id: open[1] });
6170
+ }
6171
+ /** A footnote whose continuation is still arriving: open to the end of the text. */
6172
+ heldFootnote(p, id) {
6173
+ return this.island("footnote_def", p, this.n, false, { id });
6069
6174
  }
6070
6175
  /**
6071
6176
  * Backtick fence — the renderer splitter's close rules: JSON-string aware for
@@ -6309,7 +6414,12 @@ var Tokenizer = class {
6309
6414
  return this.island("html_block", p, close.index + close[0].length, true, { tag: name });
6310
6415
  }
6311
6416
  const typeSix = HTML_BLOCK_LEVEL_TAGS.has(name);
6312
- const typeSeven = atParaStart && t.trimEnd() === tag.raw && !this.isOpenTail(li);
6417
+ const loneTag = atParaStart && t.trimEnd() === tag.raw;
6418
+ if (loneTag && this.isOpenTail(li)) {
6419
+ this.provisionalFrom = Math.min(this.provisionalFrom, p);
6420
+ return null;
6421
+ }
6422
+ const typeSeven = loneTag;
6313
6423
  if (!typeSix && !typeSeven) return null;
6314
6424
  let end = this.contentEnds[li];
6315
6425
  for (let k = li + 1; k < this.lineCount && !this.lineIsBlank(k); k++) {
@@ -6401,10 +6511,6 @@ var Tokenizer = class {
6401
6511
  let breakLine = -1;
6402
6512
  for (let k = li + 1; k < this.lineCount; k++) {
6403
6513
  if (this.lineIsBlank(k)) break;
6404
- if (this.lineStarts[k] >= this.provisionalFrom) {
6405
- end = this.n;
6406
- break;
6407
- }
6408
6514
  if (this.detectBlock(this.lineStarts[k], k, false)) {
6409
6515
  breakLine = k;
6410
6516
  break;
@@ -6547,7 +6653,11 @@ var Tokenizer = class {
6547
6653
  }
6548
6654
  const end = singleDollarMathEnd(text, i, pe);
6549
6655
  this.tick(end > 0 ? end - i : Math.min(403, pe - i));
6550
- if (end > 0 && !(this.streaming && end === this.n)) {
6656
+ if (end > 0 && this.streaming && end === this.n) {
6657
+ this.provisionalFrom = Math.min(this.provisionalFrom, i);
6658
+ return { inlines, breakIsland: null, orphan: false };
6659
+ }
6660
+ if (end > 0) {
6551
6661
  inlines.push(this.island("math_inline", i, end, true, { delimiter: "$" }));
6552
6662
  i = end;
6553
6663
  continue;
@@ -7117,6 +7227,7 @@ exports.isIrEnvelopeCache = isIrEnvelopeCache;
7117
7227
  exports.isJsonAnyField = isJsonAnyField;
7118
7228
  exports.isKindDirective = isKindDirective;
7119
7229
  exports.isLegacyShell = isLegacyShell;
7230
+ exports.isMathPlaceholder = isMathPlaceholder;
7120
7231
  exports.isProvisionalKind = isProvisionalKind;
7121
7232
  exports.isReservedDirectiveSlug = isReservedDirectiveSlug;
7122
7233
  exports.isScalarArrayType = isScalarArrayType;