@ai-matrx/content-ir 0.16.1 → 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/CHANGELOG.md +63 -0
- package/README.md +24 -0
- package/dist/index.cjs +212 -19
- 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 +211 -20
- package/dist/index.js.map +1 -1
- package/dist/source.cjs +212 -19
- package/dist/source.cjs.map +1 -1
- package/dist/source.d.cts +31 -15
- package/dist/source.d.ts +31 -15
- package/dist/source.js +211 -20
- package/dist/source.js.map +1 -1
- package/package.json +1 -1
package/dist/source.cjs
CHANGED
|
@@ -315,12 +315,167 @@ function singleDollarMathEnd(text, open, limit = text.length) {
|
|
|
315
315
|
return isSingleDollarMath(content, text[close + 1]) ? close + 1 : -1;
|
|
316
316
|
}
|
|
317
317
|
|
|
318
|
+
// source/code-ranges.ts
|
|
319
|
+
function findCodeRanges(text) {
|
|
320
|
+
const ranges = [];
|
|
321
|
+
const n = text.length;
|
|
322
|
+
let fence = null;
|
|
323
|
+
let para = -1;
|
|
324
|
+
const spans = (from, to) => {
|
|
325
|
+
const runs = [];
|
|
326
|
+
for (let k = from; k < to; ) {
|
|
327
|
+
if (text.charCodeAt(k) !== 96) {
|
|
328
|
+
k++;
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
let len = 1;
|
|
332
|
+
while (k + len < to && text.charCodeAt(k + len) === 96) len++;
|
|
333
|
+
runs.push([k, len]);
|
|
334
|
+
k += len;
|
|
335
|
+
}
|
|
336
|
+
const nextSame = new Array(runs.length).fill(-1);
|
|
337
|
+
const last = /* @__PURE__ */ new Map();
|
|
338
|
+
for (let r = runs.length - 1; r >= 0; r--) {
|
|
339
|
+
const len = runs[r][1];
|
|
340
|
+
nextSame[r] = last.get(len) ?? -1;
|
|
341
|
+
last.set(len, r);
|
|
342
|
+
}
|
|
343
|
+
for (let r = 0; r < runs.length; ) {
|
|
344
|
+
const j = nextSame[r];
|
|
345
|
+
if (j === -1) {
|
|
346
|
+
r++;
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
const [s0] = runs[r];
|
|
350
|
+
const [s1, l1] = runs[j];
|
|
351
|
+
ranges.push({ start: s0, end: s1 + l1, kind: "span" });
|
|
352
|
+
r = j + 1;
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
let pos = 0;
|
|
356
|
+
while (pos <= n) {
|
|
357
|
+
const nl = text.indexOf("\n", pos);
|
|
358
|
+
const lineEnd = nl === -1 ? n : nl;
|
|
359
|
+
const line = text.slice(pos, lineEnd);
|
|
360
|
+
let indent = 0;
|
|
361
|
+
while (indent < line.length && line[indent] === " ") indent++;
|
|
362
|
+
const body = line.slice(indent);
|
|
363
|
+
if (fence) {
|
|
364
|
+
const trimmed = trimFenceLine(line);
|
|
365
|
+
let closes = false;
|
|
366
|
+
if (fence.char === "`") {
|
|
367
|
+
const kind = classifyInnerFenceLine(trimmed, fence.len, fence.nests, fence.depth);
|
|
368
|
+
if (kind === "open-nested") fence.depth++;
|
|
369
|
+
else if (kind === "close-nested") fence.depth--;
|
|
370
|
+
else if (kind === "close-outer") closes = indent <= 3;
|
|
371
|
+
} else {
|
|
372
|
+
let t = 0;
|
|
373
|
+
while (t < trimmed.length && trimmed[t] === "~") t++;
|
|
374
|
+
closes = indent <= 3 && t >= fence.len && trimFenceLine(trimmed.slice(t)) === "";
|
|
375
|
+
}
|
|
376
|
+
if (closes) {
|
|
377
|
+
ranges.push({ start: fence.start, end: lineEnd, kind: "fence" });
|
|
378
|
+
fence = null;
|
|
379
|
+
}
|
|
380
|
+
} else {
|
|
381
|
+
const opener = indent <= 3 ? /^(`{3,}|~{3,})(.*)$/.exec(body) : null;
|
|
382
|
+
const info = opener ? opener[2] : "";
|
|
383
|
+
if (opener && !(opener[1][0] === "`" && info.includes("`"))) {
|
|
384
|
+
if (para !== -1) spans(para, pos);
|
|
385
|
+
para = -1;
|
|
386
|
+
const char = opener[1][0];
|
|
387
|
+
const parsed = char === "`" ? parseFenceOpener(line) : null;
|
|
388
|
+
fence = { char, len: opener[1].length, start: pos, nests: fenceNestsInnerFences(parsed?.lang), depth: 0 };
|
|
389
|
+
} else if (body.trim() === "") {
|
|
390
|
+
if (para !== -1) spans(para, pos);
|
|
391
|
+
para = -1;
|
|
392
|
+
} else if (para === -1) para = pos;
|
|
393
|
+
}
|
|
394
|
+
if (nl === -1) break;
|
|
395
|
+
pos = nl + 1;
|
|
396
|
+
}
|
|
397
|
+
if (fence) ranges.push({ start: fence.start, end: n, kind: "fence" });
|
|
398
|
+
else if (para !== -1) spans(para, n);
|
|
399
|
+
return ranges.sort((a, b) => a.start - b.start);
|
|
400
|
+
}
|
|
401
|
+
function pendingCodeSpanStart(text) {
|
|
402
|
+
const n = text.length;
|
|
403
|
+
if (n === 0 || /\n[ \t]*\n[ \t]*$/.test(text)) return -1;
|
|
404
|
+
let fence = null;
|
|
405
|
+
let para = -1;
|
|
406
|
+
let pos = 0;
|
|
407
|
+
while (pos <= n) {
|
|
408
|
+
const nl = text.indexOf("\n", pos);
|
|
409
|
+
const lineEnd = nl === -1 ? n : nl;
|
|
410
|
+
const line = text.slice(pos, lineEnd);
|
|
411
|
+
let indent = 0;
|
|
412
|
+
while (indent < line.length && line[indent] === " ") indent++;
|
|
413
|
+
const body = line.slice(indent);
|
|
414
|
+
if (fence) {
|
|
415
|
+
const trimmed = trimFenceLine(line);
|
|
416
|
+
let closes = false;
|
|
417
|
+
if (fence.char === "`") {
|
|
418
|
+
const kind = classifyInnerFenceLine(trimmed, fence.len, fence.nests, fence.depth);
|
|
419
|
+
if (kind === "open-nested") fence.depth++;
|
|
420
|
+
else if (kind === "close-nested") fence.depth--;
|
|
421
|
+
else if (kind === "close-outer") closes = indent <= 3;
|
|
422
|
+
} else {
|
|
423
|
+
let t = 0;
|
|
424
|
+
while (t < trimmed.length && trimmed[t] === "~") t++;
|
|
425
|
+
closes = indent <= 3 && t >= fence.len && trimFenceLine(trimmed.slice(t)) === "";
|
|
426
|
+
}
|
|
427
|
+
if (closes) fence = null;
|
|
428
|
+
} else {
|
|
429
|
+
const opener = indent <= 3 ? /^(`{3,}|~{3,})(.*)$/.exec(body) : null;
|
|
430
|
+
const info = opener ? opener[2] : "";
|
|
431
|
+
if (opener && !(opener[1][0] === "`" && info.includes("`"))) {
|
|
432
|
+
para = -1;
|
|
433
|
+
const char = opener[1][0];
|
|
434
|
+
const parsed = char === "`" ? parseFenceOpener(line) : null;
|
|
435
|
+
fence = { char, len: opener[1].length, nests: fenceNestsInnerFences(parsed?.lang), depth: 0 };
|
|
436
|
+
} else if (body.trim() === "") {
|
|
437
|
+
if (!(nl === -1 && line === "")) para = -1;
|
|
438
|
+
} else if (para === -1) para = pos;
|
|
439
|
+
}
|
|
440
|
+
if (nl === -1) break;
|
|
441
|
+
pos = nl + 1;
|
|
442
|
+
}
|
|
443
|
+
if (fence || para === -1) return -1;
|
|
444
|
+
const runs = [];
|
|
445
|
+
for (let k = para; k < n; ) {
|
|
446
|
+
if (text.charCodeAt(k) !== 96) {
|
|
447
|
+
k++;
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
let len = 1;
|
|
451
|
+
while (k + len < n && text.charCodeAt(k + len) === 96) len++;
|
|
452
|
+
runs.push([k, len]);
|
|
453
|
+
k += len;
|
|
454
|
+
}
|
|
455
|
+
const growing = (r) => {
|
|
456
|
+
const [start, len] = runs[r];
|
|
457
|
+
return start + len === n;
|
|
458
|
+
};
|
|
459
|
+
for (let r = 0; r < runs.length; ) {
|
|
460
|
+
if (growing(r)) return runs[r][0];
|
|
461
|
+
const len = runs[r][1];
|
|
462
|
+
let j = r + 1;
|
|
463
|
+
while (j < runs.length && (runs[j][1] !== len || growing(j))) j++;
|
|
464
|
+
if (j >= runs.length) return runs[r][0];
|
|
465
|
+
r = j + 1;
|
|
466
|
+
}
|
|
467
|
+
return -1;
|
|
468
|
+
}
|
|
469
|
+
|
|
318
470
|
// source/math-pairs.ts
|
|
319
471
|
var MAX_MATH_SPAN = 600;
|
|
320
472
|
var STRUCTURAL_MARKDOWN = /\]\(|https?:\/\/|\*\*|(?:^|\n)[ \t]{0,3}#{1,6}[ \t]|(?:^|\n)[ \t]*[-*+][ \t]+|(?:^|\n)[ \t]*\d+[.)][ \t]/;
|
|
321
473
|
var LATEX_COMMAND = /\\[a-zA-Z]/;
|
|
322
474
|
var PROSE_WORD = /[A-Za-z]{3,}/g;
|
|
323
475
|
var PROSE_WORD_LIMIT = 6;
|
|
476
|
+
function isMathPlaceholder(inner) {
|
|
477
|
+
return /^[\s.…·⋯_-]*$/.test(inner) && /[.…·⋯]/.test(inner);
|
|
478
|
+
}
|
|
324
479
|
function opensFlowBlock(text, open) {
|
|
325
480
|
for (let k = open - 1; k >= 0 && text[k] !== "\n"; k--) if (text[k] !== " " && text[k] !== " ") return false;
|
|
326
481
|
for (let k = open + 2; k < text.length && text[k] !== "\n"; k++) if (text[k] !== " " && text[k] !== " " && text[k] !== "\r") return false;
|
|
@@ -338,15 +493,7 @@ function looksLikeDisplayMath(inner, flow = false) {
|
|
|
338
493
|
return (s.match(PROSE_WORD) ?? []).length < PROSE_WORD_LIMIT;
|
|
339
494
|
}
|
|
340
495
|
function codeRanges(text) {
|
|
341
|
-
|
|
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++;
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
return ranges.sort((a, b) => a[0] - b[0]);
|
|
496
|
+
return findCodeRanges(text).map((r) => [r.start, r.end]);
|
|
350
497
|
}
|
|
351
498
|
function pendingDisplayMathOpener(text) {
|
|
352
499
|
if (!text.includes("$$")) return -1;
|
|
@@ -368,6 +515,10 @@ function pendingDisplayMathOpener(text) {
|
|
|
368
515
|
const open = tokens[j];
|
|
369
516
|
const close = tokens[j + 1];
|
|
370
517
|
if (close === void 0) break;
|
|
518
|
+
if (isMathPlaceholder(text.slice(open + 2, close))) {
|
|
519
|
+
j += 2;
|
|
520
|
+
continue;
|
|
521
|
+
}
|
|
371
522
|
if (looksLikeDisplayMath(text.slice(open + 2, close), opensFlowBlock(text, open))) {
|
|
372
523
|
paired.add(open);
|
|
373
524
|
paired.add(close);
|
|
@@ -412,6 +563,10 @@ function pairDisplayMath(text) {
|
|
|
412
563
|
const open = tokens[j];
|
|
413
564
|
const close = tokens[j + 1];
|
|
414
565
|
if (close === void 0) break;
|
|
566
|
+
if (isMathPlaceholder(text.slice(open + 2, close))) {
|
|
567
|
+
j += 2;
|
|
568
|
+
continue;
|
|
569
|
+
}
|
|
415
570
|
if (looksLikeDisplayMath(text.slice(open + 2, close), opensFlowBlock(text, open))) {
|
|
416
571
|
pairs.set(open, close);
|
|
417
572
|
j += 2;
|
|
@@ -749,6 +904,27 @@ var Tokenizer = class {
|
|
|
749
904
|
this.mathPairs = pairDisplayMath(text);
|
|
750
905
|
this.provisionalFrom = streaming ? pendingDisplayMathOpener(text) : -1;
|
|
751
906
|
if (this.provisionalFrom === -1) this.provisionalFrom = Number.POSITIVE_INFINITY;
|
|
907
|
+
if (streaming && text.includes("$$")) {
|
|
908
|
+
const span = pendingCodeSpanStart(text);
|
|
909
|
+
if (span !== -1) {
|
|
910
|
+
const firstToken = text.indexOf("$$", span);
|
|
911
|
+
if (firstToken !== -1) this.provisionalFrom = Math.min(this.provisionalFrom, firstToken);
|
|
912
|
+
for (const [open, close] of this.mathPairs) {
|
|
913
|
+
if (close >= span) this.provisionalFrom = Math.min(this.provisionalFrom, open);
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
for (const pad of ["`", "``", "```", "~~~"]) {
|
|
917
|
+
const alt = pairDisplayMath(text + pad);
|
|
918
|
+
for (const [open, close] of this.mathPairs) {
|
|
919
|
+
if (alt.get(open) !== close) this.provisionalFrom = Math.min(this.provisionalFrom, open);
|
|
920
|
+
}
|
|
921
|
+
for (const [open, close] of alt) {
|
|
922
|
+
if (close < text.length && this.mathPairs.get(open) !== close) {
|
|
923
|
+
this.provisionalFrom = Math.min(this.provisionalFrom, open);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
}
|
|
752
928
|
let start = 0;
|
|
753
929
|
for (let i = 0; i < text.length; i++) {
|
|
754
930
|
if (text.charCodeAt(i) === 10) {
|
|
@@ -789,13 +965,17 @@ var Tokenizer = class {
|
|
|
789
965
|
/**
|
|
790
966
|
* Streaming: an open last line that begins with `{` is undecided — each new
|
|
791
967
|
* byte can balance or unbalance its braces and flip the whole line between
|
|
792
|
-
* prose and a JSON island — so
|
|
968
|
+
* prose and a JSON island — and so is a line that is exactly one allowed
|
|
969
|
+
* HTML tag so far; both are provisional until they end (G5).
|
|
793
970
|
*/
|
|
794
971
|
markOpenJsonTail() {
|
|
795
972
|
const last = this.lineStarts.length - 1;
|
|
796
973
|
if (!this.isOpenTail(last)) return;
|
|
797
974
|
const start = this.lineStarts[last];
|
|
798
|
-
|
|
975
|
+
const t = this.lineText(last).trim();
|
|
976
|
+
const oneTag = t.startsWith("<") ? readXmlTag(t, 0) : null;
|
|
977
|
+
const loneTag = !!oneTag && oneTag.raw === t && ALLOWED_RAW_HTML_TAGS.has(oneTag.tagName.toLowerCase());
|
|
978
|
+
if (t.startsWith("{") || loneTag) {
|
|
799
979
|
this.provisionalFrom = Math.min(this.provisionalFrom, start);
|
|
800
980
|
}
|
|
801
981
|
}
|
|
@@ -1088,11 +1268,17 @@ var Tokenizer = class {
|
|
|
1088
1268
|
last = k;
|
|
1089
1269
|
continue;
|
|
1090
1270
|
}
|
|
1271
|
+
if (this.isOpenTail(k)) return this.heldFootnote(p, open[1]);
|
|
1091
1272
|
if (FOOTNOTE_DEF.test(line.trimStart()) || this.detectBlock(this.lineStarts[k], k, false)) break;
|
|
1092
|
-
if (this.isOpenTail(k)) break;
|
|
1093
1273
|
last = k;
|
|
1094
1274
|
}
|
|
1095
|
-
|
|
1275
|
+
const end = this.contentEnds[last];
|
|
1276
|
+
if (this.paragraphMayGrow(end)) return this.heldFootnote(p, open[1]);
|
|
1277
|
+
return this.island("footnote_def", p, end, true, { id: open[1] });
|
|
1278
|
+
}
|
|
1279
|
+
/** A footnote whose continuation is still arriving: open to the end of the text. */
|
|
1280
|
+
heldFootnote(p, id) {
|
|
1281
|
+
return this.island("footnote_def", p, this.n, false, { id });
|
|
1096
1282
|
}
|
|
1097
1283
|
/**
|
|
1098
1284
|
* Backtick fence — the renderer splitter's close rules: JSON-string aware for
|
|
@@ -1336,7 +1522,12 @@ var Tokenizer = class {
|
|
|
1336
1522
|
return this.island("html_block", p, close.index + close[0].length, true, { tag: name });
|
|
1337
1523
|
}
|
|
1338
1524
|
const typeSix = HTML_BLOCK_LEVEL_TAGS.has(name);
|
|
1339
|
-
const
|
|
1525
|
+
const loneTag = atParaStart && t.trimEnd() === tag.raw;
|
|
1526
|
+
if (loneTag && this.isOpenTail(li)) {
|
|
1527
|
+
this.provisionalFrom = Math.min(this.provisionalFrom, p);
|
|
1528
|
+
return null;
|
|
1529
|
+
}
|
|
1530
|
+
const typeSeven = loneTag;
|
|
1340
1531
|
if (!typeSix && !typeSeven) return null;
|
|
1341
1532
|
let end = this.contentEnds[li];
|
|
1342
1533
|
for (let k = li + 1; k < this.lineCount && !this.lineIsBlank(k); k++) {
|
|
@@ -1428,10 +1619,6 @@ var Tokenizer = class {
|
|
|
1428
1619
|
let breakLine = -1;
|
|
1429
1620
|
for (let k = li + 1; k < this.lineCount; k++) {
|
|
1430
1621
|
if (this.lineIsBlank(k)) break;
|
|
1431
|
-
if (this.lineStarts[k] >= this.provisionalFrom) {
|
|
1432
|
-
end = this.n;
|
|
1433
|
-
break;
|
|
1434
|
-
}
|
|
1435
1622
|
if (this.detectBlock(this.lineStarts[k], k, false)) {
|
|
1436
1623
|
breakLine = k;
|
|
1437
1624
|
break;
|
|
@@ -1574,7 +1761,11 @@ var Tokenizer = class {
|
|
|
1574
1761
|
}
|
|
1575
1762
|
const end = singleDollarMathEnd(text, i, pe);
|
|
1576
1763
|
this.tick(end > 0 ? end - i : Math.min(403, pe - i));
|
|
1577
|
-
if (end > 0 &&
|
|
1764
|
+
if (end > 0 && this.streaming && end === this.n) {
|
|
1765
|
+
this.provisionalFrom = Math.min(this.provisionalFrom, i);
|
|
1766
|
+
return { inlines, breakIsland: null, orphan: false };
|
|
1767
|
+
}
|
|
1768
|
+
if (end > 0) {
|
|
1578
1769
|
inlines.push(this.island("math_inline", i, end, true, { delimiter: "$" }));
|
|
1579
1770
|
i = end;
|
|
1580
1771
|
continue;
|
|
@@ -2077,6 +2268,8 @@ exports.blockRangeEdit = blockRangeEdit;
|
|
|
2077
2268
|
exports.buildCodePointIndex = buildCodePointIndex;
|
|
2078
2269
|
exports.classifyInnerFenceLine = classifyInnerFenceLine;
|
|
2079
2270
|
exports.fenceNestsInnerFences = fenceNestsInnerFences;
|
|
2271
|
+
exports.findCodeRanges = findCodeRanges;
|
|
2272
|
+
exports.isMathPlaceholder = isMathPlaceholder;
|
|
2080
2273
|
exports.isSingleDollarMath = isSingleDollarMath;
|
|
2081
2274
|
exports.islandEdit = islandEdit;
|
|
2082
2275
|
exports.joinSource = joinSource;
|