@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/dist/source.cjs CHANGED
@@ -321,6 +321,9 @@ var STRUCTURAL_MARKDOWN = /\]\(|https?:\/\/|\*\*|(?:^|\n)[ \t]{0,3}#{1,6}[ \t]|(
321
321
  var LATEX_COMMAND = /\\[a-zA-Z]/;
322
322
  var PROSE_WORD = /[A-Za-z]{3,}/g;
323
323
  var PROSE_WORD_LIMIT = 6;
324
+ function isMathPlaceholder(inner) {
325
+ return /^[\s.…·⋯_-]*$/.test(inner) && /[.…·⋯]/.test(inner);
326
+ }
324
327
  function opensFlowBlock(text, open) {
325
328
  for (let k = open - 1; k >= 0 && text[k] !== "\n"; k--) if (text[k] !== " " && text[k] !== " ") return false;
326
329
  for (let k = open + 2; k < text.length && text[k] !== "\n"; k++) if (text[k] !== " " && text[k] !== " " && text[k] !== "\r") return false;
@@ -339,13 +342,84 @@ function looksLikeDisplayMath(inner, flow = false) {
339
342
  }
340
343
  function codeRanges(text) {
341
344
  const ranges = [];
342
- for (const re of [/```[\s\S]*?(?:```|$)/g, /~~~[\s\S]*?(?:~~~|$)/g, /`[^`\n]*`/g]) {
343
- let m;
344
- while ((m = re.exec(text)) !== null) {
345
- ranges.push([m.index, m.index + m[0].length]);
346
- if (m[0].length === 0) re.lastIndex++;
345
+ const n = text.length;
346
+ let fence = null;
347
+ let para = -1;
348
+ const spans = (from, to) => {
349
+ const runs = [];
350
+ for (let k = from; k < to; ) {
351
+ if (text.charCodeAt(k) !== 96) {
352
+ k++;
353
+ continue;
354
+ }
355
+ let len = 1;
356
+ while (k + len < to && text.charCodeAt(k + len) === 96) len++;
357
+ runs.push([k, len]);
358
+ k += len;
359
+ }
360
+ const nextSame = new Array(runs.length).fill(-1);
361
+ const last = /* @__PURE__ */ new Map();
362
+ for (let r = runs.length - 1; r >= 0; r--) {
363
+ const len = runs[r][1];
364
+ nextSame[r] = last.get(len) ?? -1;
365
+ last.set(len, r);
366
+ }
367
+ for (let r = 0; r < runs.length; ) {
368
+ const j = nextSame[r];
369
+ if (j === -1) {
370
+ r++;
371
+ continue;
372
+ }
373
+ const [s0] = runs[r];
374
+ const [s1, l1] = runs[j];
375
+ ranges.push([s0, s1 + l1]);
376
+ r = j + 1;
347
377
  }
348
- }
378
+ };
379
+ let pos = 0;
380
+ while (pos <= n) {
381
+ const nl = text.indexOf("\n", pos);
382
+ const lineEnd = nl === -1 ? n : nl;
383
+ const line = text.slice(pos, lineEnd);
384
+ let indent = 0;
385
+ while (indent < line.length && line[indent] === " ") indent++;
386
+ const body = line.slice(indent);
387
+ if (fence) {
388
+ const trimmed = trimFenceLine(line);
389
+ let closes = false;
390
+ if (fence.char === "`") {
391
+ const kind = classifyInnerFenceLine(trimmed, fence.len, fence.nests, fence.depth);
392
+ if (kind === "open-nested") fence.depth++;
393
+ else if (kind === "close-nested") fence.depth--;
394
+ else if (kind === "close-outer") closes = indent <= 3;
395
+ } else {
396
+ let t = 0;
397
+ while (t < trimmed.length && trimmed[t] === "~") t++;
398
+ closes = indent <= 3 && t >= fence.len && trimFenceLine(trimmed.slice(t)) === "";
399
+ }
400
+ if (closes) {
401
+ ranges.push([fence.start, lineEnd]);
402
+ fence = null;
403
+ }
404
+ } else {
405
+ const opener = indent <= 3 ? /^(`{3,}|~{3,})(.*)$/.exec(body) : null;
406
+ const info = opener ? opener[2] : "";
407
+ if (opener && !(opener[1][0] === "`" && info.includes("`"))) {
408
+ if (para !== -1) spans(para, pos);
409
+ para = -1;
410
+ const char = opener[1][0];
411
+ const parsed = char === "`" ? parseFenceOpener(line) : null;
412
+ fence = { char, len: opener[1].length, start: pos, nests: fenceNestsInnerFences(parsed?.lang), depth: 0 };
413
+ } else if (body.trim() === "") {
414
+ if (para !== -1) spans(para, pos);
415
+ para = -1;
416
+ } else if (para === -1) para = pos;
417
+ }
418
+ if (nl === -1) break;
419
+ pos = nl + 1;
420
+ }
421
+ if (fence) ranges.push([fence.start, n]);
422
+ else if (para !== -1) spans(para, n);
349
423
  return ranges.sort((a, b) => a[0] - b[0]);
350
424
  }
351
425
  function pendingDisplayMathOpener(text) {
@@ -368,6 +442,10 @@ function pendingDisplayMathOpener(text) {
368
442
  const open = tokens[j];
369
443
  const close = tokens[j + 1];
370
444
  if (close === void 0) break;
445
+ if (isMathPlaceholder(text.slice(open + 2, close))) {
446
+ j += 2;
447
+ continue;
448
+ }
371
449
  if (looksLikeDisplayMath(text.slice(open + 2, close), opensFlowBlock(text, open))) {
372
450
  paired.add(open);
373
451
  paired.add(close);
@@ -412,6 +490,10 @@ function pairDisplayMath(text) {
412
490
  const open = tokens[j];
413
491
  const close = tokens[j + 1];
414
492
  if (close === void 0) break;
493
+ if (isMathPlaceholder(text.slice(open + 2, close))) {
494
+ j += 2;
495
+ continue;
496
+ }
415
497
  if (looksLikeDisplayMath(text.slice(open + 2, close), opensFlowBlock(text, open))) {
416
498
  pairs.set(open, close);
417
499
  j += 2;
@@ -749,6 +831,19 @@ var Tokenizer = class {
749
831
  this.mathPairs = pairDisplayMath(text);
750
832
  this.provisionalFrom = streaming ? pendingDisplayMathOpener(text) : -1;
751
833
  if (this.provisionalFrom === -1) this.provisionalFrom = Number.POSITIVE_INFINITY;
834
+ if (streaming && text.includes("$$")) {
835
+ for (const pad of ["`", "``", "```", "~~~"]) {
836
+ const alt = pairDisplayMath(text + pad);
837
+ for (const [open, close] of this.mathPairs) {
838
+ if (alt.get(open) !== close) this.provisionalFrom = Math.min(this.provisionalFrom, open);
839
+ }
840
+ for (const [open, close] of alt) {
841
+ if (close < text.length && this.mathPairs.get(open) !== close) {
842
+ this.provisionalFrom = Math.min(this.provisionalFrom, open);
843
+ }
844
+ }
845
+ }
846
+ }
752
847
  let start = 0;
753
848
  for (let i = 0; i < text.length; i++) {
754
849
  if (text.charCodeAt(i) === 10) {
@@ -789,13 +884,17 @@ var Tokenizer = class {
789
884
  /**
790
885
  * Streaming: an open last line that begins with `{` is undecided — each new
791
886
  * byte can balance or unbalance its braces and flip the whole line between
792
- * prose and a JSON island — so it is provisional until it ends (G5).
887
+ * prose and a JSON island — and so is a line that is exactly one allowed
888
+ * HTML tag so far; both are provisional until they end (G5).
793
889
  */
794
890
  markOpenJsonTail() {
795
891
  const last = this.lineStarts.length - 1;
796
892
  if (!this.isOpenTail(last)) return;
797
893
  const start = this.lineStarts[last];
798
- if (this.lineText(last).trimStart().startsWith("{")) {
894
+ const t = this.lineText(last).trim();
895
+ const oneTag = t.startsWith("<") ? readXmlTag(t, 0) : null;
896
+ const loneTag = !!oneTag && oneTag.raw === t && ALLOWED_RAW_HTML_TAGS.has(oneTag.tagName.toLowerCase());
897
+ if (t.startsWith("{") || loneTag) {
799
898
  this.provisionalFrom = Math.min(this.provisionalFrom, start);
800
899
  }
801
900
  }
@@ -1089,10 +1188,16 @@ var Tokenizer = class {
1089
1188
  continue;
1090
1189
  }
1091
1190
  if (FOOTNOTE_DEF.test(line.trimStart()) || this.detectBlock(this.lineStarts[k], k, false)) break;
1092
- if (this.isOpenTail(k)) break;
1191
+ if (this.isOpenTail(k)) return this.heldFootnote(p, open[1]);
1093
1192
  last = k;
1094
1193
  }
1095
- return this.island("footnote_def", p, this.contentEnds[last], true, { id: open[1] });
1194
+ const end = this.contentEnds[last];
1195
+ if (this.paragraphMayGrow(end)) return this.heldFootnote(p, open[1]);
1196
+ return this.island("footnote_def", p, end, true, { id: open[1] });
1197
+ }
1198
+ /** A footnote whose continuation is still arriving: open to the end of the text. */
1199
+ heldFootnote(p, id) {
1200
+ return this.island("footnote_def", p, this.n, false, { id });
1096
1201
  }
1097
1202
  /**
1098
1203
  * Backtick fence — the renderer splitter's close rules: JSON-string aware for
@@ -1336,7 +1441,12 @@ var Tokenizer = class {
1336
1441
  return this.island("html_block", p, close.index + close[0].length, true, { tag: name });
1337
1442
  }
1338
1443
  const typeSix = HTML_BLOCK_LEVEL_TAGS.has(name);
1339
- const typeSeven = atParaStart && t.trimEnd() === tag.raw && !this.isOpenTail(li);
1444
+ const loneTag = atParaStart && t.trimEnd() === tag.raw;
1445
+ if (loneTag && this.isOpenTail(li)) {
1446
+ this.provisionalFrom = Math.min(this.provisionalFrom, p);
1447
+ return null;
1448
+ }
1449
+ const typeSeven = loneTag;
1340
1450
  if (!typeSix && !typeSeven) return null;
1341
1451
  let end = this.contentEnds[li];
1342
1452
  for (let k = li + 1; k < this.lineCount && !this.lineIsBlank(k); k++) {
@@ -1428,10 +1538,6 @@ var Tokenizer = class {
1428
1538
  let breakLine = -1;
1429
1539
  for (let k = li + 1; k < this.lineCount; k++) {
1430
1540
  if (this.lineIsBlank(k)) break;
1431
- if (this.lineStarts[k] >= this.provisionalFrom) {
1432
- end = this.n;
1433
- break;
1434
- }
1435
1541
  if (this.detectBlock(this.lineStarts[k], k, false)) {
1436
1542
  breakLine = k;
1437
1543
  break;
@@ -1574,7 +1680,11 @@ var Tokenizer = class {
1574
1680
  }
1575
1681
  const end = singleDollarMathEnd(text, i, pe);
1576
1682
  this.tick(end > 0 ? end - i : Math.min(403, pe - i));
1577
- if (end > 0 && !(this.streaming && end === this.n)) {
1683
+ if (end > 0 && this.streaming && end === this.n) {
1684
+ this.provisionalFrom = Math.min(this.provisionalFrom, i);
1685
+ return { inlines, breakIsland: null, orphan: false };
1686
+ }
1687
+ if (end > 0) {
1578
1688
  inlines.push(this.island("math_inline", i, end, true, { delimiter: "$" }));
1579
1689
  i = end;
1580
1690
  continue;
@@ -2077,6 +2187,7 @@ exports.blockRangeEdit = blockRangeEdit;
2077
2187
  exports.buildCodePointIndex = buildCodePointIndex;
2078
2188
  exports.classifyInnerFenceLine = classifyInnerFenceLine;
2079
2189
  exports.fenceNestsInnerFences = fenceNestsInnerFences;
2190
+ exports.isMathPlaceholder = isMathPlaceholder;
2080
2191
  exports.isSingleDollarMath = isSingleDollarMath;
2081
2192
  exports.islandEdit = islandEdit;
2082
2193
  exports.joinSource = joinSource;