@ai-matrx/content-ir 0.17.0 → 0.18.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 +40 -1
- package/dist/index.cjs +377 -295
- 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 +377 -296
- package/dist/index.js.map +1 -1
- package/dist/source.cjs +377 -295
- package/dist/source.cjs.map +1 -1
- package/dist/source.d.cts +44 -27
- package/dist/source.d.ts +44 -27
- package/dist/source.js +377 -296
- package/dist/source.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -5227,75 +5227,231 @@ function classifyInnerFenceLine(trimmed, openTicks, nests, nestedDepth) {
|
|
|
5227
5227
|
return "content";
|
|
5228
5228
|
}
|
|
5229
5229
|
|
|
5230
|
-
// source/
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
"
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
"lim",
|
|
5245
|
-
"max",
|
|
5246
|
-
"min",
|
|
5247
|
-
"det",
|
|
5248
|
-
"gcd",
|
|
5249
|
-
"mod",
|
|
5250
|
-
"arg",
|
|
5251
|
-
"sinh",
|
|
5252
|
-
"cosh",
|
|
5253
|
-
"tanh"
|
|
5254
|
-
]);
|
|
5255
|
-
function isMathShape(content) {
|
|
5256
|
-
if (!MATH_SHAPE_CHARS.test(content)) return false;
|
|
5257
|
-
const words = content.match(/[A-Za-z]+/g);
|
|
5258
|
-
if (!words) return false;
|
|
5259
|
-
if (!words.every((w) => w.length === 1 || FUNCTION_NAMES.has(w))) return false;
|
|
5260
|
-
if (/[A-Za-z]'+[A-Za-z]/.test(content) || /(?:^|[\s(,])[A-Za-z]\.(?:[A-Za-z]\.|\s|$)/.test(content)) return false;
|
|
5261
|
-
return /[A-Za-z]'*\(|[A-Za-z]'|\b[A-Za-z]\s+[A-Za-z]\b|\([^)]*[A-Za-z][^)]*\)/.test(content);
|
|
5230
|
+
// source/code-ranges.ts
|
|
5231
|
+
function fenceOpenerOf(content) {
|
|
5232
|
+
const t = content.trimStart();
|
|
5233
|
+
if (t.startsWith("```")) {
|
|
5234
|
+
let ticks = 0;
|
|
5235
|
+
while (ticks < t.length && t[ticks] === "`") ticks++;
|
|
5236
|
+
return { char: "`", ticks, lang: parseFenceOpener(t)?.lang ?? "" };
|
|
5237
|
+
}
|
|
5238
|
+
if (content.length - t.length <= 3 && t.startsWith("~~~")) {
|
|
5239
|
+
const open = /^(~{3,})(.*)$/.exec(t);
|
|
5240
|
+
if (!open) return null;
|
|
5241
|
+
return { char: "~", ticks: open[1].length, lang: open[2].trim().split(/\s/)[0] ?? "" };
|
|
5242
|
+
}
|
|
5243
|
+
return null;
|
|
5262
5244
|
}
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5245
|
+
var FenceReader = class {
|
|
5246
|
+
constructor(opener, options = {}) {
|
|
5247
|
+
this.opener = opener;
|
|
5248
|
+
this.isJson = opener.char === "`" && opener.lang === "json";
|
|
5249
|
+
this.nesting = opener.char === "`" && (options.nesting ?? fenceNestsInnerFences(opener.lang));
|
|
5250
|
+
this.tildeCloser = opener.char === "~" ? new RegExp(`^ {0,3}~{${opener.ticks},}[ \\t]*$`) : null;
|
|
5251
|
+
}
|
|
5252
|
+
opener;
|
|
5253
|
+
state = { inString: false, escaped: false };
|
|
5254
|
+
depth = 0;
|
|
5255
|
+
/** A nested fence was opened at some point. */
|
|
5256
|
+
sawNested = false;
|
|
5257
|
+
isJson;
|
|
5258
|
+
nesting;
|
|
5259
|
+
tildeCloser;
|
|
5260
|
+
/** How many nested fences are open right now. */
|
|
5261
|
+
get nestedDepth() {
|
|
5262
|
+
return this.depth;
|
|
5263
|
+
}
|
|
5264
|
+
feed(line) {
|
|
5265
|
+
if (this.tildeCloser) return this.tildeCloser.test(line);
|
|
5266
|
+
const trimmedLine = trimFenceLine(line);
|
|
5267
|
+
const at = line.indexOf("```");
|
|
5268
|
+
if (at === -1) {
|
|
5269
|
+
if (this.isJson) this.state = jsonStringState(line, 0, line.length, this.state);
|
|
5270
|
+
return false;
|
|
5271
|
+
}
|
|
5272
|
+
if (this.isJson) {
|
|
5273
|
+
const probe = jsonStringState(line, 0, at, this.state);
|
|
5274
|
+
if (probe.inString) {
|
|
5275
|
+
this.state = jsonStringState(line, at, line.length, probe);
|
|
5276
|
+
return false;
|
|
5277
|
+
}
|
|
5278
|
+
}
|
|
5279
|
+
if (trimmedLine.startsWith("```")) {
|
|
5280
|
+
const kind = classifyInnerFenceLine(trimmedLine, this.opener.ticks, this.nesting, this.depth);
|
|
5281
|
+
if (kind === "close-outer") return true;
|
|
5282
|
+
if (kind === "open-nested") {
|
|
5283
|
+
this.depth++;
|
|
5284
|
+
this.sawNested = true;
|
|
5285
|
+
}
|
|
5286
|
+
if (kind === "close-nested") this.depth--;
|
|
5287
|
+
} else {
|
|
5288
|
+
const closeTicks = backtickRunLength(line, at);
|
|
5289
|
+
const after = trimFenceLine(line.slice(at + closeTicks));
|
|
5290
|
+
if (closeTicks >= this.opener.ticks && after === "" && this.depth === 0) return true;
|
|
5291
|
+
}
|
|
5292
|
+
if (this.isJson) this.state = jsonStringState(line, 0, line.length, this.state);
|
|
5293
|
+
return false;
|
|
5294
|
+
}
|
|
5295
|
+
};
|
|
5296
|
+
function closeFence(src, open, opener) {
|
|
5297
|
+
const first = readFence(src, open, new FenceReader(opener));
|
|
5298
|
+
if (first.closed || !first.reader.sawNested || first.reader.nestedDepth <= 0) return { line: first.line, closed: first.closed };
|
|
5299
|
+
const strict = readFence(src, open, new FenceReader(opener, { nesting: false }));
|
|
5300
|
+
return { line: strict.line, closed: strict.closed };
|
|
5270
5301
|
}
|
|
5271
|
-
function
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
if (
|
|
5277
|
-
|
|
5278
|
-
|
|
5302
|
+
function readFence(src, open, reader) {
|
|
5303
|
+
for (let k = open + 1; k < src.count; k++) {
|
|
5304
|
+
if (src.openTail?.(k)) continue;
|
|
5305
|
+
const line = src.line(k);
|
|
5306
|
+
if (line === null) return { line: k - 1, closed: false, reader };
|
|
5307
|
+
if (reader.feed(line)) return { line: k, closed: true, reader };
|
|
5308
|
+
}
|
|
5309
|
+
return { line: src.count - 1, closed: false, reader };
|
|
5310
|
+
}
|
|
5311
|
+
function jsonStringState(line, from, upTo, state) {
|
|
5312
|
+
let { inString, escaped } = state;
|
|
5313
|
+
for (let idx = from; idx < upTo; idx++) {
|
|
5314
|
+
const ch = line[idx];
|
|
5315
|
+
if (escaped) {
|
|
5316
|
+
escaped = false;
|
|
5279
5317
|
continue;
|
|
5280
5318
|
}
|
|
5281
|
-
if (
|
|
5282
|
-
|
|
5283
|
-
|
|
5319
|
+
if (ch === "\\" && inString) {
|
|
5320
|
+
escaped = true;
|
|
5321
|
+
continue;
|
|
5284
5322
|
}
|
|
5323
|
+
if (ch === '"') inString = !inString;
|
|
5285
5324
|
}
|
|
5286
|
-
|
|
5287
|
-
const content = text.slice(open + 1, close);
|
|
5288
|
-
return isSingleDollarMath(content, text[close + 1]) ? close + 1 : -1;
|
|
5325
|
+
return { inString, escaped };
|
|
5289
5326
|
}
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5327
|
+
function backtickRunLength(str2, pos) {
|
|
5328
|
+
let n = 0;
|
|
5329
|
+
while (pos + n < str2.length && str2[pos + n] === "`") n++;
|
|
5330
|
+
return n;
|
|
5331
|
+
}
|
|
5332
|
+
function quotePrefix(line) {
|
|
5333
|
+
let depth = 0;
|
|
5334
|
+
let offset = 0;
|
|
5335
|
+
for (; ; ) {
|
|
5336
|
+
const m = /^ {0,3}> ?/.exec(line.slice(offset));
|
|
5337
|
+
if (!m) return { depth, offset };
|
|
5338
|
+
depth++;
|
|
5339
|
+
offset += m[0].length;
|
|
5340
|
+
}
|
|
5341
|
+
}
|
|
5342
|
+
function stripQuotes(line, depth) {
|
|
5343
|
+
let offset = 0;
|
|
5344
|
+
for (let d = 0; d < depth; d++) {
|
|
5345
|
+
const m = /^ {0,3}> ?/.exec(line.slice(offset));
|
|
5346
|
+
if (!m) return null;
|
|
5347
|
+
offset += m[0].length;
|
|
5348
|
+
}
|
|
5349
|
+
return line.slice(offset);
|
|
5350
|
+
}
|
|
5351
|
+
var LIST_ITEM = /^( *)([-*+]|\d{1,9}[.)])( +|\t|$)/;
|
|
5352
|
+
function leadingSpaces(s) {
|
|
5353
|
+
let i = 0;
|
|
5354
|
+
while (i < s.length && s[i] === " ") i++;
|
|
5355
|
+
return i;
|
|
5356
|
+
}
|
|
5357
|
+
function scan(text) {
|
|
5358
|
+
const starts = [];
|
|
5359
|
+
const ends = [];
|
|
5360
|
+
for (let pos = 0; ; ) {
|
|
5361
|
+
const nl = text.indexOf("\n", pos);
|
|
5362
|
+
const lineEnd = nl === -1 ? text.length : nl;
|
|
5363
|
+
starts.push(pos);
|
|
5364
|
+
ends.push(lineEnd > pos && text.charCodeAt(lineEnd - 1) === 13 ? lineEnd - 1 : lineEnd);
|
|
5365
|
+
if (nl === -1) break;
|
|
5366
|
+
pos = nl + 1;
|
|
5367
|
+
}
|
|
5368
|
+
const count = starts.length;
|
|
5369
|
+
const raw = (k) => text.slice(starts[k], ends[k]);
|
|
5370
|
+
const out = { ranges: [], paragraphs: [], endsInFence: false, pendingPara: -1 };
|
|
5371
|
+
const rawLines = { count, line: raw };
|
|
5372
|
+
let segment = 0;
|
|
5373
|
+
for (let k = 0; k < count; k++) {
|
|
5374
|
+
const opener = fenceOpenerOf(raw(k));
|
|
5375
|
+
if (!opener || opener.char !== "`") continue;
|
|
5376
|
+
prose(text, starts, ends, raw, segment, k, out);
|
|
5377
|
+
const end = closeFence(rawLines, k, opener);
|
|
5378
|
+
out.ranges.push({ start: starts[k], end: ends[end.line], kind: "fence" });
|
|
5379
|
+
out.pendingPara = -1;
|
|
5380
|
+
if (!end.closed && end.line === count - 1) out.endsInFence = true;
|
|
5381
|
+
k = end.line;
|
|
5382
|
+
segment = k + 1;
|
|
5383
|
+
}
|
|
5384
|
+
prose(text, starts, ends, raw, segment, count, out);
|
|
5385
|
+
return out;
|
|
5386
|
+
}
|
|
5387
|
+
function prose(text, starts, ends, raw, from, to, out) {
|
|
5296
5388
|
let para = -1;
|
|
5297
|
-
|
|
5298
|
-
|
|
5389
|
+
let quoteDepth = 0;
|
|
5390
|
+
let lists = [];
|
|
5391
|
+
const closePara = (at) => {
|
|
5392
|
+
if (para !== -1) out.paragraphs.push([para, at]);
|
|
5393
|
+
para = -1;
|
|
5394
|
+
};
|
|
5395
|
+
for (let k = from; k < to; k++) {
|
|
5396
|
+
const line = raw(k);
|
|
5397
|
+
const { depth, offset } = quotePrefix(line);
|
|
5398
|
+
if (depth !== quoteDepth) {
|
|
5399
|
+
quoteDepth = depth;
|
|
5400
|
+
lists = [];
|
|
5401
|
+
}
|
|
5402
|
+
let content = line.slice(offset);
|
|
5403
|
+
if (content.trim() === "") {
|
|
5404
|
+
closePara(starts[k]);
|
|
5405
|
+
if (!(k === starts.length - 1 && line === "")) out.pendingPara = -1;
|
|
5406
|
+
continue;
|
|
5407
|
+
}
|
|
5408
|
+
const indent = leadingSpaces(content);
|
|
5409
|
+
while (lists.length && indent < lists[lists.length - 1]) lists.pop();
|
|
5410
|
+
const item = LIST_ITEM.exec(content);
|
|
5411
|
+
let column = lists.length ? lists[lists.length - 1] : 0;
|
|
5412
|
+
if (item) {
|
|
5413
|
+
const gap = item[3].length;
|
|
5414
|
+
column = item[1].length + item[2].length + (gap >= 1 && gap <= 4 ? gap : 1);
|
|
5415
|
+
lists.push(column);
|
|
5416
|
+
content = content.slice(Math.min(column, content.length));
|
|
5417
|
+
} else {
|
|
5418
|
+
content = content.slice(Math.min(indent, column));
|
|
5419
|
+
}
|
|
5420
|
+
const opener = fenceOpenerOf(content);
|
|
5421
|
+
if (!opener) {
|
|
5422
|
+
if (para === -1) para = starts[k];
|
|
5423
|
+
if (out.pendingPara === -1) out.pendingPara = starts[k];
|
|
5424
|
+
continue;
|
|
5425
|
+
}
|
|
5426
|
+
closePara(starts[k]);
|
|
5427
|
+
out.pendingPara = -1;
|
|
5428
|
+
const col = column;
|
|
5429
|
+
const src = {
|
|
5430
|
+
count: to,
|
|
5431
|
+
line: (j) => {
|
|
5432
|
+
const inner = stripQuotes(raw(j), depth);
|
|
5433
|
+
if (inner === null) return null;
|
|
5434
|
+
if (opener.char === "~" && col > 0) {
|
|
5435
|
+
const ind = leadingSpaces(inner);
|
|
5436
|
+
if (inner.trim() !== "" && ind < col) return null;
|
|
5437
|
+
return inner.slice(Math.min(ind, col));
|
|
5438
|
+
}
|
|
5439
|
+
return inner;
|
|
5440
|
+
}
|
|
5441
|
+
};
|
|
5442
|
+
const end = closeFence(src, k, opener);
|
|
5443
|
+
out.ranges.push({ start: starts[k], end: ends[end.line], kind: "fence" });
|
|
5444
|
+
if (!end.closed && end.line === starts.length - 1) out.endsInFence = true;
|
|
5445
|
+
k = end.line;
|
|
5446
|
+
}
|
|
5447
|
+
closePara(to < starts.length ? starts[to] : text.length);
|
|
5448
|
+
}
|
|
5449
|
+
var BacktickRuns = class {
|
|
5450
|
+
/** Every run, in order: [start, length]. */
|
|
5451
|
+
all = [];
|
|
5452
|
+
byLength = /* @__PURE__ */ new Map();
|
|
5453
|
+
indexOf = /* @__PURE__ */ new Map();
|
|
5454
|
+
constructor(text, from, to) {
|
|
5299
5455
|
for (let k = from; k < to; ) {
|
|
5300
5456
|
if (text.charCodeAt(k) !== 96) {
|
|
5301
5457
|
k++;
|
|
@@ -5303,117 +5459,57 @@ function findCodeRanges(text) {
|
|
|
5303
5459
|
}
|
|
5304
5460
|
let len = 1;
|
|
5305
5461
|
while (k + len < to && text.charCodeAt(k + len) === 96) len++;
|
|
5306
|
-
|
|
5462
|
+
this.indexOf.set(k, this.all.length);
|
|
5463
|
+
this.all.push([k, len]);
|
|
5464
|
+
const list = this.byLength.get(len);
|
|
5465
|
+
if (list) list.push(k);
|
|
5466
|
+
else this.byLength.set(len, [k]);
|
|
5307
5467
|
k += len;
|
|
5308
5468
|
}
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
const
|
|
5318
|
-
if (
|
|
5319
|
-
|
|
5320
|
-
continue;
|
|
5321
|
-
}
|
|
5322
|
-
const [s0] = runs[r];
|
|
5323
|
-
const [s1, l1] = runs[j];
|
|
5324
|
-
ranges.push({ start: s0, end: s1 + l1, kind: "span" });
|
|
5325
|
-
r = j + 1;
|
|
5469
|
+
}
|
|
5470
|
+
/** Start of the first run of exactly `n` backticks at or after `after`, or -1. */
|
|
5471
|
+
next(n, after) {
|
|
5472
|
+
const list = this.byLength.get(n);
|
|
5473
|
+
if (!list) return -1;
|
|
5474
|
+
let lo = 0;
|
|
5475
|
+
let hi = list.length;
|
|
5476
|
+
while (lo < hi) {
|
|
5477
|
+
const mid = lo + hi >>> 1;
|
|
5478
|
+
if (list[mid] < after) lo = mid + 1;
|
|
5479
|
+
else hi = mid;
|
|
5326
5480
|
}
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
else if (kind === "close-nested") fence.depth--;
|
|
5343
|
-
else if (kind === "close-outer") closes = indent <= 3;
|
|
5344
|
-
} else {
|
|
5345
|
-
let t = 0;
|
|
5346
|
-
while (t < trimmed.length && trimmed[t] === "~") t++;
|
|
5347
|
-
closes = indent <= 3 && t >= fence.len && trimFenceLine(trimmed.slice(t)) === "";
|
|
5348
|
-
}
|
|
5349
|
-
if (closes) {
|
|
5350
|
-
ranges.push({ start: fence.start, end: lineEnd, kind: "fence" });
|
|
5351
|
-
fence = null;
|
|
5352
|
-
}
|
|
5353
|
-
} else {
|
|
5354
|
-
const opener = indent <= 3 ? /^(`{3,}|~{3,})(.*)$/.exec(body) : null;
|
|
5355
|
-
const info = opener ? opener[2] : "";
|
|
5356
|
-
if (opener && !(opener[1][0] === "`" && info.includes("`"))) {
|
|
5357
|
-
if (para !== -1) spans(para, pos);
|
|
5358
|
-
para = -1;
|
|
5359
|
-
const char = opener[1][0];
|
|
5360
|
-
const parsed = char === "`" ? parseFenceOpener(line) : null;
|
|
5361
|
-
fence = { char, len: opener[1].length, start: pos, nests: fenceNestsInnerFences(parsed?.lang), depth: 0 };
|
|
5362
|
-
} else if (body.trim() === "") {
|
|
5363
|
-
if (para !== -1) spans(para, pos);
|
|
5364
|
-
para = -1;
|
|
5365
|
-
} else if (para === -1) para = pos;
|
|
5481
|
+
return list[lo] ?? -1;
|
|
5482
|
+
}
|
|
5483
|
+
/** Index of the run starting at `start` in `all`. */
|
|
5484
|
+
index(start) {
|
|
5485
|
+
return this.indexOf.get(start) ?? -1;
|
|
5486
|
+
}
|
|
5487
|
+
};
|
|
5488
|
+
function codeSpans(text, from, to, out) {
|
|
5489
|
+
const runs = new BacktickRuns(text, from, to);
|
|
5490
|
+
for (let r = 0; r < runs.all.length; ) {
|
|
5491
|
+
const [start, n] = runs.all[r];
|
|
5492
|
+
const close = runs.next(n, start + n);
|
|
5493
|
+
if (close === -1) {
|
|
5494
|
+
r++;
|
|
5495
|
+
continue;
|
|
5366
5496
|
}
|
|
5367
|
-
|
|
5368
|
-
|
|
5497
|
+
out.push({ start, end: close + n, kind: "span" });
|
|
5498
|
+
r = runs.index(close) + 1;
|
|
5369
5499
|
}
|
|
5370
|
-
|
|
5371
|
-
|
|
5500
|
+
}
|
|
5501
|
+
function findCodeRanges(text) {
|
|
5502
|
+
const s = scan(text);
|
|
5503
|
+
const ranges = [...s.ranges];
|
|
5504
|
+
for (const [from, to] of s.paragraphs) codeSpans(text, from, to, ranges);
|
|
5372
5505
|
return ranges.sort((a, b) => a.start - b.start);
|
|
5373
5506
|
}
|
|
5374
5507
|
function pendingCodeSpanStart(text) {
|
|
5375
5508
|
const n = text.length;
|
|
5376
5509
|
if (n === 0 || /\n[ \t]*\n[ \t]*$/.test(text)) return -1;
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
while (pos <= n) {
|
|
5381
|
-
const nl = text.indexOf("\n", pos);
|
|
5382
|
-
const lineEnd = nl === -1 ? n : nl;
|
|
5383
|
-
const line = text.slice(pos, lineEnd);
|
|
5384
|
-
let indent = 0;
|
|
5385
|
-
while (indent < line.length && line[indent] === " ") indent++;
|
|
5386
|
-
const body = line.slice(indent);
|
|
5387
|
-
if (fence) {
|
|
5388
|
-
const trimmed = trimFenceLine(line);
|
|
5389
|
-
let closes = false;
|
|
5390
|
-
if (fence.char === "`") {
|
|
5391
|
-
const kind = classifyInnerFenceLine(trimmed, fence.len, fence.nests, fence.depth);
|
|
5392
|
-
if (kind === "open-nested") fence.depth++;
|
|
5393
|
-
else if (kind === "close-nested") fence.depth--;
|
|
5394
|
-
else if (kind === "close-outer") closes = indent <= 3;
|
|
5395
|
-
} else {
|
|
5396
|
-
let t = 0;
|
|
5397
|
-
while (t < trimmed.length && trimmed[t] === "~") t++;
|
|
5398
|
-
closes = indent <= 3 && t >= fence.len && trimFenceLine(trimmed.slice(t)) === "";
|
|
5399
|
-
}
|
|
5400
|
-
if (closes) fence = null;
|
|
5401
|
-
} else {
|
|
5402
|
-
const opener = indent <= 3 ? /^(`{3,}|~{3,})(.*)$/.exec(body) : null;
|
|
5403
|
-
const info = opener ? opener[2] : "";
|
|
5404
|
-
if (opener && !(opener[1][0] === "`" && info.includes("`"))) {
|
|
5405
|
-
para = -1;
|
|
5406
|
-
const char = opener[1][0];
|
|
5407
|
-
const parsed = char === "`" ? parseFenceOpener(line) : null;
|
|
5408
|
-
fence = { char, len: opener[1].length, nests: fenceNestsInnerFences(parsed?.lang), depth: 0 };
|
|
5409
|
-
} else if (body.trim() === "") {
|
|
5410
|
-
if (!(nl === -1 && line === "")) para = -1;
|
|
5411
|
-
} else if (para === -1) para = pos;
|
|
5412
|
-
}
|
|
5413
|
-
if (nl === -1) break;
|
|
5414
|
-
pos = nl + 1;
|
|
5415
|
-
}
|
|
5416
|
-
if (fence || para === -1) return -1;
|
|
5510
|
+
const s = scan(text);
|
|
5511
|
+
const para = s.pendingPara;
|
|
5512
|
+
if (s.endsInFence || para === -1) return -1;
|
|
5417
5513
|
const runs = [];
|
|
5418
5514
|
for (let k = para; k < n; ) {
|
|
5419
5515
|
if (text.charCodeAt(k) !== 96) {
|
|
@@ -5550,6 +5646,83 @@ function pairDisplayMath(text) {
|
|
|
5550
5646
|
return pairs;
|
|
5551
5647
|
}
|
|
5552
5648
|
|
|
5649
|
+
// source/math.ts
|
|
5650
|
+
var TEX_SIGNAL = /\\[A-Za-z]+|[\\^_{}=<>+]/;
|
|
5651
|
+
var LONE_VARIABLE = /^[A-Za-z](?:'|[0-9])?$/;
|
|
5652
|
+
var MATH_SHAPE_CHARS = /^[A-Za-z0-9'\s(),.*\/-]+$/;
|
|
5653
|
+
function isSingleDollarMath(content, after) {
|
|
5654
|
+
if (!content || content.length > 400) return false;
|
|
5655
|
+
if (/^\s/.test(content) || /\s$/.test(content)) return false;
|
|
5656
|
+
if (after !== void 0 && /[0-9]/.test(after)) return false;
|
|
5657
|
+
if (/(?:^|[^\\])%/.test(content)) return false;
|
|
5658
|
+
if (/^[)\]}"/]/.test(content) || /[(\[{":;,/]$/.test(content)) return false;
|
|
5659
|
+
if (/^[0-9]/.test(content) && after !== void 0 && /[A-Za-z]/.test(after)) return false;
|
|
5660
|
+
if (isMathPlaceholder(content)) return false;
|
|
5661
|
+
return TEX_SIGNAL.test(content) || !readsAsProse(content);
|
|
5662
|
+
}
|
|
5663
|
+
var FUNCTION_NAMES = /* @__PURE__ */ new Set([
|
|
5664
|
+
"sin",
|
|
5665
|
+
"cos",
|
|
5666
|
+
"tan",
|
|
5667
|
+
"sec",
|
|
5668
|
+
"csc",
|
|
5669
|
+
"cot",
|
|
5670
|
+
"log",
|
|
5671
|
+
"ln",
|
|
5672
|
+
"exp",
|
|
5673
|
+
"lim",
|
|
5674
|
+
"max",
|
|
5675
|
+
"min",
|
|
5676
|
+
"det",
|
|
5677
|
+
"gcd",
|
|
5678
|
+
"mod",
|
|
5679
|
+
"arg",
|
|
5680
|
+
"sinh",
|
|
5681
|
+
"cosh",
|
|
5682
|
+
"tanh"
|
|
5683
|
+
]);
|
|
5684
|
+
function readsAsProse(content) {
|
|
5685
|
+
if (/[A-Za-z]'[a-z]/.test(content)) return true;
|
|
5686
|
+
if (/(?:^|[\s(,])[A-Za-z]\.(?:[A-Za-z]\.|\s|$)/.test(content)) return true;
|
|
5687
|
+
if (!/\s/.test(content)) return false;
|
|
5688
|
+
const words = (content.match(/[A-Za-z]{3,}/g) ?? []).filter((w) => !FUNCTION_NAMES.has(w.toLowerCase()));
|
|
5689
|
+
return words.length >= 2;
|
|
5690
|
+
}
|
|
5691
|
+
function looksLikeOpenInlineMath(partial) {
|
|
5692
|
+
if (!partial || partial.length > 400) return false;
|
|
5693
|
+
if (/^\s/.test(partial) || /\s$/.test(partial)) return false;
|
|
5694
|
+
if (LONE_VARIABLE.test(partial)) return true;
|
|
5695
|
+
if (/^[0-9]/.test(partial)) return /\\[A-Za-z]+|[\\^_{}]/.test(partial);
|
|
5696
|
+
return TEX_SIGNAL.test(partial) || isMathShape(partial);
|
|
5697
|
+
}
|
|
5698
|
+
function isMathShape(content) {
|
|
5699
|
+
if (!MATH_SHAPE_CHARS.test(content)) return false;
|
|
5700
|
+
const words = content.match(/[A-Za-z]+/g);
|
|
5701
|
+
if (!words) return false;
|
|
5702
|
+
if (!words.every((w) => w.length === 1 || FUNCTION_NAMES.has(w))) return false;
|
|
5703
|
+
if (/[A-Za-z]'+[A-Za-z]/.test(content) || /(?:^|[\s(,])[A-Za-z]\.(?:[A-Za-z]\.|\s|$)/.test(content)) return false;
|
|
5704
|
+
return /[A-Za-z]'*\(|[A-Za-z]'|\b[A-Za-z]\s+[A-Za-z]\b|\([^)]*[A-Za-z][^)]*\)/.test(content);
|
|
5705
|
+
}
|
|
5706
|
+
function singleDollarMathEnd(text, open, limit = text.length) {
|
|
5707
|
+
const bound = Math.min(limit, open + 403);
|
|
5708
|
+
let close = -1;
|
|
5709
|
+
for (let k = open + 1; k < bound; k += 1) {
|
|
5710
|
+
const c = text[k];
|
|
5711
|
+
if (c === "\n") break;
|
|
5712
|
+
if (c === "\\") {
|
|
5713
|
+
k += 1;
|
|
5714
|
+
continue;
|
|
5715
|
+
}
|
|
5716
|
+
if (c === "$") {
|
|
5717
|
+
close = k;
|
|
5718
|
+
break;
|
|
5719
|
+
}
|
|
5720
|
+
}
|
|
5721
|
+
if (close === -1 || text[close + 1] === "$") return -1;
|
|
5722
|
+
const content = text.slice(open + 1, close);
|
|
5723
|
+
return isSingleDollarMath(content, text[close + 1]) ? close + 1 : -1;
|
|
5724
|
+
}
|
|
5725
|
+
|
|
5553
5726
|
// source/xml-tag.ts
|
|
5554
5727
|
var XML_NAME_START = /[A-Za-z_]/;
|
|
5555
5728
|
var XML_NAME_CHARACTER = /[\w.:-]/;
|
|
@@ -5842,27 +6015,6 @@ function isUnclosedGenericXmlOpening(source) {
|
|
|
5842
6015
|
}
|
|
5843
6016
|
return true;
|
|
5844
6017
|
}
|
|
5845
|
-
function jsonStringState(line, from, upTo, state) {
|
|
5846
|
-
let { inString, escaped } = state;
|
|
5847
|
-
for (let idx = from; idx < upTo; idx++) {
|
|
5848
|
-
const ch = line[idx];
|
|
5849
|
-
if (escaped) {
|
|
5850
|
-
escaped = false;
|
|
5851
|
-
continue;
|
|
5852
|
-
}
|
|
5853
|
-
if (ch === "\\" && inString) {
|
|
5854
|
-
escaped = true;
|
|
5855
|
-
continue;
|
|
5856
|
-
}
|
|
5857
|
-
if (ch === '"') inString = !inString;
|
|
5858
|
-
}
|
|
5859
|
-
return { inString, escaped };
|
|
5860
|
-
}
|
|
5861
|
-
function backtickRunLength(str2, pos) {
|
|
5862
|
-
let n = 0;
|
|
5863
|
-
while (pos + n < str2.length && str2[pos + n] === "`") n++;
|
|
5864
|
-
return n;
|
|
5865
|
-
}
|
|
5866
6018
|
function isSplitterTreeLine(line) {
|
|
5867
6019
|
return TREE_GLYPHS.test(line) || /^[\s│|]*[├└+|][\s─\-]+/.test(line);
|
|
5868
6020
|
}
|
|
@@ -6094,11 +6246,9 @@ var Tokenizer = class {
|
|
|
6094
6246
|
const footnote = this.footnoteDefinition(p, li, t);
|
|
6095
6247
|
if (footnote) return footnote;
|
|
6096
6248
|
}
|
|
6097
|
-
|
|
6098
|
-
if (
|
|
6099
|
-
|
|
6100
|
-
if (tilde) return tilde;
|
|
6101
|
-
}
|
|
6249
|
+
const fence = fenceOpenerOf(seg);
|
|
6250
|
+
if (fence?.char === "`") return this.backtickFence(p, li, fence);
|
|
6251
|
+
if (fence?.char === "~") return this.tildeFence(p, li, fence);
|
|
6102
6252
|
if (t.startsWith("$$")) {
|
|
6103
6253
|
const math = this.mathBlock(p, tp);
|
|
6104
6254
|
if (math) return math;
|
|
@@ -6253,74 +6403,31 @@ var Tokenizer = class {
|
|
|
6253
6403
|
heldFootnote(p, id) {
|
|
6254
6404
|
return this.island("footnote_def", p, this.n, false, { id });
|
|
6255
6405
|
}
|
|
6406
|
+
/** The text's lines as the one fence closer reads them (streaming: the open tail closes nothing). */
|
|
6407
|
+
get fenceLines() {
|
|
6408
|
+
return {
|
|
6409
|
+
count: this.lineCount,
|
|
6410
|
+
line: (k) => this.lineText(k),
|
|
6411
|
+
openTail: (k) => this.isOpenTail(k)
|
|
6412
|
+
};
|
|
6413
|
+
}
|
|
6256
6414
|
/**
|
|
6257
|
-
* Backtick fence —
|
|
6258
|
-
*
|
|
6259
|
-
*
|
|
6260
|
-
* still open at the end of the text.
|
|
6415
|
+
* Backtick fence — THE one closer (`closeFence`, source/code-ranges.ts): the
|
|
6416
|
+
* nested-fence rule for markdown fences with the strict-CommonMark retry, the
|
|
6417
|
+
* renderer's line-end closer, JSON-string awareness for ```json.
|
|
6261
6418
|
*/
|
|
6262
|
-
backtickFence(p, li,
|
|
6263
|
-
const
|
|
6264
|
-
const lang = parseFenceOpener(t)?.lang ?? "";
|
|
6419
|
+
backtickFence(p, li, opener) {
|
|
6420
|
+
const lang = opener.lang;
|
|
6265
6421
|
const isJson = lang === "json";
|
|
6266
6422
|
const normalized = normalizeFenceLanguage(lang);
|
|
6267
|
-
const meta = { fence: "`", ticks:
|
|
6423
|
+
const meta = { fence: "`", ticks: opener.ticks, lang };
|
|
6268
6424
|
if (normalized && SPECIAL_CODE_LANGUAGES.has(normalized)) meta.special = normalized;
|
|
6269
|
-
const
|
|
6270
|
-
|
|
6271
|
-
|
|
6272
|
-
if (typeof close === "number") {
|
|
6273
|
-
return this.fenceIsland(p, this.contentEnds[close], true, meta, li, close, isJson);
|
|
6425
|
+
const end = closeFence(this.fenceLines, li, opener);
|
|
6426
|
+
if (end.closed) {
|
|
6427
|
+
return this.fenceIsland(p, this.contentEnds[end.line], true, meta, li, end.line, isJson);
|
|
6274
6428
|
}
|
|
6275
6429
|
return this.fenceIsland(p, this.n, false, meta, li, this.lineCount, isJson);
|
|
6276
6430
|
}
|
|
6277
|
-
/** The closing line of a backtick fence opened on line `li`, or null when it never closes. */
|
|
6278
|
-
backtickFenceClose(li, openTicks, isJson, nesting) {
|
|
6279
|
-
let state = { inString: false, escaped: false };
|
|
6280
|
-
let nestedDepth = 0;
|
|
6281
|
-
let sawNested = false;
|
|
6282
|
-
for (let k = li + 1; k < this.lineCount; k++) {
|
|
6283
|
-
if (this.isOpenTail(k)) continue;
|
|
6284
|
-
const line = this.lineText(k);
|
|
6285
|
-
const trimmedLine = trimFenceLine(line);
|
|
6286
|
-
if (trimmedLine.startsWith("```")) {
|
|
6287
|
-
const at2 = line.indexOf("```");
|
|
6288
|
-
if (isJson) {
|
|
6289
|
-
const probe = jsonStringState(line, 0, at2, state);
|
|
6290
|
-
if (probe.inString) {
|
|
6291
|
-
state = jsonStringState(line, at2, line.length, probe);
|
|
6292
|
-
continue;
|
|
6293
|
-
}
|
|
6294
|
-
}
|
|
6295
|
-
const kind = classifyInnerFenceLine(trimmedLine, openTicks, nesting, nestedDepth);
|
|
6296
|
-
if (kind === "close-outer") return k;
|
|
6297
|
-
if (kind === "open-nested") {
|
|
6298
|
-
nestedDepth++;
|
|
6299
|
-
sawNested = true;
|
|
6300
|
-
}
|
|
6301
|
-
if (kind === "close-nested") nestedDepth--;
|
|
6302
|
-
if (isJson) state = jsonStringState(line, 0, line.length, state);
|
|
6303
|
-
continue;
|
|
6304
|
-
}
|
|
6305
|
-
const at = line.indexOf("```");
|
|
6306
|
-
if (at !== -1) {
|
|
6307
|
-
if (isJson) {
|
|
6308
|
-
const probe = jsonStringState(line, 0, at, state);
|
|
6309
|
-
if (probe.inString) {
|
|
6310
|
-
state = jsonStringState(line, at, line.length, probe);
|
|
6311
|
-
continue;
|
|
6312
|
-
}
|
|
6313
|
-
}
|
|
6314
|
-
const closeTicks = backtickRunLength(line, at);
|
|
6315
|
-
const after = trimFenceLine(line.slice(at + closeTicks));
|
|
6316
|
-
if (closeTicks >= openTicks && after === "" && nestedDepth === 0) return k;
|
|
6317
|
-
if (isJson) state = jsonStringState(line, 0, line.length, state);
|
|
6318
|
-
continue;
|
|
6319
|
-
}
|
|
6320
|
-
if (isJson) state = jsonStringState(line, 0, line.length, state);
|
|
6321
|
-
}
|
|
6322
|
-
return sawNested && nestedDepth > 0 ? "retry-strict" : null;
|
|
6323
|
-
}
|
|
6324
6431
|
fenceIsland(p, end, complete, meta, openLine, closeLine, isJson) {
|
|
6325
6432
|
if (isJson && openLine + 1 < this.lineCount) {
|
|
6326
6433
|
const bodyEnd = closeLine < this.lineCount ? this.lineStarts[closeLine] : this.n;
|
|
@@ -6329,22 +6436,16 @@ var Tokenizer = class {
|
|
|
6329
6436
|
}
|
|
6330
6437
|
return this.island("fence", p, end, complete, meta);
|
|
6331
6438
|
}
|
|
6332
|
-
tildeFence(p, li,
|
|
6333
|
-
const
|
|
6334
|
-
|
|
6335
|
-
const ticks = open[1].length;
|
|
6336
|
-
const lang = open[2].trim().split(/\s/)[0] ?? "";
|
|
6337
|
-
const meta = { fence: "~", ticks, lang };
|
|
6439
|
+
tildeFence(p, li, opener) {
|
|
6440
|
+
const lang = opener.lang;
|
|
6441
|
+
const meta = { fence: "~", ticks: opener.ticks, lang };
|
|
6338
6442
|
const normalized = normalizeFenceLanguage(lang);
|
|
6339
6443
|
if (normalized && SPECIAL_CODE_LANGUAGES.has(normalized)) meta.special = normalized;
|
|
6340
|
-
const close =
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
const end = this.rendererOverflow(li + 1, k, tildeEnd);
|
|
6346
|
-
return this.island("fence", p, end, end === this.n ? this.overflowComplete : true, meta);
|
|
6347
|
-
}
|
|
6444
|
+
const close = closeFence(this.fenceLines, li, opener);
|
|
6445
|
+
if (close.closed) {
|
|
6446
|
+
const tildeEnd = this.contentEnds[close.line];
|
|
6447
|
+
const end = this.rendererOverflow(li + 1, close.line, tildeEnd);
|
|
6448
|
+
return this.island("fence", p, end, end === this.n ? this.overflowComplete : true, meta);
|
|
6348
6449
|
}
|
|
6349
6450
|
return this.island("fence", p, this.n, false, meta);
|
|
6350
6451
|
}
|
|
@@ -6364,7 +6465,7 @@ var Tokenizer = class {
|
|
|
6364
6465
|
for (let j = firstLine; j <= closeLine && j < this.lineCount; j++) {
|
|
6365
6466
|
const start = this.lineStarts[j];
|
|
6366
6467
|
if (this.lineIsBlank(j)) continue;
|
|
6367
|
-
if (this.lineText(j)
|
|
6468
|
+
if (fenceOpenerOf(this.lineText(j))?.char === "~") continue;
|
|
6368
6469
|
const inner = this.detectBlockUncached(start, j, false);
|
|
6369
6470
|
if (!inner) continue;
|
|
6370
6471
|
if (inner.end > end) {
|
|
@@ -6612,9 +6713,9 @@ var Tokenizer = class {
|
|
|
6612
6713
|
const tree = { ...breakIsland, start: treeStart };
|
|
6613
6714
|
if (treeStart > pos) {
|
|
6614
6715
|
const proseEnd = this.contentEnds[root - 1];
|
|
6615
|
-
const
|
|
6616
|
-
if (!
|
|
6617
|
-
this.push({ kind: "prose", start: pos, end: proseEnd, island: null, inlines:
|
|
6716
|
+
const scan3 = this.scanInline(pos, proseEnd);
|
|
6717
|
+
if (!scan3.breakIsland) {
|
|
6718
|
+
this.push({ kind: "prose", start: pos, end: proseEnd, island: null, inlines: scan3.inlines });
|
|
6618
6719
|
this.push({ kind: "gap", start: proseEnd, end: treeStart, island: null, inlines: [] });
|
|
6619
6720
|
this.push({ kind: "island", start: treeStart, end: tree.end, island: tree, inlines: [] });
|
|
6620
6721
|
return tree.end;
|
|
@@ -6626,13 +6727,13 @@ var Tokenizer = class {
|
|
|
6626
6727
|
}
|
|
6627
6728
|
}
|
|
6628
6729
|
}
|
|
6629
|
-
const
|
|
6630
|
-
if (!
|
|
6631
|
-
this.push({ kind: "prose", start: pos, end, island: null, inlines:
|
|
6730
|
+
const scan2 = this.scanInline(pos, end);
|
|
6731
|
+
if (!scan2.breakIsland) {
|
|
6732
|
+
this.push({ kind: "prose", start: pos, end, island: null, inlines: scan2.inlines });
|
|
6632
6733
|
return end;
|
|
6633
6734
|
}
|
|
6634
|
-
const br =
|
|
6635
|
-
if (
|
|
6735
|
+
const br = scan2.breakIsland;
|
|
6736
|
+
if (scan2.orphan) {
|
|
6636
6737
|
let start = pos;
|
|
6637
6738
|
while (this.blocks.length) {
|
|
6638
6739
|
const last = this.blocks[this.blocks.length - 1];
|
|
@@ -6649,7 +6750,7 @@ var Tokenizer = class {
|
|
|
6649
6750
|
start: pos,
|
|
6650
6751
|
end: br.start,
|
|
6651
6752
|
island: null,
|
|
6652
|
-
inlines:
|
|
6753
|
+
inlines: scan2.inlines.filter((inline) => inline.end <= br.start)
|
|
6653
6754
|
});
|
|
6654
6755
|
this.push({ kind: "island", start: br.start, end: br.end, island: br, inlines: [] });
|
|
6655
6756
|
return br.end;
|
|
@@ -6669,30 +6770,10 @@ var Tokenizer = class {
|
|
|
6669
6770
|
const codeSpanClose = (n, from) => {
|
|
6670
6771
|
if (!runs) {
|
|
6671
6772
|
this.tick(pe - ps);
|
|
6672
|
-
runs =
|
|
6673
|
-
for (let k = ps; k < pe; ) {
|
|
6674
|
-
if (text.charCodeAt(k) !== 96) {
|
|
6675
|
-
k++;
|
|
6676
|
-
continue;
|
|
6677
|
-
}
|
|
6678
|
-
const len = backtickRunLength(text, k);
|
|
6679
|
-
const list2 = runs.get(len);
|
|
6680
|
-
if (list2) list2.push(k);
|
|
6681
|
-
else runs.set(len, [k]);
|
|
6682
|
-
k += len;
|
|
6683
|
-
}
|
|
6773
|
+
runs = new BacktickRuns(text, ps, pe);
|
|
6684
6774
|
}
|
|
6685
|
-
const
|
|
6686
|
-
|
|
6687
|
-
let lo = 0;
|
|
6688
|
-
let hi = list.length;
|
|
6689
|
-
while (lo < hi) {
|
|
6690
|
-
const mid = lo + hi >>> 1;
|
|
6691
|
-
if (list[mid] < from) lo = mid + 1;
|
|
6692
|
-
else hi = mid;
|
|
6693
|
-
}
|
|
6694
|
-
const at = list[lo];
|
|
6695
|
-
return at !== void 0 && at + n <= pe ? at : -1;
|
|
6775
|
+
const at = runs.next(n, from);
|
|
6776
|
+
return at !== -1 && at + n <= pe ? at : -1;
|
|
6696
6777
|
};
|
|
6697
6778
|
let i = ps;
|
|
6698
6779
|
const scanEnd = Math.min(pe, this.provisionalFrom);
|
|
@@ -7328,6 +7409,7 @@ exports.legacyShellUses = legacyShellUses;
|
|
|
7328
7409
|
exports.listIslands = listIslands;
|
|
7329
7410
|
exports.looksLikeDirectiveHead = looksLikeDirectiveHead;
|
|
7330
7411
|
exports.looksLikeDisplayMath = looksLikeDisplayMath;
|
|
7412
|
+
exports.looksLikeOpenInlineMath = looksLikeOpenInlineMath;
|
|
7331
7413
|
exports.makePartialKindStalenessGate = makePartialKindStalenessGate;
|
|
7332
7414
|
exports.mapPosition = mapPosition;
|
|
7333
7415
|
exports.mapRange = mapRange;
|