@ai-matrx/content-ir 0.18.4 → 0.18.6
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 +62 -1
- package/README.md +3 -1
- package/dist/index.cjs +211 -29
- 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 +210 -30
- package/dist/index.js.map +1 -1
- package/dist/source.cjs +211 -29
- package/dist/source.cjs.map +1 -1
- package/dist/source.d.cts +24 -2
- package/dist/source.d.ts +24 -2
- package/dist/source.js +210 -30
- package/dist/source.js.map +1 -1
- package/package.json +1 -1
package/dist/source.d.cts
CHANGED
|
@@ -328,7 +328,14 @@ declare function toUtf16Offset(text: string, codePoint: number): number;
|
|
|
328
328
|
* - a placeholder (`$...$`);
|
|
329
329
|
* - prose, unless a TeX command or operator says otherwise: two plain
|
|
330
330
|
* words (`$Tipping (fee)$`), a contraction (`$I'm$`, never `$X'Y$`), an
|
|
331
|
-
* abbreviation (`$e.g. (x)$`)
|
|
331
|
+
* abbreviation (`$e.g. (x)$`);
|
|
332
|
+
* - a shell or template variable chain (`$USER$HOSTNAME`, `$name.$ext`,
|
|
333
|
+
* `${a}${b}`) — {@link isVariableChain}.
|
|
334
|
+
*
|
|
335
|
+
* `after` is the text right after the closing `$` — {@link singleDollarAfter}
|
|
336
|
+
* (up to {@link AFTER_WINDOW} characters; `\n` marks the end of the text). A single character still
|
|
337
|
+
* applies the Pandoc digit rule, but the variable-chain guard needs the
|
|
338
|
+
* whole following name.
|
|
332
339
|
*/
|
|
333
340
|
declare function isSingleDollarMath(content: string, after: string | undefined): boolean;
|
|
334
341
|
/**
|
|
@@ -348,6 +355,14 @@ declare function looksLikeOpenInlineMath(partial: string): boolean;
|
|
|
348
355
|
* closer is a `$` not followed by another `$`, and the content passes
|
|
349
356
|
* {@link isSingleDollarMath}. Returns the offset just past the closing `$`.
|
|
350
357
|
*/
|
|
358
|
+
/** How much text after a closing `$` the rule reads (a glued suffix or the next variable name). */
|
|
359
|
+
declare const AFTER_WINDOW = 32;
|
|
360
|
+
/**
|
|
361
|
+
* The `after` argument of {@link isSingleDollarMath} for the closing `$` at
|
|
362
|
+
* `close`: the next {@link AFTER_WINDOW} characters, with a `\n` standing for
|
|
363
|
+
* the end of the text (so `$A$B` at the very end reads the whole name `B`).
|
|
364
|
+
*/
|
|
365
|
+
declare function singleDollarAfter(text: string, close: number): string;
|
|
351
366
|
declare function singleDollarMathEnd(text: string, open: number, limit?: number): number;
|
|
352
367
|
/**
|
|
353
368
|
* THE escaped-bracket rule — whether a closed `\[ … \]` is display math or
|
|
@@ -476,6 +491,13 @@ interface FenceLines {
|
|
|
476
491
|
line(k: number): string | null;
|
|
477
492
|
/** Streaming: line `k` has not ended yet, so it closes nothing. */
|
|
478
493
|
openTail?(k: number): boolean;
|
|
494
|
+
/**
|
|
495
|
+
* Streaming: more lines may still arrive. The strict-CommonMark retry
|
|
496
|
+
* applies only while the nested reading ends inside a nested fence — a
|
|
497
|
+
* later line can close that nested fence, so a retry's closer is
|
|
498
|
+
* undecided and the fence stays open (verify-RC-B3 F3).
|
|
499
|
+
*/
|
|
500
|
+
streaming?: boolean;
|
|
479
501
|
}
|
|
480
502
|
interface FenceEnd {
|
|
481
503
|
/** The closing line when `closed`; otherwise the fence's last line (text end, or the line before its container ended). */
|
|
@@ -585,4 +607,4 @@ declare function pendingDisplayMathOpener(text: string): number;
|
|
|
585
607
|
/** Map of `$$` opener offset → closer offset for every pair the renderer shows as math. */
|
|
586
608
|
declare function pairDisplayMath(text: string): Map<number, number>;
|
|
587
609
|
|
|
588
|
-
export { BacktickRuns, type BlockIslandType, CALLOUT_NAMES, type CodePointIndex, type CodeRange, type DisturbedIsland, FENCE_OPENER_WHITESPACE, FENCE_WHITESPACE, type FenceEnd, type FenceLineKind, type FenceLines, type FenceOpener, FenceReader, 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, closeFence, codeSpanText, fenceLineKinds, fenceNestsInnerFences, fenceOpenerOf, fenceParts, findCodeRanges, isEscapedBracketMath, isMathPlaceholder, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, looksLikeOpenInlineMath, mapCodeRanges, mapPosition, mapRange, pairDisplayMath, parseFenceOpener, pendingDisplayMathOpener, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };
|
|
610
|
+
export { AFTER_WINDOW, BacktickRuns, type BlockIslandType, CALLOUT_NAMES, type CodePointIndex, type CodeRange, type DisturbedIsland, FENCE_OPENER_WHITESPACE, FENCE_WHITESPACE, type FenceEnd, type FenceLineKind, type FenceLines, type FenceOpener, FenceReader, 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, closeFence, codeSpanText, fenceLineKinds, fenceNestsInnerFences, fenceOpenerOf, fenceParts, findCodeRanges, isEscapedBracketMath, isMathPlaceholder, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, looksLikeOpenInlineMath, mapCodeRanges, mapPosition, mapRange, pairDisplayMath, parseFenceOpener, pendingDisplayMathOpener, readXmlTag, singleDollarAfter, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };
|
package/dist/source.d.ts
CHANGED
|
@@ -328,7 +328,14 @@ declare function toUtf16Offset(text: string, codePoint: number): number;
|
|
|
328
328
|
* - a placeholder (`$...$`);
|
|
329
329
|
* - prose, unless a TeX command or operator says otherwise: two plain
|
|
330
330
|
* words (`$Tipping (fee)$`), a contraction (`$I'm$`, never `$X'Y$`), an
|
|
331
|
-
* abbreviation (`$e.g. (x)$`)
|
|
331
|
+
* abbreviation (`$e.g. (x)$`);
|
|
332
|
+
* - a shell or template variable chain (`$USER$HOSTNAME`, `$name.$ext`,
|
|
333
|
+
* `${a}${b}`) — {@link isVariableChain}.
|
|
334
|
+
*
|
|
335
|
+
* `after` is the text right after the closing `$` — {@link singleDollarAfter}
|
|
336
|
+
* (up to {@link AFTER_WINDOW} characters; `\n` marks the end of the text). A single character still
|
|
337
|
+
* applies the Pandoc digit rule, but the variable-chain guard needs the
|
|
338
|
+
* whole following name.
|
|
332
339
|
*/
|
|
333
340
|
declare function isSingleDollarMath(content: string, after: string | undefined): boolean;
|
|
334
341
|
/**
|
|
@@ -348,6 +355,14 @@ declare function looksLikeOpenInlineMath(partial: string): boolean;
|
|
|
348
355
|
* closer is a `$` not followed by another `$`, and the content passes
|
|
349
356
|
* {@link isSingleDollarMath}. Returns the offset just past the closing `$`.
|
|
350
357
|
*/
|
|
358
|
+
/** How much text after a closing `$` the rule reads (a glued suffix or the next variable name). */
|
|
359
|
+
declare const AFTER_WINDOW = 32;
|
|
360
|
+
/**
|
|
361
|
+
* The `after` argument of {@link isSingleDollarMath} for the closing `$` at
|
|
362
|
+
* `close`: the next {@link AFTER_WINDOW} characters, with a `\n` standing for
|
|
363
|
+
* the end of the text (so `$A$B` at the very end reads the whole name `B`).
|
|
364
|
+
*/
|
|
365
|
+
declare function singleDollarAfter(text: string, close: number): string;
|
|
351
366
|
declare function singleDollarMathEnd(text: string, open: number, limit?: number): number;
|
|
352
367
|
/**
|
|
353
368
|
* THE escaped-bracket rule — whether a closed `\[ … \]` is display math or
|
|
@@ -476,6 +491,13 @@ interface FenceLines {
|
|
|
476
491
|
line(k: number): string | null;
|
|
477
492
|
/** Streaming: line `k` has not ended yet, so it closes nothing. */
|
|
478
493
|
openTail?(k: number): boolean;
|
|
494
|
+
/**
|
|
495
|
+
* Streaming: more lines may still arrive. The strict-CommonMark retry
|
|
496
|
+
* applies only while the nested reading ends inside a nested fence — a
|
|
497
|
+
* later line can close that nested fence, so a retry's closer is
|
|
498
|
+
* undecided and the fence stays open (verify-RC-B3 F3).
|
|
499
|
+
*/
|
|
500
|
+
streaming?: boolean;
|
|
479
501
|
}
|
|
480
502
|
interface FenceEnd {
|
|
481
503
|
/** The closing line when `closed`; otherwise the fence's last line (text end, or the line before its container ended). */
|
|
@@ -585,4 +607,4 @@ declare function pendingDisplayMathOpener(text: string): number;
|
|
|
585
607
|
/** Map of `$$` opener offset → closer offset for every pair the renderer shows as math. */
|
|
586
608
|
declare function pairDisplayMath(text: string): Map<number, number>;
|
|
587
609
|
|
|
588
|
-
export { BacktickRuns, type BlockIslandType, CALLOUT_NAMES, type CodePointIndex, type CodeRange, type DisturbedIsland, FENCE_OPENER_WHITESPACE, FENCE_WHITESPACE, type FenceEnd, type FenceLineKind, type FenceLines, type FenceOpener, FenceReader, 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, closeFence, codeSpanText, fenceLineKinds, fenceNestsInnerFences, fenceOpenerOf, fenceParts, findCodeRanges, isEscapedBracketMath, isMathPlaceholder, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, looksLikeOpenInlineMath, mapCodeRanges, mapPosition, mapRange, pairDisplayMath, parseFenceOpener, pendingDisplayMathOpener, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };
|
|
610
|
+
export { AFTER_WINDOW, BacktickRuns, type BlockIslandType, CALLOUT_NAMES, type CodePointIndex, type CodeRange, type DisturbedIsland, FENCE_OPENER_WHITESPACE, FENCE_WHITESPACE, type FenceEnd, type FenceLineKind, type FenceLines, type FenceOpener, FenceReader, 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, closeFence, codeSpanText, fenceLineKinds, fenceNestsInnerFences, fenceOpenerOf, fenceParts, findCodeRanges, isEscapedBracketMath, isMathPlaceholder, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, looksLikeOpenInlineMath, mapCodeRanges, mapPosition, mapRange, pairDisplayMath, parseFenceOpener, pendingDisplayMathOpener, readXmlTag, singleDollarAfter, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };
|
package/dist/source.js
CHANGED
|
@@ -321,6 +321,7 @@ var FenceReader = class {
|
|
|
321
321
|
function closeFence(src, open, opener) {
|
|
322
322
|
const first = readFence(src, open, new FenceReader(opener));
|
|
323
323
|
if (first.closed || !first.reader.sawNested || first.reader.nestedDepth <= 0) return { line: first.line, closed: first.closed };
|
|
324
|
+
if (src.streaming) return { line: first.line, closed: false };
|
|
324
325
|
const strict = readFence(src, open, new FenceReader(opener, { nesting: false }));
|
|
325
326
|
return { line: strict.line, closed: strict.closed };
|
|
326
327
|
}
|
|
@@ -584,6 +585,8 @@ function fenceLineKinds(text) {
|
|
|
584
585
|
function pendingCodeSpanStart(text) {
|
|
585
586
|
const n = text.length;
|
|
586
587
|
if (n === 0 || /\n[ \t]*\n[ \t]*$/.test(text)) return -1;
|
|
588
|
+
const lastLine = text.slice(text.lastIndexOf("\n") + 1);
|
|
589
|
+
if (lastLine && /^(?: {0,3}>[ \t]?)*[ \t]*$/.test(lastLine)) return pendingCodeSpanStart(`${text}x`);
|
|
587
590
|
const s = scan(text);
|
|
588
591
|
const para = s.pendingPara;
|
|
589
592
|
if (s.endsInFence || para === -1) return -1;
|
|
@@ -730,13 +733,26 @@ var MATH_SHAPE_CHARS = /^[A-Za-z0-9'\s(),.*\/-]+$/;
|
|
|
730
733
|
function isSingleDollarMath(content, after) {
|
|
731
734
|
if (!content || content.length > 400) return false;
|
|
732
735
|
if (/^\s/.test(content) || /\s$/.test(content)) return false;
|
|
733
|
-
if (after !== void 0 &&
|
|
736
|
+
if (after !== void 0 && /^[0-9]/.test(after)) return false;
|
|
737
|
+
if (isVariableChain(content, after)) return false;
|
|
734
738
|
if (/(?:^|[^\\])%/.test(content)) return false;
|
|
735
739
|
if (/^[)\]}"/]/.test(content) || /[(\[{":;,/]$/.test(content)) return false;
|
|
736
|
-
if (/^[0-9]/.test(content) && after !== void 0 &&
|
|
740
|
+
if (/^[0-9]/.test(content) && after !== void 0 && /^[A-Za-z]/.test(after)) return false;
|
|
737
741
|
if (isMathPlaceholder(content)) return false;
|
|
738
742
|
return TEX_SIGNAL.test(content) || !readsAsProse(content);
|
|
739
743
|
}
|
|
744
|
+
var IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
745
|
+
var MATH_SUFFIX = /^(?:s|es|th|st|nd|rd)$/i;
|
|
746
|
+
function isVariableChain(content, after) {
|
|
747
|
+
if (/^\{[A-Za-z_][\w.]*\}$/.test(content)) return true;
|
|
748
|
+
if (!after) return false;
|
|
749
|
+
if (after[0] === "{") return IDENTIFIER.test(content);
|
|
750
|
+
const run = /^[A-Za-z0-9_]+/.exec(after)?.[0];
|
|
751
|
+
if (!run) return false;
|
|
752
|
+
if (after.length === 1) return false;
|
|
753
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*[.@-]$/.test(content)) return true;
|
|
754
|
+
return IDENTIFIER.test(content) && !MATH_SUFFIX.test(run);
|
|
755
|
+
}
|
|
740
756
|
var FUNCTION_NAMES = /* @__PURE__ */ new Set([
|
|
741
757
|
"sin",
|
|
742
758
|
"cos",
|
|
@@ -780,6 +796,12 @@ function isMathShape(content) {
|
|
|
780
796
|
if (/[A-Za-z]'+[A-Za-z]/.test(content) || /(?:^|[\s(,])[A-Za-z]\.(?:[A-Za-z]\.|\s|$)/.test(content)) return false;
|
|
781
797
|
return /[A-Za-z]'*\(|[A-Za-z]'|\b[A-Za-z]\s+[A-Za-z]\b|\([^)]*[A-Za-z][^)]*\)/.test(content);
|
|
782
798
|
}
|
|
799
|
+
var AFTER_WINDOW = 32;
|
|
800
|
+
function singleDollarAfter(text, close) {
|
|
801
|
+
const rest = text.slice(close + 1, close + 1 + AFTER_WINDOW);
|
|
802
|
+
return rest.length < AFTER_WINDOW ? `${rest}
|
|
803
|
+
` : rest;
|
|
804
|
+
}
|
|
783
805
|
function singleDollarMathEnd(text, open, limit = text.length) {
|
|
784
806
|
const bound = Math.min(limit, open + 403);
|
|
785
807
|
let close = -1;
|
|
@@ -797,7 +819,7 @@ function singleDollarMathEnd(text, open, limit = text.length) {
|
|
|
797
819
|
}
|
|
798
820
|
if (close === -1 || text[close + 1] === "$") return -1;
|
|
799
821
|
const content = text.slice(open + 1, close);
|
|
800
|
-
return isSingleDollarMath(content, text
|
|
822
|
+
return isSingleDollarMath(content, singleDollarAfter(text, close)) ? close + 1 : -1;
|
|
801
823
|
}
|
|
802
824
|
var BRACKET_TEX_SIGNAL = /\\[A-Za-z]+|[\^{}=<>+]|_\{|(?:^|[^A-Za-z0-9])[A-Za-z]_[A-Za-z0-9](?![A-Za-z0-9])/;
|
|
803
825
|
function isEscapedBracketMath(content, before) {
|
|
@@ -1168,18 +1190,14 @@ var Tokenizer = class {
|
|
|
1168
1190
|
/**
|
|
1169
1191
|
* Streaming: an open last line that begins with `{` is undecided — each new
|
|
1170
1192
|
* byte can balance or unbalance its braces and flip the whole line between
|
|
1171
|
-
* prose and a JSON island —
|
|
1172
|
-
* HTML tag
|
|
1193
|
+
* prose and a JSON island — so it is provisional until it ends (G5).
|
|
1194
|
+
* (A lone HTML tag on that line is held by {@link holdUndecidedTail}.)
|
|
1173
1195
|
*/
|
|
1174
1196
|
markOpenJsonTail() {
|
|
1175
1197
|
const last = this.lineStarts.length - 1;
|
|
1176
1198
|
if (!this.isOpenTail(last)) return;
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
const oneTag = t.startsWith("<") ? readXmlTag(t, 0) : null;
|
|
1180
|
-
const loneTag = !!oneTag && oneTag.raw === t && ALLOWED_RAW_HTML_TAGS.has(oneTag.tagName.toLowerCase());
|
|
1181
|
-
if (t.startsWith("{") || loneTag) {
|
|
1182
|
-
this.provisionalFrom = Math.min(this.provisionalFrom, start);
|
|
1199
|
+
if (this.lineText(last).trim().startsWith("{")) {
|
|
1200
|
+
this.provisionalFrom = Math.min(this.provisionalFrom, this.lineStarts[last]);
|
|
1183
1201
|
}
|
|
1184
1202
|
}
|
|
1185
1203
|
/**
|
|
@@ -1212,11 +1230,25 @@ var Tokenizer = class {
|
|
|
1212
1230
|
/** Streaming only: a paragraph ending at `pe` may still be continued by a line not yet arrived. */
|
|
1213
1231
|
paragraphMayGrow(pe) {
|
|
1214
1232
|
if (!this.streaming) return false;
|
|
1233
|
+
if (this.undecidedBreaks.has(pe)) return true;
|
|
1215
1234
|
const rest = this.n - pe;
|
|
1216
1235
|
if (rest === 0) return true;
|
|
1217
1236
|
const tail = this.text.slice(pe);
|
|
1218
|
-
return
|
|
1237
|
+
return /^(?:\r\n|\r|\n)[ \t]*$/.test(tail);
|
|
1219
1238
|
}
|
|
1239
|
+
/**
|
|
1240
|
+
* Streaming: an open block that may still turn back into prose — a `$$`
|
|
1241
|
+
* pair whose closer is on the open last line (prose after it makes it
|
|
1242
|
+
* inline), a JSON head whose braces have not balanced (it may never parse),
|
|
1243
|
+
* or any opener that is itself still arriving on the open last line.
|
|
1244
|
+
*/
|
|
1245
|
+
mayDissolve(block) {
|
|
1246
|
+
if (!this.streaming || block.complete) return false;
|
|
1247
|
+
if (block.type === "math_block" || block.type === "json") return true;
|
|
1248
|
+
return this.isOpenTail(this.lineOf(block.start));
|
|
1249
|
+
}
|
|
1250
|
+
/** Streaming: paragraph ends where an undecided, dissolvable block cut them short. */
|
|
1251
|
+
undecidedBreaks = /* @__PURE__ */ new Set();
|
|
1220
1252
|
/** Streaming only: the final line, still waiting for its terminator. */
|
|
1221
1253
|
isOpenTail(k) {
|
|
1222
1254
|
return this.streaming && k === this.lineStarts.length - 1 && (this.lineEnds[k] === this.contentEnds[k] || this.pendingCR);
|
|
@@ -1234,6 +1266,12 @@ var Tokenizer = class {
|
|
|
1234
1266
|
}
|
|
1235
1267
|
return lo;
|
|
1236
1268
|
}
|
|
1269
|
+
/** How many whitespace characters open the text at `from` (up to `to`). */
|
|
1270
|
+
leadingSpace(from, to) {
|
|
1271
|
+
let k = from;
|
|
1272
|
+
while (k < to && /\s/.test(this.text[k])) k++;
|
|
1273
|
+
return k - from;
|
|
1274
|
+
}
|
|
1237
1275
|
isBlank(from, to) {
|
|
1238
1276
|
return !NOT_WHITESPACE.test(this.text.slice(from, to));
|
|
1239
1277
|
}
|
|
@@ -1258,6 +1296,10 @@ var Tokenizer = class {
|
|
|
1258
1296
|
break;
|
|
1259
1297
|
}
|
|
1260
1298
|
const island = this.detectBlock(pos, li, true);
|
|
1299
|
+
if (island && pos + this.leadingSpace(pos, this.contentEnds[li]) >= this.provisionalFrom) {
|
|
1300
|
+
this.push({ kind: "prose", start: pos, end: this.n, island: null, inlines: [] });
|
|
1301
|
+
break;
|
|
1302
|
+
}
|
|
1261
1303
|
if (island) {
|
|
1262
1304
|
this.push({ kind: "island", start: island.start, end: island.end, island, inlines: [] });
|
|
1263
1305
|
pos = island.end;
|
|
@@ -1265,8 +1307,122 @@ var Tokenizer = class {
|
|
|
1265
1307
|
}
|
|
1266
1308
|
pos = this.paragraph(pos, li);
|
|
1267
1309
|
}
|
|
1310
|
+
if (this.streaming) this.holdUndecidedTail();
|
|
1268
1311
|
return this.blocks;
|
|
1269
1312
|
}
|
|
1313
|
+
/**
|
|
1314
|
+
* Streaming: settle nothing the next bytes can still change (verify-RC-B3 F3).
|
|
1315
|
+
*
|
|
1316
|
+
* 1. A block island that ends on the open last line is undecided — the next
|
|
1317
|
+
* bytes on that line can re-read it or dissolve it (`<!--@a:k1-->` +
|
|
1318
|
+
* ` more` is an inline anchor, `<br>` + `x` is prose). It runs open to
|
|
1319
|
+
* the end of the text.
|
|
1320
|
+
* 2. A box-drawing tree still forming at the end of the text claims, as its
|
|
1321
|
+
* root label, the lines directly above its first connector (the
|
|
1322
|
+
* renderer's `findTreeBlockStart`), and the open last line itself may
|
|
1323
|
+
* become one of its connector lines — so inlines on those lines are held
|
|
1324
|
+
* back as prose until a blank line, a heading or a tree line decides.
|
|
1325
|
+
* This also holds everything a closer still able to arrive on the open
|
|
1326
|
+
* last line could change (`$x$` + `5` is currency, G4; `{{v}}` + `}`).
|
|
1327
|
+
*/
|
|
1328
|
+
holdUndecidedTail() {
|
|
1329
|
+
const last = this.lineStarts.length - 1;
|
|
1330
|
+
if (last < 0) return;
|
|
1331
|
+
if (this.isOpenTail(last)) {
|
|
1332
|
+
const lineStart = this.lineStarts[last];
|
|
1333
|
+
for (const block2 of this.blocks) {
|
|
1334
|
+
if (block2.kind === "prose" && block2.end > lineStart) {
|
|
1335
|
+
block2.inlines = block2.inlines.filter((inline) => inline.end <= lineStart);
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
let b = this.blocks.length - 1;
|
|
1339
|
+
while (b >= 0 && this.blocks[b].kind === "gap") b--;
|
|
1340
|
+
const block = this.blocks[b];
|
|
1341
|
+
if (block?.island?.complete && block.island.end > this.lineStarts[last]) {
|
|
1342
|
+
block.island.complete = false;
|
|
1343
|
+
block.island.end = this.n;
|
|
1344
|
+
block.end = this.n;
|
|
1345
|
+
this.blocks.length = b + 1;
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
const from = this.treeRootHoldFrom();
|
|
1349
|
+
for (let b = this.blocks.length - 1; b >= 0; b--) {
|
|
1350
|
+
const block = this.blocks[b];
|
|
1351
|
+
if (block.end <= from) break;
|
|
1352
|
+
if (block.kind === "prose") block.inlines = block.inlines.filter((inline) => inline.end <= from);
|
|
1353
|
+
if (block.island) this.blocks[b] = { kind: "prose", start: block.start, end: block.end, island: null, inlines: [] };
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
/**
|
|
1357
|
+
* Streaming: where a tree that may still form at the end of the text would
|
|
1358
|
+
* start claiming lines (`n` when none can). Only paragraph lines can be
|
|
1359
|
+
* claimed — a line that starts inside an island (a fence body, an XML
|
|
1360
|
+
* region…) is never a tree line nor a root label, so it stops the walk.
|
|
1361
|
+
*/
|
|
1362
|
+
treeRootHoldFrom() {
|
|
1363
|
+
const claimFrom = (k2) => {
|
|
1364
|
+
const lineStart = this.lineStarts[k2];
|
|
1365
|
+
const lineEnd = this.contentEnds[k2];
|
|
1366
|
+
let pos = lineStart;
|
|
1367
|
+
for (; ; ) {
|
|
1368
|
+
const block = this.blockAt(pos);
|
|
1369
|
+
if (!block || block.kind !== "island" || !block.island) return pos;
|
|
1370
|
+
if (block.island.fromParagraph === true || this.mayDissolve(block.island)) return pos;
|
|
1371
|
+
if (block.start < lineStart) {
|
|
1372
|
+
const opened = this.lineOf(block.start);
|
|
1373
|
+
if (this.lineStarts[opened] !== block.start && claimFrom(opened) !== -1) return pos;
|
|
1374
|
+
if (block.end >= lineEnd) return -1;
|
|
1375
|
+
pos = block.end;
|
|
1376
|
+
continue;
|
|
1377
|
+
}
|
|
1378
|
+
if (block.end >= lineEnd) return -1;
|
|
1379
|
+
pos = block.end;
|
|
1380
|
+
}
|
|
1381
|
+
};
|
|
1382
|
+
let k = this.lineCount - 1;
|
|
1383
|
+
let start = this.lineCount;
|
|
1384
|
+
let startPos = this.n;
|
|
1385
|
+
if (k >= 0 && this.isOpenTail(k)) {
|
|
1386
|
+
const at = claimFrom(k);
|
|
1387
|
+
if (at === -1) return this.n;
|
|
1388
|
+
start = k;
|
|
1389
|
+
startPos = at;
|
|
1390
|
+
k--;
|
|
1391
|
+
}
|
|
1392
|
+
for (; k >= 0; k--) {
|
|
1393
|
+
this.tick(1);
|
|
1394
|
+
const at = claimFrom(k);
|
|
1395
|
+
if (at === -1) break;
|
|
1396
|
+
if (this.lineIsBlank(k)) continue;
|
|
1397
|
+
if (!TREE_GLYPHS.test(this.lineText(k))) break;
|
|
1398
|
+
start = k;
|
|
1399
|
+
startPos = at;
|
|
1400
|
+
}
|
|
1401
|
+
let rootPos = startPos;
|
|
1402
|
+
for (let j = start - 1; j >= 0; j--) {
|
|
1403
|
+
const at = claimFrom(j);
|
|
1404
|
+
if (at === -1) break;
|
|
1405
|
+
const trimmed = this.lineText(j).trim();
|
|
1406
|
+
this.tick(trimmed.length + 1);
|
|
1407
|
+
if (!trimmed || isSplitterTreeLine(trimmed) || /^#{1,6}\s/.test(trimmed)) break;
|
|
1408
|
+
rootPos = at;
|
|
1409
|
+
if (at > this.lineStarts[j]) break;
|
|
1410
|
+
}
|
|
1411
|
+
return rootPos;
|
|
1412
|
+
}
|
|
1413
|
+
/** The block (so far) containing offset `pos`, or null. */
|
|
1414
|
+
blockAt(pos) {
|
|
1415
|
+
let lo = 0;
|
|
1416
|
+
let hi = this.blocks.length - 1;
|
|
1417
|
+
while (lo <= hi) {
|
|
1418
|
+
const mid = lo + hi >>> 1;
|
|
1419
|
+
const block = this.blocks[mid];
|
|
1420
|
+
if (pos < block.start) hi = mid - 1;
|
|
1421
|
+
else if (pos >= block.end) lo = mid + 1;
|
|
1422
|
+
else return block;
|
|
1423
|
+
}
|
|
1424
|
+
return null;
|
|
1425
|
+
}
|
|
1270
1426
|
push(block) {
|
|
1271
1427
|
if (block.end <= block.start) return;
|
|
1272
1428
|
if (block.kind === "prose" && this.isBlank(block.start, block.end)) {
|
|
@@ -1470,7 +1626,10 @@ var Tokenizer = class {
|
|
|
1470
1626
|
continue;
|
|
1471
1627
|
}
|
|
1472
1628
|
if (this.isOpenTail(k)) return this.heldFootnote(p, open[1]);
|
|
1473
|
-
if (FOOTNOTE_DEF.test(line.trimStart())
|
|
1629
|
+
if (FOOTNOTE_DEF.test(line.trimStart())) break;
|
|
1630
|
+
const block = this.detectBlock(this.lineStarts[k], k, false);
|
|
1631
|
+
if (block && this.mayDissolve(block)) return this.heldFootnote(p, open[1]);
|
|
1632
|
+
if (block) break;
|
|
1474
1633
|
last = k;
|
|
1475
1634
|
}
|
|
1476
1635
|
const end = this.contentEnds[last];
|
|
@@ -1486,7 +1645,8 @@ var Tokenizer = class {
|
|
|
1486
1645
|
return {
|
|
1487
1646
|
count: this.lineCount,
|
|
1488
1647
|
line: (k) => this.lineText(k),
|
|
1489
|
-
openTail: (k) => this.isOpenTail(k)
|
|
1648
|
+
openTail: (k) => this.isOpenTail(k),
|
|
1649
|
+
streaming: this.streaming
|
|
1490
1650
|
};
|
|
1491
1651
|
}
|
|
1492
1652
|
/**
|
|
@@ -1546,6 +1706,10 @@ var Tokenizer = class {
|
|
|
1546
1706
|
if (fenceOpenerOf(this.lineText(j))?.char === "~") continue;
|
|
1547
1707
|
const inner = this.detectBlockUncached(start, j, false);
|
|
1548
1708
|
if (!inner) continue;
|
|
1709
|
+
if (this.streaming && inner.end >= tildeEnd && this.paragraphMayGrow(inner.end)) {
|
|
1710
|
+
this.overflowComplete = false;
|
|
1711
|
+
return this.n;
|
|
1712
|
+
}
|
|
1549
1713
|
if (inner.end > end) {
|
|
1550
1714
|
end = inner.end;
|
|
1551
1715
|
this.overflowComplete = inner.complete;
|
|
@@ -1674,12 +1838,7 @@ var Tokenizer = class {
|
|
|
1674
1838
|
return this.island("html_block", p, close.index + close[0].length, true, { tag: name });
|
|
1675
1839
|
}
|
|
1676
1840
|
const typeSix = HTML_BLOCK_LEVEL_TAGS.has(name);
|
|
1677
|
-
const
|
|
1678
|
-
if (loneTag && this.isOpenTail(li)) {
|
|
1679
|
-
this.provisionalFrom = Math.min(this.provisionalFrom, p);
|
|
1680
|
-
return null;
|
|
1681
|
-
}
|
|
1682
|
-
const typeSeven = loneTag;
|
|
1841
|
+
const typeSeven = atParaStart && t.trimEnd() === tag.raw;
|
|
1683
1842
|
if (!typeSix && !typeSeven) return null;
|
|
1684
1843
|
let end = this.contentEnds[li];
|
|
1685
1844
|
for (let k = li + 1; k < this.lineCount && !this.lineIsBlank(k); k++) {
|
|
@@ -1737,6 +1896,13 @@ var Tokenizer = class {
|
|
|
1737
1896
|
}
|
|
1738
1897
|
return null;
|
|
1739
1898
|
}
|
|
1899
|
+
if (this.isOpenTail(lastLine)) {
|
|
1900
|
+
if (isRecognizedJsonHead(this.text.slice(tp, tp + 512))) {
|
|
1901
|
+
return this.island("json", p, this.n, false, jsonMeta(this.text.slice(tp)));
|
|
1902
|
+
}
|
|
1903
|
+
this.provisionalFrom = Math.min(this.provisionalFrom, p);
|
|
1904
|
+
return null;
|
|
1905
|
+
}
|
|
1740
1906
|
if (net !== 0) return null;
|
|
1741
1907
|
const end = this.contentEnds[lastLine];
|
|
1742
1908
|
const content = this.text.slice(tp, end).trim();
|
|
@@ -1771,8 +1937,10 @@ var Tokenizer = class {
|
|
|
1771
1937
|
let breakLine = -1;
|
|
1772
1938
|
for (let k = li + 1; k < this.lineCount; k++) {
|
|
1773
1939
|
if (this.lineIsBlank(k)) break;
|
|
1774
|
-
|
|
1940
|
+
const block = this.detectBlock(this.lineStarts[k], k, false);
|
|
1941
|
+
if (block) {
|
|
1775
1942
|
breakLine = k;
|
|
1943
|
+
if (this.mayDissolve(block)) this.undecidedBreaks.add(end);
|
|
1776
1944
|
break;
|
|
1777
1945
|
}
|
|
1778
1946
|
end = this.contentEnds[k];
|
|
@@ -1810,7 +1978,7 @@ var Tokenizer = class {
|
|
|
1810
1978
|
this.push({ kind: "prose", start: pos, end, island: null, inlines: scan2.inlines });
|
|
1811
1979
|
return end;
|
|
1812
1980
|
}
|
|
1813
|
-
const br = scan2.breakIsland;
|
|
1981
|
+
const br = { ...scan2.breakIsland, fromParagraph: true };
|
|
1814
1982
|
if (scan2.orphan) {
|
|
1815
1983
|
let start = pos;
|
|
1816
1984
|
while (this.blocks.length) {
|
|
@@ -1833,6 +2001,15 @@ var Tokenizer = class {
|
|
|
1833
2001
|
this.push({ kind: "island", start: br.start, end: br.end, island: br, inlines: [] });
|
|
1834
2002
|
return br.end;
|
|
1835
2003
|
}
|
|
2004
|
+
/**
|
|
2005
|
+
* An island that opens inside a paragraph and closes past its end becomes a
|
|
2006
|
+
* block. Streaming: while the paragraph may still grow over its closer, the
|
|
2007
|
+
* island may yet be inline — undecided, so it runs open to the end (F3).
|
|
2008
|
+
*/
|
|
2009
|
+
spill(type, start, end, pe, meta) {
|
|
2010
|
+
if (this.paragraphMayGrow(pe)) return this.island(type, start, this.n, false, meta);
|
|
2011
|
+
return this.island(type, start, end, true, meta);
|
|
2012
|
+
}
|
|
1836
2013
|
scanInline(ps, pe) {
|
|
1837
2014
|
const text = this.text;
|
|
1838
2015
|
const inlines = [];
|
|
@@ -1867,6 +2044,9 @@ var Tokenizer = class {
|
|
|
1867
2044
|
i = close + 2;
|
|
1868
2045
|
continue;
|
|
1869
2046
|
}
|
|
2047
|
+
if (close === -1 && this.streaming && this.paragraphMayGrow(pe)) {
|
|
2048
|
+
return { inlines, breakIsland: null, orphan: false };
|
|
2049
|
+
}
|
|
1870
2050
|
}
|
|
1871
2051
|
i += 2;
|
|
1872
2052
|
continue;
|
|
@@ -1887,17 +2067,13 @@ var Tokenizer = class {
|
|
|
1887
2067
|
i += 2;
|
|
1888
2068
|
continue;
|
|
1889
2069
|
}
|
|
1890
|
-
if (close + 2 > pe) return stop(this.
|
|
2070
|
+
if (close + 2 > pe) return stop(this.spill("math_block", i, close + 2, pe, { delimiter: "$$" }));
|
|
1891
2071
|
inlines.push(this.island("math_inline", i, close + 2, true, { delimiter: "$$" }));
|
|
1892
2072
|
i = close + 2;
|
|
1893
2073
|
continue;
|
|
1894
2074
|
}
|
|
1895
2075
|
const end = singleDollarMathEnd(text, i, pe);
|
|
1896
2076
|
this.tick(end > 0 ? end - i : Math.min(403, pe - i));
|
|
1897
|
-
if (end > 0 && this.streaming && end === this.n) {
|
|
1898
|
-
this.provisionalFrom = Math.min(this.provisionalFrom, i);
|
|
1899
|
-
return { inlines, breakIsland: null, orphan: false };
|
|
1900
|
-
}
|
|
1901
2077
|
if (end > 0) {
|
|
1902
2078
|
inlines.push(this.island("math_inline", i, end, true, { delimiter: "$" }));
|
|
1903
2079
|
i = end;
|
|
@@ -1975,7 +2151,7 @@ var Tokenizer = class {
|
|
|
1975
2151
|
const anchor = end - i <= 64 ? PINNED_ANCHOR_RE.exec(text.slice(i, end)) : null;
|
|
1976
2152
|
const type = anchor ? "anchor" : "html_comment";
|
|
1977
2153
|
const meta = anchor ? { id: anchor[1] } : {};
|
|
1978
|
-
if (end > pe) return stop(this.
|
|
2154
|
+
if (end > pe) return stop(this.spill(type, i, end, pe, meta));
|
|
1979
2155
|
inlines.push(this.island(type, i, end, true, meta));
|
|
1980
2156
|
i = end;
|
|
1981
2157
|
continue;
|
|
@@ -2002,9 +2178,13 @@ var Tokenizer = class {
|
|
|
2002
2178
|
const closer = `</${name}>`;
|
|
2003
2179
|
const close = this.next(closer, tagEnd);
|
|
2004
2180
|
const blockType = isAttr ? "xml_attr" : "xml_region";
|
|
2181
|
+
if (close === -1 && isThinking && !this.streaming) {
|
|
2182
|
+
i = tagEnd;
|
|
2183
|
+
continue;
|
|
2184
|
+
}
|
|
2005
2185
|
if (close === -1) return stop(this.island(blockType, i, this.n, false, { tag: name }));
|
|
2006
2186
|
const end = close + closer.length;
|
|
2007
|
-
if (end > pe) return stop(this.
|
|
2187
|
+
if (end > pe) return stop(this.spill(blockType, i, end, pe, { tag: name }));
|
|
2008
2188
|
inlines.push(this.island("xml_inline", i, end, true, { tag: name }));
|
|
2009
2189
|
i = end;
|
|
2010
2190
|
continue;
|
|
@@ -2389,6 +2569,6 @@ function mapRange(changes, start, end, unit = "utf16") {
|
|
|
2389
2569
|
return { start: newStart, end: newEnd, touched, collapsed: newEnd === newStart && end > start };
|
|
2390
2570
|
}
|
|
2391
2571
|
|
|
2392
|
-
export { BacktickRuns, CALLOUT_NAMES, FENCE_OPENER_WHITESPACE, FENCE_WHITESPACE, FenceReader, NESTING_FENCE_LANGUAGES, SourceSpliceError, XmlContainerTracker, blockAt, blockEdit, blockRangeEdit, buildCodePointIndex, classifyInnerFenceLine, closeFence, codeSpanText, fenceLineKinds, fenceNestsInnerFences, fenceOpenerOf, fenceParts, findCodeRanges, isEscapedBracketMath, isMathPlaceholder, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, looksLikeOpenInlineMath, mapCodeRanges, mapPosition, mapRange, pairDisplayMath, parseFenceOpener, pendingDisplayMathOpener, readXmlTag, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };
|
|
2572
|
+
export { AFTER_WINDOW, BacktickRuns, CALLOUT_NAMES, FENCE_OPENER_WHITESPACE, FENCE_WHITESPACE, FenceReader, NESTING_FENCE_LANGUAGES, SourceSpliceError, XmlContainerTracker, blockAt, blockEdit, blockRangeEdit, buildCodePointIndex, classifyInnerFenceLine, closeFence, codeSpanText, fenceLineKinds, fenceNestsInnerFences, fenceOpenerOf, fenceParts, findCodeRanges, isEscapedBracketMath, isMathPlaceholder, isSingleDollarMath, islandEdit, joinSource, listIslands, looksLikeDisplayMath, looksLikeOpenInlineMath, mapCodeRanges, mapPosition, mapRange, pairDisplayMath, parseFenceOpener, pendingDisplayMathOpener, readXmlTag, singleDollarAfter, singleDollarMathEnd, spliceSave, splitsSurrogatePair, toCodePointOffset, toUtf16Offset, tokenizeSource, trimFenceLine };
|
|
2393
2573
|
//# sourceMappingURL=source.js.map
|
|
2394
2574
|
//# sourceMappingURL=source.js.map
|