@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.d.cts
CHANGED
|
@@ -420,21 +420,36 @@ declare function parseFenceOpener(line: string): {
|
|
|
420
420
|
} | null;
|
|
421
421
|
declare function classifyInnerFenceLine(trimmed: string, openTicks: number, nests: boolean, nestedDepth: number): InnerFenceLine;
|
|
422
422
|
|
|
423
|
+
interface CodeRange {
|
|
424
|
+
/** UTF-16 offset of the first character (the fence line start, or the opening backtick run). */
|
|
425
|
+
start: number;
|
|
426
|
+
/** Offset just past the closing fence line's last character / closing backtick run (end of text when unclosed). */
|
|
427
|
+
end: number;
|
|
428
|
+
kind: "fence" | "span";
|
|
429
|
+
}
|
|
423
430
|
/**
|
|
424
|
-
*
|
|
425
|
-
*
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
*
|
|
430
|
-
*
|
|
431
|
-
*
|
|
432
|
-
* the
|
|
433
|
-
*
|
|
434
|
-
*
|
|
435
|
-
*
|
|
436
|
-
*
|
|
431
|
+
* Where code is, by CommonMark — THE ONE code-range rule for every package.
|
|
432
|
+
* Math pairing (`pairDisplayMath`), the tokenizer's math islands, print's math
|
|
433
|
+
* lifting and kit's delimiter guard all ask this function; a second copy of
|
|
434
|
+
* code detection anywhere in `apps/shared` fails
|
|
435
|
+
* `__tests__/one-code-range-rule.test.ts`.
|
|
436
|
+
* - A fence opens only at the START of a line (≤ 3 spaces of indent): a
|
|
437
|
+
* mid-sentence "```python" is text, not a fence that swallows everything
|
|
438
|
+
* after it (verify-RC-B9: one inline ``` turned math off for the rest of
|
|
439
|
+
* the answer). Closing follows THE ONE nested-fence rule
|
|
440
|
+
* (`classifyInnerFenceLine`); an unclosed fence runs to the end.
|
|
441
|
+
* - An inline code span closes only at a backtick run of the SAME length in
|
|
442
|
+
* the same paragraph; an unmatched run is literal text.
|
|
443
|
+
* Linear: one pass over lines, one over each paragraph's backtick runs.
|
|
444
|
+
*/
|
|
445
|
+
declare function findCodeRanges(text: string): CodeRange[];
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* `$$...$$`, `$$…$$`, `$$ · $$`: a PLACEHOLDER — prose describing the syntax,
|
|
449
|
+
* never a formula. The pair is consumed whole as literal text (neither `$$`
|
|
450
|
+
* may open the next span).
|
|
437
451
|
*/
|
|
452
|
+
declare function isMathPlaceholder(inner: string): boolean;
|
|
438
453
|
/**
|
|
439
454
|
* The guard's `looksLikeMath`. `flow` = the opener is alone on its line: a
|
|
440
455
|
* flow block may span blank lines (like a fence); a `$$` with text beside it
|
|
@@ -442,7 +457,7 @@ declare function classifyInnerFenceLine(trimmed: string, openTicks: number, nest
|
|
|
442
457
|
* pairing with the next paragraph's formula.
|
|
443
458
|
*/
|
|
444
459
|
declare function looksLikeDisplayMath(inner: string, flow?: boolean): boolean;
|
|
445
|
-
|
|
460
|
+
|
|
446
461
|
/**
|
|
447
462
|
* STREAMING: the last `$$` token that is still unpaired AND could still pair
|
|
448
463
|
* with a `$$` not yet arrived — its span so far is short enough, carries no
|
|
@@ -451,6 +466,7 @@ declare function looksLikeDisplayMath(inner: string, flow?: boolean): boolean;
|
|
|
451
466
|
* streaming tokenizer treats it as provisional. -1 when there is none.
|
|
452
467
|
*/
|
|
453
468
|
declare function pendingDisplayMathOpener(text: string): number;
|
|
469
|
+
/** Map of `$$` opener offset → closer offset for every pair the renderer shows as math. */
|
|
454
470
|
declare function pairDisplayMath(text: string): Map<number, number>;
|
|
455
471
|
|
|
456
|
-
export { type BlockIslandType, CALLOUT_NAMES, type CodePointIndex, type DisturbedIsland, FENCE_OPENER_WHITESPACE, FENCE_WHITESPACE, type InlineIslandType, type InnerFenceLine, type IslandMeta, type IslandType, type MapOptions, type MappedPosition, type MappedRange, NESTING_FENCE_LANGUAGES, type ReadXmlTag, type SourceBlock, type SourceBlockKind, type SourceChange, type SourceEdit, type SourceIsland, type SourceSpan, SourceSpliceError, type SourceSpliceErrorCode, type SpliceIntegrity, type SpliceOptions, type SpliceResult, type TokenizeOptions, XmlContainerTracker, blockAt, blockEdit, blockRangeEdit, buildCodePointIndex, classifyInnerFenceLine, fenceNestsInnerFences, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, mapPosition, mapRange, pairDisplayMath, parseFenceOpener, pendingDisplayMathOpener, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };
|
|
472
|
+
export { type BlockIslandType, CALLOUT_NAMES, type CodePointIndex, type CodeRange, type DisturbedIsland, FENCE_OPENER_WHITESPACE, FENCE_WHITESPACE, type InlineIslandType, type InnerFenceLine, type IslandMeta, type IslandType, type MapOptions, type MappedPosition, type MappedRange, NESTING_FENCE_LANGUAGES, type ReadXmlTag, type SourceBlock, type SourceBlockKind, type SourceChange, type SourceEdit, type SourceIsland, type SourceSpan, SourceSpliceError, type SourceSpliceErrorCode, type SpliceIntegrity, type SpliceOptions, type SpliceResult, type TokenizeOptions, XmlContainerTracker, blockAt, blockEdit, blockRangeEdit, buildCodePointIndex, classifyInnerFenceLine, fenceNestsInnerFences, findCodeRanges, isMathPlaceholder, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, mapPosition, mapRange, pairDisplayMath, parseFenceOpener, pendingDisplayMathOpener, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };
|
package/dist/source.d.ts
CHANGED
|
@@ -420,21 +420,36 @@ declare function parseFenceOpener(line: string): {
|
|
|
420
420
|
} | null;
|
|
421
421
|
declare function classifyInnerFenceLine(trimmed: string, openTicks: number, nests: boolean, nestedDepth: number): InnerFenceLine;
|
|
422
422
|
|
|
423
|
+
interface CodeRange {
|
|
424
|
+
/** UTF-16 offset of the first character (the fence line start, or the opening backtick run). */
|
|
425
|
+
start: number;
|
|
426
|
+
/** Offset just past the closing fence line's last character / closing backtick run (end of text when unclosed). */
|
|
427
|
+
end: number;
|
|
428
|
+
kind: "fence" | "span";
|
|
429
|
+
}
|
|
423
430
|
/**
|
|
424
|
-
*
|
|
425
|
-
*
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
*
|
|
430
|
-
*
|
|
431
|
-
*
|
|
432
|
-
* the
|
|
433
|
-
*
|
|
434
|
-
*
|
|
435
|
-
*
|
|
436
|
-
*
|
|
431
|
+
* Where code is, by CommonMark — THE ONE code-range rule for every package.
|
|
432
|
+
* Math pairing (`pairDisplayMath`), the tokenizer's math islands, print's math
|
|
433
|
+
* lifting and kit's delimiter guard all ask this function; a second copy of
|
|
434
|
+
* code detection anywhere in `apps/shared` fails
|
|
435
|
+
* `__tests__/one-code-range-rule.test.ts`.
|
|
436
|
+
* - A fence opens only at the START of a line (≤ 3 spaces of indent): a
|
|
437
|
+
* mid-sentence "```python" is text, not a fence that swallows everything
|
|
438
|
+
* after it (verify-RC-B9: one inline ``` turned math off for the rest of
|
|
439
|
+
* the answer). Closing follows THE ONE nested-fence rule
|
|
440
|
+
* (`classifyInnerFenceLine`); an unclosed fence runs to the end.
|
|
441
|
+
* - An inline code span closes only at a backtick run of the SAME length in
|
|
442
|
+
* the same paragraph; an unmatched run is literal text.
|
|
443
|
+
* Linear: one pass over lines, one over each paragraph's backtick runs.
|
|
444
|
+
*/
|
|
445
|
+
declare function findCodeRanges(text: string): CodeRange[];
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* `$$...$$`, `$$…$$`, `$$ · $$`: a PLACEHOLDER — prose describing the syntax,
|
|
449
|
+
* never a formula. The pair is consumed whole as literal text (neither `$$`
|
|
450
|
+
* may open the next span).
|
|
437
451
|
*/
|
|
452
|
+
declare function isMathPlaceholder(inner: string): boolean;
|
|
438
453
|
/**
|
|
439
454
|
* The guard's `looksLikeMath`. `flow` = the opener is alone on its line: a
|
|
440
455
|
* flow block may span blank lines (like a fence); a `$$` with text beside it
|
|
@@ -442,7 +457,7 @@ declare function classifyInnerFenceLine(trimmed: string, openTicks: number, nest
|
|
|
442
457
|
* pairing with the next paragraph's formula.
|
|
443
458
|
*/
|
|
444
459
|
declare function looksLikeDisplayMath(inner: string, flow?: boolean): boolean;
|
|
445
|
-
|
|
460
|
+
|
|
446
461
|
/**
|
|
447
462
|
* STREAMING: the last `$$` token that is still unpaired AND could still pair
|
|
448
463
|
* with a `$$` not yet arrived — its span so far is short enough, carries no
|
|
@@ -451,6 +466,7 @@ declare function looksLikeDisplayMath(inner: string, flow?: boolean): boolean;
|
|
|
451
466
|
* streaming tokenizer treats it as provisional. -1 when there is none.
|
|
452
467
|
*/
|
|
453
468
|
declare function pendingDisplayMathOpener(text: string): number;
|
|
469
|
+
/** Map of `$$` opener offset → closer offset for every pair the renderer shows as math. */
|
|
454
470
|
declare function pairDisplayMath(text: string): Map<number, number>;
|
|
455
471
|
|
|
456
|
-
export { type BlockIslandType, CALLOUT_NAMES, type CodePointIndex, type DisturbedIsland, FENCE_OPENER_WHITESPACE, FENCE_WHITESPACE, type InlineIslandType, type InnerFenceLine, type IslandMeta, type IslandType, type MapOptions, type MappedPosition, type MappedRange, NESTING_FENCE_LANGUAGES, type ReadXmlTag, type SourceBlock, type SourceBlockKind, type SourceChange, type SourceEdit, type SourceIsland, type SourceSpan, SourceSpliceError, type SourceSpliceErrorCode, type SpliceIntegrity, type SpliceOptions, type SpliceResult, type TokenizeOptions, XmlContainerTracker, blockAt, blockEdit, blockRangeEdit, buildCodePointIndex, classifyInnerFenceLine, fenceNestsInnerFences, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, mapPosition, mapRange, pairDisplayMath, parseFenceOpener, pendingDisplayMathOpener, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };
|
|
472
|
+
export { type BlockIslandType, CALLOUT_NAMES, type CodePointIndex, type CodeRange, type DisturbedIsland, FENCE_OPENER_WHITESPACE, FENCE_WHITESPACE, type InlineIslandType, type InnerFenceLine, type IslandMeta, type IslandType, type MapOptions, type MappedPosition, type MappedRange, NESTING_FENCE_LANGUAGES, type ReadXmlTag, type SourceBlock, type SourceBlockKind, type SourceChange, type SourceEdit, type SourceIsland, type SourceSpan, SourceSpliceError, type SourceSpliceErrorCode, type SpliceIntegrity, type SpliceOptions, type SpliceResult, type TokenizeOptions, XmlContainerTracker, blockAt, blockEdit, blockRangeEdit, buildCodePointIndex, classifyInnerFenceLine, fenceNestsInnerFences, findCodeRanges, isMathPlaceholder, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, mapPosition, mapRange, pairDisplayMath, parseFenceOpener, pendingDisplayMathOpener, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };
|
package/dist/source.js
CHANGED
|
@@ -313,12 +313,167 @@ function singleDollarMathEnd(text, open, limit = text.length) {
|
|
|
313
313
|
return isSingleDollarMath(content, text[close + 1]) ? close + 1 : -1;
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
+
// source/code-ranges.ts
|
|
317
|
+
function findCodeRanges(text) {
|
|
318
|
+
const ranges = [];
|
|
319
|
+
const n = text.length;
|
|
320
|
+
let fence = null;
|
|
321
|
+
let para = -1;
|
|
322
|
+
const spans = (from, to) => {
|
|
323
|
+
const runs = [];
|
|
324
|
+
for (let k = from; k < to; ) {
|
|
325
|
+
if (text.charCodeAt(k) !== 96) {
|
|
326
|
+
k++;
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
let len = 1;
|
|
330
|
+
while (k + len < to && text.charCodeAt(k + len) === 96) len++;
|
|
331
|
+
runs.push([k, len]);
|
|
332
|
+
k += len;
|
|
333
|
+
}
|
|
334
|
+
const nextSame = new Array(runs.length).fill(-1);
|
|
335
|
+
const last = /* @__PURE__ */ new Map();
|
|
336
|
+
for (let r = runs.length - 1; r >= 0; r--) {
|
|
337
|
+
const len = runs[r][1];
|
|
338
|
+
nextSame[r] = last.get(len) ?? -1;
|
|
339
|
+
last.set(len, r);
|
|
340
|
+
}
|
|
341
|
+
for (let r = 0; r < runs.length; ) {
|
|
342
|
+
const j = nextSame[r];
|
|
343
|
+
if (j === -1) {
|
|
344
|
+
r++;
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
const [s0] = runs[r];
|
|
348
|
+
const [s1, l1] = runs[j];
|
|
349
|
+
ranges.push({ start: s0, end: s1 + l1, kind: "span" });
|
|
350
|
+
r = j + 1;
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
let pos = 0;
|
|
354
|
+
while (pos <= n) {
|
|
355
|
+
const nl = text.indexOf("\n", pos);
|
|
356
|
+
const lineEnd = nl === -1 ? n : nl;
|
|
357
|
+
const line = text.slice(pos, lineEnd);
|
|
358
|
+
let indent = 0;
|
|
359
|
+
while (indent < line.length && line[indent] === " ") indent++;
|
|
360
|
+
const body = line.slice(indent);
|
|
361
|
+
if (fence) {
|
|
362
|
+
const trimmed = trimFenceLine(line);
|
|
363
|
+
let closes = false;
|
|
364
|
+
if (fence.char === "`") {
|
|
365
|
+
const kind = classifyInnerFenceLine(trimmed, fence.len, fence.nests, fence.depth);
|
|
366
|
+
if (kind === "open-nested") fence.depth++;
|
|
367
|
+
else if (kind === "close-nested") fence.depth--;
|
|
368
|
+
else if (kind === "close-outer") closes = indent <= 3;
|
|
369
|
+
} else {
|
|
370
|
+
let t = 0;
|
|
371
|
+
while (t < trimmed.length && trimmed[t] === "~") t++;
|
|
372
|
+
closes = indent <= 3 && t >= fence.len && trimFenceLine(trimmed.slice(t)) === "";
|
|
373
|
+
}
|
|
374
|
+
if (closes) {
|
|
375
|
+
ranges.push({ start: fence.start, end: lineEnd, kind: "fence" });
|
|
376
|
+
fence = null;
|
|
377
|
+
}
|
|
378
|
+
} else {
|
|
379
|
+
const opener = indent <= 3 ? /^(`{3,}|~{3,})(.*)$/.exec(body) : null;
|
|
380
|
+
const info = opener ? opener[2] : "";
|
|
381
|
+
if (opener && !(opener[1][0] === "`" && info.includes("`"))) {
|
|
382
|
+
if (para !== -1) spans(para, pos);
|
|
383
|
+
para = -1;
|
|
384
|
+
const char = opener[1][0];
|
|
385
|
+
const parsed = char === "`" ? parseFenceOpener(line) : null;
|
|
386
|
+
fence = { char, len: opener[1].length, start: pos, nests: fenceNestsInnerFences(parsed?.lang), depth: 0 };
|
|
387
|
+
} else if (body.trim() === "") {
|
|
388
|
+
if (para !== -1) spans(para, pos);
|
|
389
|
+
para = -1;
|
|
390
|
+
} else if (para === -1) para = pos;
|
|
391
|
+
}
|
|
392
|
+
if (nl === -1) break;
|
|
393
|
+
pos = nl + 1;
|
|
394
|
+
}
|
|
395
|
+
if (fence) ranges.push({ start: fence.start, end: n, kind: "fence" });
|
|
396
|
+
else if (para !== -1) spans(para, n);
|
|
397
|
+
return ranges.sort((a, b) => a.start - b.start);
|
|
398
|
+
}
|
|
399
|
+
function pendingCodeSpanStart(text) {
|
|
400
|
+
const n = text.length;
|
|
401
|
+
if (n === 0 || /\n[ \t]*\n[ \t]*$/.test(text)) return -1;
|
|
402
|
+
let fence = null;
|
|
403
|
+
let para = -1;
|
|
404
|
+
let pos = 0;
|
|
405
|
+
while (pos <= n) {
|
|
406
|
+
const nl = text.indexOf("\n", pos);
|
|
407
|
+
const lineEnd = nl === -1 ? n : nl;
|
|
408
|
+
const line = text.slice(pos, lineEnd);
|
|
409
|
+
let indent = 0;
|
|
410
|
+
while (indent < line.length && line[indent] === " ") indent++;
|
|
411
|
+
const body = line.slice(indent);
|
|
412
|
+
if (fence) {
|
|
413
|
+
const trimmed = trimFenceLine(line);
|
|
414
|
+
let closes = false;
|
|
415
|
+
if (fence.char === "`") {
|
|
416
|
+
const kind = classifyInnerFenceLine(trimmed, fence.len, fence.nests, fence.depth);
|
|
417
|
+
if (kind === "open-nested") fence.depth++;
|
|
418
|
+
else if (kind === "close-nested") fence.depth--;
|
|
419
|
+
else if (kind === "close-outer") closes = indent <= 3;
|
|
420
|
+
} else {
|
|
421
|
+
let t = 0;
|
|
422
|
+
while (t < trimmed.length && trimmed[t] === "~") t++;
|
|
423
|
+
closes = indent <= 3 && t >= fence.len && trimFenceLine(trimmed.slice(t)) === "";
|
|
424
|
+
}
|
|
425
|
+
if (closes) fence = null;
|
|
426
|
+
} else {
|
|
427
|
+
const opener = indent <= 3 ? /^(`{3,}|~{3,})(.*)$/.exec(body) : null;
|
|
428
|
+
const info = opener ? opener[2] : "";
|
|
429
|
+
if (opener && !(opener[1][0] === "`" && info.includes("`"))) {
|
|
430
|
+
para = -1;
|
|
431
|
+
const char = opener[1][0];
|
|
432
|
+
const parsed = char === "`" ? parseFenceOpener(line) : null;
|
|
433
|
+
fence = { char, len: opener[1].length, nests: fenceNestsInnerFences(parsed?.lang), depth: 0 };
|
|
434
|
+
} else if (body.trim() === "") {
|
|
435
|
+
if (!(nl === -1 && line === "")) para = -1;
|
|
436
|
+
} else if (para === -1) para = pos;
|
|
437
|
+
}
|
|
438
|
+
if (nl === -1) break;
|
|
439
|
+
pos = nl + 1;
|
|
440
|
+
}
|
|
441
|
+
if (fence || para === -1) return -1;
|
|
442
|
+
const runs = [];
|
|
443
|
+
for (let k = para; k < n; ) {
|
|
444
|
+
if (text.charCodeAt(k) !== 96) {
|
|
445
|
+
k++;
|
|
446
|
+
continue;
|
|
447
|
+
}
|
|
448
|
+
let len = 1;
|
|
449
|
+
while (k + len < n && text.charCodeAt(k + len) === 96) len++;
|
|
450
|
+
runs.push([k, len]);
|
|
451
|
+
k += len;
|
|
452
|
+
}
|
|
453
|
+
const growing = (r) => {
|
|
454
|
+
const [start, len] = runs[r];
|
|
455
|
+
return start + len === n;
|
|
456
|
+
};
|
|
457
|
+
for (let r = 0; r < runs.length; ) {
|
|
458
|
+
if (growing(r)) return runs[r][0];
|
|
459
|
+
const len = runs[r][1];
|
|
460
|
+
let j = r + 1;
|
|
461
|
+
while (j < runs.length && (runs[j][1] !== len || growing(j))) j++;
|
|
462
|
+
if (j >= runs.length) return runs[r][0];
|
|
463
|
+
r = j + 1;
|
|
464
|
+
}
|
|
465
|
+
return -1;
|
|
466
|
+
}
|
|
467
|
+
|
|
316
468
|
// source/math-pairs.ts
|
|
317
469
|
var MAX_MATH_SPAN = 600;
|
|
318
470
|
var STRUCTURAL_MARKDOWN = /\]\(|https?:\/\/|\*\*|(?:^|\n)[ \t]{0,3}#{1,6}[ \t]|(?:^|\n)[ \t]*[-*+][ \t]+|(?:^|\n)[ \t]*\d+[.)][ \t]/;
|
|
319
471
|
var LATEX_COMMAND = /\\[a-zA-Z]/;
|
|
320
472
|
var PROSE_WORD = /[A-Za-z]{3,}/g;
|
|
321
473
|
var PROSE_WORD_LIMIT = 6;
|
|
474
|
+
function isMathPlaceholder(inner) {
|
|
475
|
+
return /^[\s.…·⋯_-]*$/.test(inner) && /[.…·⋯]/.test(inner);
|
|
476
|
+
}
|
|
322
477
|
function opensFlowBlock(text, open) {
|
|
323
478
|
for (let k = open - 1; k >= 0 && text[k] !== "\n"; k--) if (text[k] !== " " && text[k] !== " ") return false;
|
|
324
479
|
for (let k = open + 2; k < text.length && text[k] !== "\n"; k++) if (text[k] !== " " && text[k] !== " " && text[k] !== "\r") return false;
|
|
@@ -336,15 +491,7 @@ function looksLikeDisplayMath(inner, flow = false) {
|
|
|
336
491
|
return (s.match(PROSE_WORD) ?? []).length < PROSE_WORD_LIMIT;
|
|
337
492
|
}
|
|
338
493
|
function codeRanges(text) {
|
|
339
|
-
|
|
340
|
-
for (const re of [/```[\s\S]*?(?:```|$)/g, /~~~[\s\S]*?(?:~~~|$)/g, /`[^`\n]*`/g]) {
|
|
341
|
-
let m;
|
|
342
|
-
while ((m = re.exec(text)) !== null) {
|
|
343
|
-
ranges.push([m.index, m.index + m[0].length]);
|
|
344
|
-
if (m[0].length === 0) re.lastIndex++;
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
return ranges.sort((a, b) => a[0] - b[0]);
|
|
494
|
+
return findCodeRanges(text).map((r) => [r.start, r.end]);
|
|
348
495
|
}
|
|
349
496
|
function pendingDisplayMathOpener(text) {
|
|
350
497
|
if (!text.includes("$$")) return -1;
|
|
@@ -366,6 +513,10 @@ function pendingDisplayMathOpener(text) {
|
|
|
366
513
|
const open = tokens[j];
|
|
367
514
|
const close = tokens[j + 1];
|
|
368
515
|
if (close === void 0) break;
|
|
516
|
+
if (isMathPlaceholder(text.slice(open + 2, close))) {
|
|
517
|
+
j += 2;
|
|
518
|
+
continue;
|
|
519
|
+
}
|
|
369
520
|
if (looksLikeDisplayMath(text.slice(open + 2, close), opensFlowBlock(text, open))) {
|
|
370
521
|
paired.add(open);
|
|
371
522
|
paired.add(close);
|
|
@@ -410,6 +561,10 @@ function pairDisplayMath(text) {
|
|
|
410
561
|
const open = tokens[j];
|
|
411
562
|
const close = tokens[j + 1];
|
|
412
563
|
if (close === void 0) break;
|
|
564
|
+
if (isMathPlaceholder(text.slice(open + 2, close))) {
|
|
565
|
+
j += 2;
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
413
568
|
if (looksLikeDisplayMath(text.slice(open + 2, close), opensFlowBlock(text, open))) {
|
|
414
569
|
pairs.set(open, close);
|
|
415
570
|
j += 2;
|
|
@@ -747,6 +902,27 @@ var Tokenizer = class {
|
|
|
747
902
|
this.mathPairs = pairDisplayMath(text);
|
|
748
903
|
this.provisionalFrom = streaming ? pendingDisplayMathOpener(text) : -1;
|
|
749
904
|
if (this.provisionalFrom === -1) this.provisionalFrom = Number.POSITIVE_INFINITY;
|
|
905
|
+
if (streaming && text.includes("$$")) {
|
|
906
|
+
const span = pendingCodeSpanStart(text);
|
|
907
|
+
if (span !== -1) {
|
|
908
|
+
const firstToken = text.indexOf("$$", span);
|
|
909
|
+
if (firstToken !== -1) this.provisionalFrom = Math.min(this.provisionalFrom, firstToken);
|
|
910
|
+
for (const [open, close] of this.mathPairs) {
|
|
911
|
+
if (close >= span) this.provisionalFrom = Math.min(this.provisionalFrom, open);
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
for (const pad of ["`", "``", "```", "~~~"]) {
|
|
915
|
+
const alt = pairDisplayMath(text + pad);
|
|
916
|
+
for (const [open, close] of this.mathPairs) {
|
|
917
|
+
if (alt.get(open) !== close) this.provisionalFrom = Math.min(this.provisionalFrom, open);
|
|
918
|
+
}
|
|
919
|
+
for (const [open, close] of alt) {
|
|
920
|
+
if (close < text.length && this.mathPairs.get(open) !== close) {
|
|
921
|
+
this.provisionalFrom = Math.min(this.provisionalFrom, open);
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
}
|
|
750
926
|
let start = 0;
|
|
751
927
|
for (let i = 0; i < text.length; i++) {
|
|
752
928
|
if (text.charCodeAt(i) === 10) {
|
|
@@ -787,13 +963,17 @@ var Tokenizer = class {
|
|
|
787
963
|
/**
|
|
788
964
|
* Streaming: an open last line that begins with `{` is undecided — each new
|
|
789
965
|
* byte can balance or unbalance its braces and flip the whole line between
|
|
790
|
-
* prose and a JSON island — so
|
|
966
|
+
* prose and a JSON island — and so is a line that is exactly one allowed
|
|
967
|
+
* HTML tag so far; both are provisional until they end (G5).
|
|
791
968
|
*/
|
|
792
969
|
markOpenJsonTail() {
|
|
793
970
|
const last = this.lineStarts.length - 1;
|
|
794
971
|
if (!this.isOpenTail(last)) return;
|
|
795
972
|
const start = this.lineStarts[last];
|
|
796
|
-
|
|
973
|
+
const t = this.lineText(last).trim();
|
|
974
|
+
const oneTag = t.startsWith("<") ? readXmlTag(t, 0) : null;
|
|
975
|
+
const loneTag = !!oneTag && oneTag.raw === t && ALLOWED_RAW_HTML_TAGS.has(oneTag.tagName.toLowerCase());
|
|
976
|
+
if (t.startsWith("{") || loneTag) {
|
|
797
977
|
this.provisionalFrom = Math.min(this.provisionalFrom, start);
|
|
798
978
|
}
|
|
799
979
|
}
|
|
@@ -1086,11 +1266,17 @@ var Tokenizer = class {
|
|
|
1086
1266
|
last = k;
|
|
1087
1267
|
continue;
|
|
1088
1268
|
}
|
|
1269
|
+
if (this.isOpenTail(k)) return this.heldFootnote(p, open[1]);
|
|
1089
1270
|
if (FOOTNOTE_DEF.test(line.trimStart()) || this.detectBlock(this.lineStarts[k], k, false)) break;
|
|
1090
|
-
if (this.isOpenTail(k)) break;
|
|
1091
1271
|
last = k;
|
|
1092
1272
|
}
|
|
1093
|
-
|
|
1273
|
+
const end = this.contentEnds[last];
|
|
1274
|
+
if (this.paragraphMayGrow(end)) return this.heldFootnote(p, open[1]);
|
|
1275
|
+
return this.island("footnote_def", p, end, true, { id: open[1] });
|
|
1276
|
+
}
|
|
1277
|
+
/** A footnote whose continuation is still arriving: open to the end of the text. */
|
|
1278
|
+
heldFootnote(p, id) {
|
|
1279
|
+
return this.island("footnote_def", p, this.n, false, { id });
|
|
1094
1280
|
}
|
|
1095
1281
|
/**
|
|
1096
1282
|
* Backtick fence — the renderer splitter's close rules: JSON-string aware for
|
|
@@ -1334,7 +1520,12 @@ var Tokenizer = class {
|
|
|
1334
1520
|
return this.island("html_block", p, close.index + close[0].length, true, { tag: name });
|
|
1335
1521
|
}
|
|
1336
1522
|
const typeSix = HTML_BLOCK_LEVEL_TAGS.has(name);
|
|
1337
|
-
const
|
|
1523
|
+
const loneTag = atParaStart && t.trimEnd() === tag.raw;
|
|
1524
|
+
if (loneTag && this.isOpenTail(li)) {
|
|
1525
|
+
this.provisionalFrom = Math.min(this.provisionalFrom, p);
|
|
1526
|
+
return null;
|
|
1527
|
+
}
|
|
1528
|
+
const typeSeven = loneTag;
|
|
1338
1529
|
if (!typeSix && !typeSeven) return null;
|
|
1339
1530
|
let end = this.contentEnds[li];
|
|
1340
1531
|
for (let k = li + 1; k < this.lineCount && !this.lineIsBlank(k); k++) {
|
|
@@ -1426,10 +1617,6 @@ var Tokenizer = class {
|
|
|
1426
1617
|
let breakLine = -1;
|
|
1427
1618
|
for (let k = li + 1; k < this.lineCount; k++) {
|
|
1428
1619
|
if (this.lineIsBlank(k)) break;
|
|
1429
|
-
if (this.lineStarts[k] >= this.provisionalFrom) {
|
|
1430
|
-
end = this.n;
|
|
1431
|
-
break;
|
|
1432
|
-
}
|
|
1433
1620
|
if (this.detectBlock(this.lineStarts[k], k, false)) {
|
|
1434
1621
|
breakLine = k;
|
|
1435
1622
|
break;
|
|
@@ -1572,7 +1759,11 @@ var Tokenizer = class {
|
|
|
1572
1759
|
}
|
|
1573
1760
|
const end = singleDollarMathEnd(text, i, pe);
|
|
1574
1761
|
this.tick(end > 0 ? end - i : Math.min(403, pe - i));
|
|
1575
|
-
if (end > 0 &&
|
|
1762
|
+
if (end > 0 && this.streaming && end === this.n) {
|
|
1763
|
+
this.provisionalFrom = Math.min(this.provisionalFrom, i);
|
|
1764
|
+
return { inlines, breakIsland: null, orphan: false };
|
|
1765
|
+
}
|
|
1766
|
+
if (end > 0) {
|
|
1576
1767
|
inlines.push(this.island("math_inline", i, end, true, { delimiter: "$" }));
|
|
1577
1768
|
i = end;
|
|
1578
1769
|
continue;
|
|
@@ -2063,6 +2254,6 @@ function mapRange(changes, start, end, unit = "utf16") {
|
|
|
2063
2254
|
return { start: newStart, end: newEnd, touched, collapsed: newEnd === newStart && end > start };
|
|
2064
2255
|
}
|
|
2065
2256
|
|
|
2066
|
-
export { CALLOUT_NAMES, FENCE_OPENER_WHITESPACE, FENCE_WHITESPACE, NESTING_FENCE_LANGUAGES, SourceSpliceError, XmlContainerTracker, blockAt, blockEdit, blockRangeEdit, buildCodePointIndex, classifyInnerFenceLine, fenceNestsInnerFences, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, mapPosition, mapRange, pairDisplayMath, parseFenceOpener, pendingDisplayMathOpener, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };
|
|
2257
|
+
export { CALLOUT_NAMES, FENCE_OPENER_WHITESPACE, FENCE_WHITESPACE, NESTING_FENCE_LANGUAGES, SourceSpliceError, XmlContainerTracker, blockAt, blockEdit, blockRangeEdit, buildCodePointIndex, classifyInnerFenceLine, fenceNestsInnerFences, findCodeRanges, isMathPlaceholder, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, mapPosition, mapRange, pairDisplayMath, parseFenceOpener, pendingDisplayMathOpener, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };
|
|
2067
2258
|
//# sourceMappingURL=source.js.map
|
|
2068
2259
|
//# sourceMappingURL=source.js.map
|