@ai-matrx/content-ir 0.17.0 → 0.18.1
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 +74 -1
- package/dist/index.cjs +406 -310
- 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 +401 -311
- package/dist/index.js.map +1 -1
- package/dist/source.cjs +406 -310
- package/dist/source.cjs.map +1 -1
- package/dist/source.d.cts +124 -39
- package/dist/source.d.ts +124 -39
- package/dist/source.js +401 -311
- package/dist/source.js.map +1 -1
- package/package.json +1 -1
package/dist/source.cjs
CHANGED
|
@@ -254,75 +254,233 @@ function classifyInnerFenceLine(trimmed, openTicks, nests, nestedDepth) {
|
|
|
254
254
|
return "content";
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
-
// source/
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
"
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
"lim",
|
|
272
|
-
"max",
|
|
273
|
-
"min",
|
|
274
|
-
"det",
|
|
275
|
-
"gcd",
|
|
276
|
-
"mod",
|
|
277
|
-
"arg",
|
|
278
|
-
"sinh",
|
|
279
|
-
"cosh",
|
|
280
|
-
"tanh"
|
|
281
|
-
]);
|
|
282
|
-
function isMathShape(content) {
|
|
283
|
-
if (!MATH_SHAPE_CHARS.test(content)) return false;
|
|
284
|
-
const words = content.match(/[A-Za-z]+/g);
|
|
285
|
-
if (!words) return false;
|
|
286
|
-
if (!words.every((w) => w.length === 1 || FUNCTION_NAMES.has(w))) return false;
|
|
287
|
-
if (/[A-Za-z]'+[A-Za-z]/.test(content) || /(?:^|[\s(,])[A-Za-z]\.(?:[A-Za-z]\.|\s|$)/.test(content)) return false;
|
|
288
|
-
return /[A-Za-z]'*\(|[A-Za-z]'|\b[A-Za-z]\s+[A-Za-z]\b|\([^)]*[A-Za-z][^)]*\)/.test(content);
|
|
257
|
+
// source/code-ranges.ts
|
|
258
|
+
function fenceOpenerOf(content) {
|
|
259
|
+
const t = content.trimStart();
|
|
260
|
+
if (t.startsWith("```")) {
|
|
261
|
+
let ticks = 0;
|
|
262
|
+
while (ticks < t.length && t[ticks] === "`") ticks++;
|
|
263
|
+
return { char: "`", ticks, lang: parseFenceOpener(t)?.lang ?? "" };
|
|
264
|
+
}
|
|
265
|
+
if (content.length - t.length <= 3 && t.startsWith("~~~")) {
|
|
266
|
+
const open = /^(~{3,})(.*)$/.exec(t);
|
|
267
|
+
if (!open) return null;
|
|
268
|
+
return { char: "~", ticks: open[1].length, lang: open[2].trim().split(/\s/)[0] ?? "" };
|
|
269
|
+
}
|
|
270
|
+
return null;
|
|
289
271
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
272
|
+
var FenceReader = class {
|
|
273
|
+
constructor(opener, options = {}) {
|
|
274
|
+
this.opener = opener;
|
|
275
|
+
this.isJson = opener.char === "`" && opener.lang === "json";
|
|
276
|
+
this.nesting = opener.char === "`" && (options.nesting ?? fenceNestsInnerFences(opener.lang));
|
|
277
|
+
this.tildeCloser = opener.char === "~" ? new RegExp(`^ {0,3}~{${opener.ticks},}[ \\t]*$`) : null;
|
|
278
|
+
}
|
|
279
|
+
opener;
|
|
280
|
+
state = { inString: false, escaped: false };
|
|
281
|
+
depth = 0;
|
|
282
|
+
/** A nested fence was opened at some point. */
|
|
283
|
+
sawNested = false;
|
|
284
|
+
isJson;
|
|
285
|
+
nesting;
|
|
286
|
+
tildeCloser;
|
|
287
|
+
/** How many nested fences are open right now. */
|
|
288
|
+
get nestedDepth() {
|
|
289
|
+
return this.depth;
|
|
290
|
+
}
|
|
291
|
+
feed(line) {
|
|
292
|
+
if (this.tildeCloser) return this.tildeCloser.test(line);
|
|
293
|
+
const trimmedLine = trimFenceLine(line);
|
|
294
|
+
const at = line.indexOf("```");
|
|
295
|
+
if (at === -1) {
|
|
296
|
+
if (this.isJson) this.state = jsonStringState(line, 0, line.length, this.state);
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
if (this.isJson) {
|
|
300
|
+
const probe = jsonStringState(line, 0, at, this.state);
|
|
301
|
+
if (probe.inString) {
|
|
302
|
+
this.state = jsonStringState(line, at, line.length, probe);
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
if (trimmedLine.startsWith("```")) {
|
|
307
|
+
const kind = classifyInnerFenceLine(trimmedLine, this.opener.ticks, this.nesting, this.depth);
|
|
308
|
+
if (kind === "close-outer") return true;
|
|
309
|
+
if (kind === "open-nested") {
|
|
310
|
+
this.depth++;
|
|
311
|
+
this.sawNested = true;
|
|
312
|
+
}
|
|
313
|
+
if (kind === "close-nested") this.depth--;
|
|
314
|
+
} else {
|
|
315
|
+
const closeTicks = backtickRunLength(line, at);
|
|
316
|
+
const after = trimFenceLine(line.slice(at + closeTicks));
|
|
317
|
+
if (closeTicks >= this.opener.ticks && after === "" && this.depth === 0) return true;
|
|
318
|
+
}
|
|
319
|
+
if (this.isJson) this.state = jsonStringState(line, 0, line.length, this.state);
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
function closeFence(src, open, opener) {
|
|
324
|
+
const first = readFence(src, open, new FenceReader(opener));
|
|
325
|
+
if (first.closed || !first.reader.sawNested || first.reader.nestedDepth <= 0) return { line: first.line, closed: first.closed };
|
|
326
|
+
const strict = readFence(src, open, new FenceReader(opener, { nesting: false }));
|
|
327
|
+
return { line: strict.line, closed: strict.closed };
|
|
297
328
|
}
|
|
298
|
-
function
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
if (
|
|
304
|
-
|
|
305
|
-
|
|
329
|
+
function readFence(src, open, reader) {
|
|
330
|
+
for (let k = open + 1; k < src.count; k++) {
|
|
331
|
+
if (src.openTail?.(k)) continue;
|
|
332
|
+
const line = src.line(k);
|
|
333
|
+
if (line === null) return { line: k - 1, closed: false, reader };
|
|
334
|
+
if (reader.feed(line)) return { line: k, closed: true, reader };
|
|
335
|
+
}
|
|
336
|
+
return { line: src.count - 1, closed: false, reader };
|
|
337
|
+
}
|
|
338
|
+
function jsonStringState(line, from, upTo, state) {
|
|
339
|
+
let { inString, escaped } = state;
|
|
340
|
+
for (let idx = from; idx < upTo; idx++) {
|
|
341
|
+
const ch = line[idx];
|
|
342
|
+
if (escaped) {
|
|
343
|
+
escaped = false;
|
|
306
344
|
continue;
|
|
307
345
|
}
|
|
308
|
-
if (
|
|
309
|
-
|
|
310
|
-
|
|
346
|
+
if (ch === "\\" && inString) {
|
|
347
|
+
escaped = true;
|
|
348
|
+
continue;
|
|
311
349
|
}
|
|
350
|
+
if (ch === '"') inString = !inString;
|
|
312
351
|
}
|
|
313
|
-
|
|
314
|
-
const content = text.slice(open + 1, close);
|
|
315
|
-
return isSingleDollarMath(content, text[close + 1]) ? close + 1 : -1;
|
|
352
|
+
return { inString, escaped };
|
|
316
353
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
354
|
+
function backtickRunLength(str, pos) {
|
|
355
|
+
let n = 0;
|
|
356
|
+
while (pos + n < str.length && str[pos + n] === "`") n++;
|
|
357
|
+
return n;
|
|
358
|
+
}
|
|
359
|
+
function quotePrefix(line) {
|
|
360
|
+
let depth = 0;
|
|
361
|
+
let offset = 0;
|
|
362
|
+
for (; ; ) {
|
|
363
|
+
const m = /^ {0,3}> ?/.exec(line.slice(offset));
|
|
364
|
+
if (!m) return { depth, offset };
|
|
365
|
+
depth++;
|
|
366
|
+
offset += m[0].length;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
function stripQuotes(line, depth) {
|
|
370
|
+
let offset = 0;
|
|
371
|
+
for (let d = 0; d < depth; d++) {
|
|
372
|
+
const m = /^ {0,3}> ?/.exec(line.slice(offset));
|
|
373
|
+
if (!m) return null;
|
|
374
|
+
offset += m[0].length;
|
|
375
|
+
}
|
|
376
|
+
return line.slice(offset);
|
|
377
|
+
}
|
|
378
|
+
var LIST_ITEM = /^( *)([-*+]|\d{1,9}[.)])( +|\t|$)/;
|
|
379
|
+
function leadingSpaces(s) {
|
|
380
|
+
let i = 0;
|
|
381
|
+
while (i < s.length && s[i] === " ") i++;
|
|
382
|
+
return i;
|
|
383
|
+
}
|
|
384
|
+
function scan(text) {
|
|
385
|
+
const starts = [];
|
|
386
|
+
const ends = [];
|
|
387
|
+
for (let pos = 0; ; ) {
|
|
388
|
+
const nl = text.indexOf("\n", pos);
|
|
389
|
+
const lineEnd = nl === -1 ? text.length : nl;
|
|
390
|
+
starts.push(pos);
|
|
391
|
+
ends.push(lineEnd > pos && text.charCodeAt(lineEnd - 1) === 13 ? lineEnd - 1 : lineEnd);
|
|
392
|
+
if (nl === -1) break;
|
|
393
|
+
pos = nl + 1;
|
|
394
|
+
}
|
|
395
|
+
const count = starts.length;
|
|
396
|
+
const raw = (k) => text.slice(starts[k], ends[k]);
|
|
397
|
+
const out = { ranges: [], fences: [], paragraphs: [], endsInFence: false, pendingPara: -1 };
|
|
398
|
+
const rawLines = { count, line: raw };
|
|
399
|
+
let segment = 0;
|
|
400
|
+
for (let k = 0; k < count; k++) {
|
|
401
|
+
const opener = fenceOpenerOf(raw(k));
|
|
402
|
+
if (!opener || opener.char !== "`") continue;
|
|
403
|
+
prose(text, starts, ends, raw, segment, k, out);
|
|
404
|
+
const end = closeFence(rawLines, k, opener);
|
|
405
|
+
out.ranges.push({ start: starts[k], end: ends[end.line], kind: "fence" });
|
|
406
|
+
out.fences.push([k, end.line, end.closed]);
|
|
407
|
+
out.pendingPara = -1;
|
|
408
|
+
if (!end.closed && end.line === count - 1) out.endsInFence = true;
|
|
409
|
+
k = end.line;
|
|
410
|
+
segment = k + 1;
|
|
411
|
+
}
|
|
412
|
+
prose(text, starts, ends, raw, segment, count, out);
|
|
413
|
+
return out;
|
|
414
|
+
}
|
|
415
|
+
function prose(text, starts, ends, raw, from, to, out) {
|
|
323
416
|
let para = -1;
|
|
324
|
-
|
|
325
|
-
|
|
417
|
+
let quoteDepth = 0;
|
|
418
|
+
let lists = [];
|
|
419
|
+
const closePara = (at) => {
|
|
420
|
+
if (para !== -1) out.paragraphs.push([para, at]);
|
|
421
|
+
para = -1;
|
|
422
|
+
};
|
|
423
|
+
for (let k = from; k < to; k++) {
|
|
424
|
+
const line = raw(k);
|
|
425
|
+
const { depth, offset } = quotePrefix(line);
|
|
426
|
+
if (depth !== quoteDepth) {
|
|
427
|
+
quoteDepth = depth;
|
|
428
|
+
lists = [];
|
|
429
|
+
}
|
|
430
|
+
let content = line.slice(offset);
|
|
431
|
+
if (content.trim() === "") {
|
|
432
|
+
closePara(starts[k]);
|
|
433
|
+
if (!(k === starts.length - 1 && line === "")) out.pendingPara = -1;
|
|
434
|
+
continue;
|
|
435
|
+
}
|
|
436
|
+
const indent = leadingSpaces(content);
|
|
437
|
+
while (lists.length && indent < lists[lists.length - 1]) lists.pop();
|
|
438
|
+
const item = LIST_ITEM.exec(content);
|
|
439
|
+
let column = lists.length ? lists[lists.length - 1] : 0;
|
|
440
|
+
if (item) {
|
|
441
|
+
const gap = item[3].length;
|
|
442
|
+
column = item[1].length + item[2].length + (gap >= 1 && gap <= 4 ? gap : 1);
|
|
443
|
+
lists.push(column);
|
|
444
|
+
content = content.slice(Math.min(column, content.length));
|
|
445
|
+
} else {
|
|
446
|
+
content = content.slice(Math.min(indent, column));
|
|
447
|
+
}
|
|
448
|
+
const opener = fenceOpenerOf(content);
|
|
449
|
+
if (!opener) {
|
|
450
|
+
if (para === -1) para = starts[k];
|
|
451
|
+
if (out.pendingPara === -1) out.pendingPara = starts[k];
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
closePara(starts[k]);
|
|
455
|
+
out.pendingPara = -1;
|
|
456
|
+
const col = column;
|
|
457
|
+
const src = {
|
|
458
|
+
count: to,
|
|
459
|
+
line: (j) => {
|
|
460
|
+
const inner = stripQuotes(raw(j), depth);
|
|
461
|
+
if (inner === null) return null;
|
|
462
|
+
if (opener.char === "~" && col > 0) {
|
|
463
|
+
const ind = leadingSpaces(inner);
|
|
464
|
+
if (inner.trim() !== "" && ind < col) return null;
|
|
465
|
+
return inner.slice(Math.min(ind, col));
|
|
466
|
+
}
|
|
467
|
+
return inner;
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
const end = closeFence(src, k, opener);
|
|
471
|
+
out.ranges.push({ start: starts[k], end: ends[end.line], kind: "fence" });
|
|
472
|
+
out.fences.push([k, end.line, end.closed]);
|
|
473
|
+
if (!end.closed && end.line === starts.length - 1) out.endsInFence = true;
|
|
474
|
+
k = end.line;
|
|
475
|
+
}
|
|
476
|
+
closePara(to < starts.length ? starts[to] : text.length);
|
|
477
|
+
}
|
|
478
|
+
var BacktickRuns = class {
|
|
479
|
+
/** Every run, in order: [start, length]. */
|
|
480
|
+
all = [];
|
|
481
|
+
byLength = /* @__PURE__ */ new Map();
|
|
482
|
+
indexOf = /* @__PURE__ */ new Map();
|
|
483
|
+
constructor(text, from, to) {
|
|
326
484
|
for (let k = from; k < to; ) {
|
|
327
485
|
if (text.charCodeAt(k) !== 96) {
|
|
328
486
|
k++;
|
|
@@ -330,117 +488,69 @@ function findCodeRanges(text) {
|
|
|
330
488
|
}
|
|
331
489
|
let len = 1;
|
|
332
490
|
while (k + len < to && text.charCodeAt(k + len) === 96) len++;
|
|
333
|
-
|
|
491
|
+
this.indexOf.set(k, this.all.length);
|
|
492
|
+
this.all.push([k, len]);
|
|
493
|
+
const list = this.byLength.get(len);
|
|
494
|
+
if (list) list.push(k);
|
|
495
|
+
else this.byLength.set(len, [k]);
|
|
334
496
|
k += len;
|
|
335
497
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
const
|
|
345
|
-
if (
|
|
346
|
-
|
|
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;
|
|
498
|
+
}
|
|
499
|
+
/** Start of the first run of exactly `n` backticks at or after `after`, or -1. */
|
|
500
|
+
next(n, after) {
|
|
501
|
+
const list = this.byLength.get(n);
|
|
502
|
+
if (!list) return -1;
|
|
503
|
+
let lo = 0;
|
|
504
|
+
let hi = list.length;
|
|
505
|
+
while (lo < hi) {
|
|
506
|
+
const mid = lo + hi >>> 1;
|
|
507
|
+
if (list[mid] < after) lo = mid + 1;
|
|
508
|
+
else hi = mid;
|
|
353
509
|
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
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;
|
|
510
|
+
return list[lo] ?? -1;
|
|
511
|
+
}
|
|
512
|
+
/** Index of the run starting at `start` in `all`. */
|
|
513
|
+
index(start) {
|
|
514
|
+
return this.indexOf.get(start) ?? -1;
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
function codeSpans(text, from, to, out) {
|
|
518
|
+
const runs = new BacktickRuns(text, from, to);
|
|
519
|
+
for (let r = 0; r < runs.all.length; ) {
|
|
520
|
+
const [start, n] = runs.all[r];
|
|
521
|
+
const close = runs.next(n, start + n);
|
|
522
|
+
if (close === -1) {
|
|
523
|
+
r++;
|
|
524
|
+
continue;
|
|
393
525
|
}
|
|
394
|
-
|
|
395
|
-
|
|
526
|
+
out.push({ start, end: close + n, kind: "span" });
|
|
527
|
+
r = runs.index(close) + 1;
|
|
396
528
|
}
|
|
397
|
-
|
|
398
|
-
|
|
529
|
+
}
|
|
530
|
+
function findCodeRanges(text) {
|
|
531
|
+
const s = scan(text);
|
|
532
|
+
const ranges = [...s.ranges];
|
|
533
|
+
for (const [from, to] of s.paragraphs) codeSpans(text, from, to, ranges);
|
|
399
534
|
return ranges.sort((a, b) => a.start - b.start);
|
|
400
535
|
}
|
|
536
|
+
function fenceLineKinds(text) {
|
|
537
|
+
const s = scan(text);
|
|
538
|
+
let count = 1;
|
|
539
|
+
for (let i = text.indexOf("\n"); i !== -1; i = text.indexOf("\n", i + 1)) count++;
|
|
540
|
+
const kinds = new Array(count).fill("prose");
|
|
541
|
+
for (const [open, last, closed] of s.fences) {
|
|
542
|
+
kinds[open] = "open";
|
|
543
|
+
for (let k = open + 1; k <= last; k++) kinds[k] = "body";
|
|
544
|
+
if (closed && last > open) kinds[last] = "close";
|
|
545
|
+
}
|
|
546
|
+
return kinds;
|
|
547
|
+
}
|
|
401
548
|
function pendingCodeSpanStart(text) {
|
|
402
549
|
const n = text.length;
|
|
403
550
|
if (n === 0 || /\n[ \t]*\n[ \t]*$/.test(text)) return -1;
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
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;
|
|
551
|
+
const s = scan(text);
|
|
552
|
+
const para = s.pendingPara;
|
|
553
|
+
if (s.endsInFence || para === -1) return -1;
|
|
444
554
|
const runs = [];
|
|
445
555
|
for (let k = para; k < n; ) {
|
|
446
556
|
if (text.charCodeAt(k) !== 96) {
|
|
@@ -577,6 +687,83 @@ function pairDisplayMath(text) {
|
|
|
577
687
|
return pairs;
|
|
578
688
|
}
|
|
579
689
|
|
|
690
|
+
// source/math.ts
|
|
691
|
+
var TEX_SIGNAL = /\\[A-Za-z]+|[\\^_{}=<>+]/;
|
|
692
|
+
var LONE_VARIABLE = /^[A-Za-z](?:'|[0-9])?$/;
|
|
693
|
+
var MATH_SHAPE_CHARS = /^[A-Za-z0-9'\s(),.*\/-]+$/;
|
|
694
|
+
function isSingleDollarMath(content, after) {
|
|
695
|
+
if (!content || content.length > 400) return false;
|
|
696
|
+
if (/^\s/.test(content) || /\s$/.test(content)) return false;
|
|
697
|
+
if (after !== void 0 && /[0-9]/.test(after)) return false;
|
|
698
|
+
if (/(?:^|[^\\])%/.test(content)) return false;
|
|
699
|
+
if (/^[)\]}"/]/.test(content) || /[(\[{":;,/]$/.test(content)) return false;
|
|
700
|
+
if (/^[0-9]/.test(content) && after !== void 0 && /[A-Za-z]/.test(after)) return false;
|
|
701
|
+
if (isMathPlaceholder(content)) return false;
|
|
702
|
+
return TEX_SIGNAL.test(content) || !readsAsProse(content);
|
|
703
|
+
}
|
|
704
|
+
var FUNCTION_NAMES = /* @__PURE__ */ new Set([
|
|
705
|
+
"sin",
|
|
706
|
+
"cos",
|
|
707
|
+
"tan",
|
|
708
|
+
"sec",
|
|
709
|
+
"csc",
|
|
710
|
+
"cot",
|
|
711
|
+
"log",
|
|
712
|
+
"ln",
|
|
713
|
+
"exp",
|
|
714
|
+
"lim",
|
|
715
|
+
"max",
|
|
716
|
+
"min",
|
|
717
|
+
"det",
|
|
718
|
+
"gcd",
|
|
719
|
+
"mod",
|
|
720
|
+
"arg",
|
|
721
|
+
"sinh",
|
|
722
|
+
"cosh",
|
|
723
|
+
"tanh"
|
|
724
|
+
]);
|
|
725
|
+
function readsAsProse(content) {
|
|
726
|
+
if (/[A-Za-z]'[a-z]/.test(content)) return true;
|
|
727
|
+
if (/(?:^|[\s(,])[A-Za-z]\.(?:[A-Za-z]\.|\s|$)/.test(content)) return true;
|
|
728
|
+
if (!/\s/.test(content)) return false;
|
|
729
|
+
const words = (content.match(/[A-Za-z]{3,}/g) ?? []).filter((w) => !FUNCTION_NAMES.has(w.toLowerCase()));
|
|
730
|
+
return words.length >= 2;
|
|
731
|
+
}
|
|
732
|
+
function looksLikeOpenInlineMath(partial) {
|
|
733
|
+
if (!partial || partial.length > 400) return false;
|
|
734
|
+
if (/^\s/.test(partial) || /\s$/.test(partial)) return false;
|
|
735
|
+
if (LONE_VARIABLE.test(partial)) return true;
|
|
736
|
+
if (/^[0-9]/.test(partial)) return /\\[A-Za-z]+|[\\^_{}]/.test(partial);
|
|
737
|
+
return TEX_SIGNAL.test(partial) || isMathShape(partial);
|
|
738
|
+
}
|
|
739
|
+
function isMathShape(content) {
|
|
740
|
+
if (!MATH_SHAPE_CHARS.test(content)) return false;
|
|
741
|
+
const words = content.match(/[A-Za-z]+/g);
|
|
742
|
+
if (!words) return false;
|
|
743
|
+
if (!words.every((w) => w.length === 1 || FUNCTION_NAMES.has(w))) return false;
|
|
744
|
+
if (/[A-Za-z]'+[A-Za-z]/.test(content) || /(?:^|[\s(,])[A-Za-z]\.(?:[A-Za-z]\.|\s|$)/.test(content)) return false;
|
|
745
|
+
return /[A-Za-z]'*\(|[A-Za-z]'|\b[A-Za-z]\s+[A-Za-z]\b|\([^)]*[A-Za-z][^)]*\)/.test(content);
|
|
746
|
+
}
|
|
747
|
+
function singleDollarMathEnd(text, open, limit = text.length) {
|
|
748
|
+
const bound = Math.min(limit, open + 403);
|
|
749
|
+
let close = -1;
|
|
750
|
+
for (let k = open + 1; k < bound; k += 1) {
|
|
751
|
+
const c = text[k];
|
|
752
|
+
if (c === "\n") break;
|
|
753
|
+
if (c === "\\") {
|
|
754
|
+
k += 1;
|
|
755
|
+
continue;
|
|
756
|
+
}
|
|
757
|
+
if (c === "$") {
|
|
758
|
+
close = k;
|
|
759
|
+
break;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
if (close === -1 || text[close + 1] === "$") return -1;
|
|
763
|
+
const content = text.slice(open + 1, close);
|
|
764
|
+
return isSingleDollarMath(content, text[close + 1]) ? close + 1 : -1;
|
|
765
|
+
}
|
|
766
|
+
|
|
580
767
|
// source/xml-tag.ts
|
|
581
768
|
var XML_NAME_START = /[A-Za-z_]/;
|
|
582
769
|
var XML_NAME_CHARACTER = /[\w.:-]/;
|
|
@@ -656,25 +843,20 @@ var XmlContainerTracker = class {
|
|
|
656
843
|
inComment = false;
|
|
657
844
|
inCdata = false;
|
|
658
845
|
inlineTicks = 0;
|
|
659
|
-
|
|
846
|
+
/** The open fence, read by THE one closer (source/code-ranges.ts). */
|
|
847
|
+
fence = null;
|
|
660
848
|
consumeLine(line, startOffset = 0) {
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
return null;
|
|
670
|
-
}
|
|
671
|
-
if (char === this.fenceMarker.char && marker.length >= this.fenceMarker.ticks && suffix.trim() === "") {
|
|
672
|
-
this.fenceMarker = null;
|
|
673
|
-
}
|
|
849
|
+
if (this.fence) {
|
|
850
|
+
if (this.fence.feed(line)) this.fence = null;
|
|
851
|
+
return null;
|
|
852
|
+
}
|
|
853
|
+
if (!this.inComment && !this.inCdata && this.inlineTicks === 0) {
|
|
854
|
+
const opener = fenceOpenerOf(line);
|
|
855
|
+
if (opener) {
|
|
856
|
+
this.fence = new FenceReader(opener);
|
|
674
857
|
return null;
|
|
675
858
|
}
|
|
676
859
|
}
|
|
677
|
-
if (this.fenceMarker) return null;
|
|
678
860
|
for (let i = startOffset; i < line.length; i++) {
|
|
679
861
|
if (this.inlineTicks > 0) {
|
|
680
862
|
if (line[i] === "`") {
|
|
@@ -869,27 +1051,6 @@ function isUnclosedGenericXmlOpening(source) {
|
|
|
869
1051
|
}
|
|
870
1052
|
return true;
|
|
871
1053
|
}
|
|
872
|
-
function jsonStringState(line, from, upTo, state) {
|
|
873
|
-
let { inString, escaped } = state;
|
|
874
|
-
for (let idx = from; idx < upTo; idx++) {
|
|
875
|
-
const ch = line[idx];
|
|
876
|
-
if (escaped) {
|
|
877
|
-
escaped = false;
|
|
878
|
-
continue;
|
|
879
|
-
}
|
|
880
|
-
if (ch === "\\" && inString) {
|
|
881
|
-
escaped = true;
|
|
882
|
-
continue;
|
|
883
|
-
}
|
|
884
|
-
if (ch === '"') inString = !inString;
|
|
885
|
-
}
|
|
886
|
-
return { inString, escaped };
|
|
887
|
-
}
|
|
888
|
-
function backtickRunLength(str, pos) {
|
|
889
|
-
let n = 0;
|
|
890
|
-
while (pos + n < str.length && str[pos + n] === "`") n++;
|
|
891
|
-
return n;
|
|
892
|
-
}
|
|
893
1054
|
function isSplitterTreeLine(line) {
|
|
894
1055
|
return TREE_GLYPHS.test(line) || /^[\s│|]*[├└+|][\s─\-]+/.test(line);
|
|
895
1056
|
}
|
|
@@ -1121,11 +1282,9 @@ var Tokenizer = class {
|
|
|
1121
1282
|
const footnote = this.footnoteDefinition(p, li, t);
|
|
1122
1283
|
if (footnote) return footnote;
|
|
1123
1284
|
}
|
|
1124
|
-
|
|
1125
|
-
if (
|
|
1126
|
-
|
|
1127
|
-
if (tilde) return tilde;
|
|
1128
|
-
}
|
|
1285
|
+
const fence = fenceOpenerOf(seg);
|
|
1286
|
+
if (fence?.char === "`") return this.backtickFence(p, li, fence);
|
|
1287
|
+
if (fence?.char === "~") return this.tildeFence(p, li, fence);
|
|
1129
1288
|
if (t.startsWith("$$")) {
|
|
1130
1289
|
const math = this.mathBlock(p, tp);
|
|
1131
1290
|
if (math) return math;
|
|
@@ -1280,74 +1439,31 @@ var Tokenizer = class {
|
|
|
1280
1439
|
heldFootnote(p, id) {
|
|
1281
1440
|
return this.island("footnote_def", p, this.n, false, { id });
|
|
1282
1441
|
}
|
|
1442
|
+
/** The text's lines as the one fence closer reads them (streaming: the open tail closes nothing). */
|
|
1443
|
+
get fenceLines() {
|
|
1444
|
+
return {
|
|
1445
|
+
count: this.lineCount,
|
|
1446
|
+
line: (k) => this.lineText(k),
|
|
1447
|
+
openTail: (k) => this.isOpenTail(k)
|
|
1448
|
+
};
|
|
1449
|
+
}
|
|
1283
1450
|
/**
|
|
1284
|
-
* Backtick fence —
|
|
1285
|
-
*
|
|
1286
|
-
*
|
|
1287
|
-
* still open at the end of the text.
|
|
1451
|
+
* Backtick fence — THE one closer (`closeFence`, source/code-ranges.ts): the
|
|
1452
|
+
* nested-fence rule for markdown fences with the strict-CommonMark retry, the
|
|
1453
|
+
* renderer's line-end closer, JSON-string awareness for ```json.
|
|
1288
1454
|
*/
|
|
1289
|
-
backtickFence(p, li,
|
|
1290
|
-
const
|
|
1291
|
-
const lang = parseFenceOpener(t)?.lang ?? "";
|
|
1455
|
+
backtickFence(p, li, opener) {
|
|
1456
|
+
const lang = opener.lang;
|
|
1292
1457
|
const isJson = lang === "json";
|
|
1293
1458
|
const normalized = normalizeFenceLanguage(lang);
|
|
1294
|
-
const meta = { fence: "`", ticks:
|
|
1459
|
+
const meta = { fence: "`", ticks: opener.ticks, lang };
|
|
1295
1460
|
if (normalized && SPECIAL_CODE_LANGUAGES.has(normalized)) meta.special = normalized;
|
|
1296
|
-
const
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
if (typeof close === "number") {
|
|
1300
|
-
return this.fenceIsland(p, this.contentEnds[close], true, meta, li, close, isJson);
|
|
1461
|
+
const end = closeFence(this.fenceLines, li, opener);
|
|
1462
|
+
if (end.closed) {
|
|
1463
|
+
return this.fenceIsland(p, this.contentEnds[end.line], true, meta, li, end.line, isJson);
|
|
1301
1464
|
}
|
|
1302
1465
|
return this.fenceIsland(p, this.n, false, meta, li, this.lineCount, isJson);
|
|
1303
1466
|
}
|
|
1304
|
-
/** The closing line of a backtick fence opened on line `li`, or null when it never closes. */
|
|
1305
|
-
backtickFenceClose(li, openTicks, isJson, nesting) {
|
|
1306
|
-
let state = { inString: false, escaped: false };
|
|
1307
|
-
let nestedDepth = 0;
|
|
1308
|
-
let sawNested = false;
|
|
1309
|
-
for (let k = li + 1; k < this.lineCount; k++) {
|
|
1310
|
-
if (this.isOpenTail(k)) continue;
|
|
1311
|
-
const line = this.lineText(k);
|
|
1312
|
-
const trimmedLine = trimFenceLine(line);
|
|
1313
|
-
if (trimmedLine.startsWith("```")) {
|
|
1314
|
-
const at2 = line.indexOf("```");
|
|
1315
|
-
if (isJson) {
|
|
1316
|
-
const probe = jsonStringState(line, 0, at2, state);
|
|
1317
|
-
if (probe.inString) {
|
|
1318
|
-
state = jsonStringState(line, at2, line.length, probe);
|
|
1319
|
-
continue;
|
|
1320
|
-
}
|
|
1321
|
-
}
|
|
1322
|
-
const kind = classifyInnerFenceLine(trimmedLine, openTicks, nesting, nestedDepth);
|
|
1323
|
-
if (kind === "close-outer") return k;
|
|
1324
|
-
if (kind === "open-nested") {
|
|
1325
|
-
nestedDepth++;
|
|
1326
|
-
sawNested = true;
|
|
1327
|
-
}
|
|
1328
|
-
if (kind === "close-nested") nestedDepth--;
|
|
1329
|
-
if (isJson) state = jsonStringState(line, 0, line.length, state);
|
|
1330
|
-
continue;
|
|
1331
|
-
}
|
|
1332
|
-
const at = line.indexOf("```");
|
|
1333
|
-
if (at !== -1) {
|
|
1334
|
-
if (isJson) {
|
|
1335
|
-
const probe = jsonStringState(line, 0, at, state);
|
|
1336
|
-
if (probe.inString) {
|
|
1337
|
-
state = jsonStringState(line, at, line.length, probe);
|
|
1338
|
-
continue;
|
|
1339
|
-
}
|
|
1340
|
-
}
|
|
1341
|
-
const closeTicks = backtickRunLength(line, at);
|
|
1342
|
-
const after = trimFenceLine(line.slice(at + closeTicks));
|
|
1343
|
-
if (closeTicks >= openTicks && after === "" && nestedDepth === 0) return k;
|
|
1344
|
-
if (isJson) state = jsonStringState(line, 0, line.length, state);
|
|
1345
|
-
continue;
|
|
1346
|
-
}
|
|
1347
|
-
if (isJson) state = jsonStringState(line, 0, line.length, state);
|
|
1348
|
-
}
|
|
1349
|
-
return sawNested && nestedDepth > 0 ? "retry-strict" : null;
|
|
1350
|
-
}
|
|
1351
1467
|
fenceIsland(p, end, complete, meta, openLine, closeLine, isJson) {
|
|
1352
1468
|
if (isJson && openLine + 1 < this.lineCount) {
|
|
1353
1469
|
const bodyEnd = closeLine < this.lineCount ? this.lineStarts[closeLine] : this.n;
|
|
@@ -1356,22 +1472,16 @@ var Tokenizer = class {
|
|
|
1356
1472
|
}
|
|
1357
1473
|
return this.island("fence", p, end, complete, meta);
|
|
1358
1474
|
}
|
|
1359
|
-
tildeFence(p, li,
|
|
1360
|
-
const
|
|
1361
|
-
|
|
1362
|
-
const ticks = open[1].length;
|
|
1363
|
-
const lang = open[2].trim().split(/\s/)[0] ?? "";
|
|
1364
|
-
const meta = { fence: "~", ticks, lang };
|
|
1475
|
+
tildeFence(p, li, opener) {
|
|
1476
|
+
const lang = opener.lang;
|
|
1477
|
+
const meta = { fence: "~", ticks: opener.ticks, lang };
|
|
1365
1478
|
const normalized = normalizeFenceLanguage(lang);
|
|
1366
1479
|
if (normalized && SPECIAL_CODE_LANGUAGES.has(normalized)) meta.special = normalized;
|
|
1367
|
-
const close =
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
const end = this.rendererOverflow(li + 1, k, tildeEnd);
|
|
1373
|
-
return this.island("fence", p, end, end === this.n ? this.overflowComplete : true, meta);
|
|
1374
|
-
}
|
|
1480
|
+
const close = closeFence(this.fenceLines, li, opener);
|
|
1481
|
+
if (close.closed) {
|
|
1482
|
+
const tildeEnd = this.contentEnds[close.line];
|
|
1483
|
+
const end = this.rendererOverflow(li + 1, close.line, tildeEnd);
|
|
1484
|
+
return this.island("fence", p, end, end === this.n ? this.overflowComplete : true, meta);
|
|
1375
1485
|
}
|
|
1376
1486
|
return this.island("fence", p, this.n, false, meta);
|
|
1377
1487
|
}
|
|
@@ -1391,7 +1501,7 @@ var Tokenizer = class {
|
|
|
1391
1501
|
for (let j = firstLine; j <= closeLine && j < this.lineCount; j++) {
|
|
1392
1502
|
const start = this.lineStarts[j];
|
|
1393
1503
|
if (this.lineIsBlank(j)) continue;
|
|
1394
|
-
if (this.lineText(j)
|
|
1504
|
+
if (fenceOpenerOf(this.lineText(j))?.char === "~") continue;
|
|
1395
1505
|
const inner = this.detectBlockUncached(start, j, false);
|
|
1396
1506
|
if (!inner) continue;
|
|
1397
1507
|
if (inner.end > end) {
|
|
@@ -1639,9 +1749,9 @@ var Tokenizer = class {
|
|
|
1639
1749
|
const tree = { ...breakIsland, start: treeStart };
|
|
1640
1750
|
if (treeStart > pos) {
|
|
1641
1751
|
const proseEnd = this.contentEnds[root - 1];
|
|
1642
|
-
const
|
|
1643
|
-
if (!
|
|
1644
|
-
this.push({ kind: "prose", start: pos, end: proseEnd, island: null, inlines:
|
|
1752
|
+
const scan3 = this.scanInline(pos, proseEnd);
|
|
1753
|
+
if (!scan3.breakIsland) {
|
|
1754
|
+
this.push({ kind: "prose", start: pos, end: proseEnd, island: null, inlines: scan3.inlines });
|
|
1645
1755
|
this.push({ kind: "gap", start: proseEnd, end: treeStart, island: null, inlines: [] });
|
|
1646
1756
|
this.push({ kind: "island", start: treeStart, end: tree.end, island: tree, inlines: [] });
|
|
1647
1757
|
return tree.end;
|
|
@@ -1653,13 +1763,13 @@ var Tokenizer = class {
|
|
|
1653
1763
|
}
|
|
1654
1764
|
}
|
|
1655
1765
|
}
|
|
1656
|
-
const
|
|
1657
|
-
if (!
|
|
1658
|
-
this.push({ kind: "prose", start: pos, end, island: null, inlines:
|
|
1766
|
+
const scan2 = this.scanInline(pos, end);
|
|
1767
|
+
if (!scan2.breakIsland) {
|
|
1768
|
+
this.push({ kind: "prose", start: pos, end, island: null, inlines: scan2.inlines });
|
|
1659
1769
|
return end;
|
|
1660
1770
|
}
|
|
1661
|
-
const br =
|
|
1662
|
-
if (
|
|
1771
|
+
const br = scan2.breakIsland;
|
|
1772
|
+
if (scan2.orphan) {
|
|
1663
1773
|
let start = pos;
|
|
1664
1774
|
while (this.blocks.length) {
|
|
1665
1775
|
const last = this.blocks[this.blocks.length - 1];
|
|
@@ -1676,7 +1786,7 @@ var Tokenizer = class {
|
|
|
1676
1786
|
start: pos,
|
|
1677
1787
|
end: br.start,
|
|
1678
1788
|
island: null,
|
|
1679
|
-
inlines:
|
|
1789
|
+
inlines: scan2.inlines.filter((inline) => inline.end <= br.start)
|
|
1680
1790
|
});
|
|
1681
1791
|
this.push({ kind: "island", start: br.start, end: br.end, island: br, inlines: [] });
|
|
1682
1792
|
return br.end;
|
|
@@ -1696,30 +1806,10 @@ var Tokenizer = class {
|
|
|
1696
1806
|
const codeSpanClose = (n, from) => {
|
|
1697
1807
|
if (!runs) {
|
|
1698
1808
|
this.tick(pe - ps);
|
|
1699
|
-
runs =
|
|
1700
|
-
for (let k = ps; k < pe; ) {
|
|
1701
|
-
if (text.charCodeAt(k) !== 96) {
|
|
1702
|
-
k++;
|
|
1703
|
-
continue;
|
|
1704
|
-
}
|
|
1705
|
-
const len = backtickRunLength(text, k);
|
|
1706
|
-
const list2 = runs.get(len);
|
|
1707
|
-
if (list2) list2.push(k);
|
|
1708
|
-
else runs.set(len, [k]);
|
|
1709
|
-
k += len;
|
|
1710
|
-
}
|
|
1711
|
-
}
|
|
1712
|
-
const list = runs.get(n);
|
|
1713
|
-
if (!list) return -1;
|
|
1714
|
-
let lo = 0;
|
|
1715
|
-
let hi = list.length;
|
|
1716
|
-
while (lo < hi) {
|
|
1717
|
-
const mid = lo + hi >>> 1;
|
|
1718
|
-
if (list[mid] < from) lo = mid + 1;
|
|
1719
|
-
else hi = mid;
|
|
1809
|
+
runs = new BacktickRuns(text, ps, pe);
|
|
1720
1810
|
}
|
|
1721
|
-
const at =
|
|
1722
|
-
return at !==
|
|
1811
|
+
const at = runs.next(n, from);
|
|
1812
|
+
return at !== -1 && at + n <= pe ? at : -1;
|
|
1723
1813
|
};
|
|
1724
1814
|
let i = ps;
|
|
1725
1815
|
const scanEnd = Math.min(pe, this.provisionalFrom);
|
|
@@ -2256,9 +2346,11 @@ function mapRange(changes, start, end, unit = "utf16") {
|
|
|
2256
2346
|
return { start: newStart, end: newEnd, touched, collapsed: newEnd === newStart && end > start };
|
|
2257
2347
|
}
|
|
2258
2348
|
|
|
2349
|
+
exports.BacktickRuns = BacktickRuns;
|
|
2259
2350
|
exports.CALLOUT_NAMES = CALLOUT_NAMES;
|
|
2260
2351
|
exports.FENCE_OPENER_WHITESPACE = FENCE_OPENER_WHITESPACE;
|
|
2261
2352
|
exports.FENCE_WHITESPACE = FENCE_WHITESPACE;
|
|
2353
|
+
exports.FenceReader = FenceReader;
|
|
2262
2354
|
exports.NESTING_FENCE_LANGUAGES = NESTING_FENCE_LANGUAGES;
|
|
2263
2355
|
exports.SourceSpliceError = SourceSpliceError;
|
|
2264
2356
|
exports.XmlContainerTracker = XmlContainerTracker;
|
|
@@ -2267,7 +2359,10 @@ exports.blockEdit = blockEdit;
|
|
|
2267
2359
|
exports.blockRangeEdit = blockRangeEdit;
|
|
2268
2360
|
exports.buildCodePointIndex = buildCodePointIndex;
|
|
2269
2361
|
exports.classifyInnerFenceLine = classifyInnerFenceLine;
|
|
2362
|
+
exports.closeFence = closeFence;
|
|
2363
|
+
exports.fenceLineKinds = fenceLineKinds;
|
|
2270
2364
|
exports.fenceNestsInnerFences = fenceNestsInnerFences;
|
|
2365
|
+
exports.fenceOpenerOf = fenceOpenerOf;
|
|
2271
2366
|
exports.findCodeRanges = findCodeRanges;
|
|
2272
2367
|
exports.isMathPlaceholder = isMathPlaceholder;
|
|
2273
2368
|
exports.isSingleDollarMath = isSingleDollarMath;
|
|
@@ -2275,6 +2370,7 @@ exports.islandEdit = islandEdit;
|
|
|
2275
2370
|
exports.joinSource = joinSource;
|
|
2276
2371
|
exports.listIslands = listIslands;
|
|
2277
2372
|
exports.looksLikeDisplayMath = looksLikeDisplayMath;
|
|
2373
|
+
exports.looksLikeOpenInlineMath = looksLikeOpenInlineMath;
|
|
2278
2374
|
exports.mapPosition = mapPosition;
|
|
2279
2375
|
exports.mapRange = mapRange;
|
|
2280
2376
|
exports.pairDisplayMath = pairDisplayMath;
|