@ai-matrx/content-ir 0.16.0 → 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 +22 -0
- package/dist/index.cjs +141 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +141 -19
- package/dist/index.js.map +1 -1
- package/dist/source.cjs +141 -18
- package/dist/source.cjs.map +1 -1
- package/dist/source.d.cts +5 -14
- package/dist/source.d.ts +5 -14
- package/dist/source.js +141 -19
- package/dist/source.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
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
|
+
|
|
11
|
+
## 0.16.1
|
|
12
|
+
|
|
13
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
14
|
+
`git diff npm/content-ir-core/v0.16.0..npm/content-ir-core/v0.16.1 -- apps/shared/content-ir-core`).
|
|
15
|
+
No source changes intended and no consumer action required.
|
|
16
|
+
|
|
17
|
+
## Unreleased
|
|
18
|
+
|
|
19
|
+
**`/source` — a callout or `:::` directive nested in a list item stays in the
|
|
20
|
+
list's prose block** (verify-RC-B8 round 2, SAFETY). Guard:
|
|
21
|
+
`source-markdown-syntax-islands.test.ts` (3 cases red before).
|
|
22
|
+
|
|
23
|
+
**Consumer action:** none.
|
|
24
|
+
|
|
3
25
|
## 0.16.0 — 2026-09-25
|
|
4
26
|
|
|
5
27
|
**`/source` — a deterministic attack suite, and streaming that only ever
|
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
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
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
|
|
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
|
-
|
|
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
|
}
|
|
@@ -5897,7 +5996,8 @@ var Tokenizer = class {
|
|
|
5897
5996
|
const fm = this.frontMatter(li, t);
|
|
5898
5997
|
if (fm) return fm;
|
|
5899
5998
|
}
|
|
5900
|
-
|
|
5999
|
+
const listNested = indent > 0 && this.inListContinuation(li);
|
|
6000
|
+
if (indent <= 3 && !listNested && t.startsWith("::")) {
|
|
5901
6001
|
const directive = this.directive(p, li, t);
|
|
5902
6002
|
if (directive) return directive;
|
|
5903
6003
|
}
|
|
@@ -5905,7 +6005,7 @@ var Tokenizer = class {
|
|
|
5905
6005
|
const admonition = this.mkdocsAdmonition(p, li, t);
|
|
5906
6006
|
if (admonition) return admonition;
|
|
5907
6007
|
}
|
|
5908
|
-
if (indent <= 3 && t.startsWith(">")) {
|
|
6008
|
+
if (indent <= 3 && !listNested && t.startsWith(">")) {
|
|
5909
6009
|
const callout = this.callout(p, li, t);
|
|
5910
6010
|
if (callout) return callout;
|
|
5911
6011
|
}
|
|
@@ -5946,6 +6046,17 @@ var Tokenizer = class {
|
|
|
5946
6046
|
}
|
|
5947
6047
|
return null;
|
|
5948
6048
|
}
|
|
6049
|
+
/** True when line `li` continues a list item (the nearest non-blank line above is a list item or indented text under one). */
|
|
6050
|
+
inListContinuation(li) {
|
|
6051
|
+
for (let k = li - 1; k >= 0; k--) {
|
|
6052
|
+
const line = this.lineText(k);
|
|
6053
|
+
if (!NOT_WHITESPACE.test(line)) continue;
|
|
6054
|
+
if (/^[ \t]*(?:[-*+]|\d{1,9}[.)])[ \t]/.test(line)) return true;
|
|
6055
|
+
if (/^[ \t]/.test(line)) continue;
|
|
6056
|
+
return false;
|
|
6057
|
+
}
|
|
6058
|
+
return false;
|
|
6059
|
+
}
|
|
5949
6060
|
island(type, start, end, complete, meta = {}) {
|
|
5950
6061
|
return { type, start, end, complete, meta };
|
|
5951
6062
|
}
|
|
@@ -6050,10 +6161,16 @@ var Tokenizer = class {
|
|
|
6050
6161
|
continue;
|
|
6051
6162
|
}
|
|
6052
6163
|
if (FOOTNOTE_DEF.test(line.trimStart()) || this.detectBlock(this.lineStarts[k], k, false)) break;
|
|
6053
|
-
if (this.isOpenTail(k))
|
|
6164
|
+
if (this.isOpenTail(k)) return this.heldFootnote(p, open[1]);
|
|
6054
6165
|
last = k;
|
|
6055
6166
|
}
|
|
6056
|
-
|
|
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 });
|
|
6057
6174
|
}
|
|
6058
6175
|
/**
|
|
6059
6176
|
* Backtick fence — the renderer splitter's close rules: JSON-string aware for
|
|
@@ -6297,7 +6414,12 @@ var Tokenizer = class {
|
|
|
6297
6414
|
return this.island("html_block", p, close.index + close[0].length, true, { tag: name });
|
|
6298
6415
|
}
|
|
6299
6416
|
const typeSix = HTML_BLOCK_LEVEL_TAGS.has(name);
|
|
6300
|
-
const
|
|
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;
|
|
6301
6423
|
if (!typeSix && !typeSeven) return null;
|
|
6302
6424
|
let end = this.contentEnds[li];
|
|
6303
6425
|
for (let k = li + 1; k < this.lineCount && !this.lineIsBlank(k); k++) {
|
|
@@ -6389,10 +6511,6 @@ var Tokenizer = class {
|
|
|
6389
6511
|
let breakLine = -1;
|
|
6390
6512
|
for (let k = li + 1; k < this.lineCount; k++) {
|
|
6391
6513
|
if (this.lineIsBlank(k)) break;
|
|
6392
|
-
if (this.lineStarts[k] >= this.provisionalFrom) {
|
|
6393
|
-
end = this.n;
|
|
6394
|
-
break;
|
|
6395
|
-
}
|
|
6396
6514
|
if (this.detectBlock(this.lineStarts[k], k, false)) {
|
|
6397
6515
|
breakLine = k;
|
|
6398
6516
|
break;
|
|
@@ -6535,7 +6653,11 @@ var Tokenizer = class {
|
|
|
6535
6653
|
}
|
|
6536
6654
|
const end = singleDollarMathEnd(text, i, pe);
|
|
6537
6655
|
this.tick(end > 0 ? end - i : Math.min(403, pe - i));
|
|
6538
|
-
if (end > 0 &&
|
|
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) {
|
|
6539
6661
|
inlines.push(this.island("math_inline", i, end, true, { delimiter: "$" }));
|
|
6540
6662
|
i = end;
|
|
6541
6663
|
continue;
|
|
@@ -7105,6 +7227,7 @@ exports.isIrEnvelopeCache = isIrEnvelopeCache;
|
|
|
7105
7227
|
exports.isJsonAnyField = isJsonAnyField;
|
|
7106
7228
|
exports.isKindDirective = isKindDirective;
|
|
7107
7229
|
exports.isLegacyShell = isLegacyShell;
|
|
7230
|
+
exports.isMathPlaceholder = isMathPlaceholder;
|
|
7108
7231
|
exports.isProvisionalKind = isProvisionalKind;
|
|
7109
7232
|
exports.isReservedDirectiveSlug = isReservedDirectiveSlug;
|
|
7110
7233
|
exports.isScalarArrayType = isScalarArrayType;
|