@temelj/mdx 0.14.0 → 0.15.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/README.md +468 -82
- package/dist/character-entities.d.mts +4 -0
- package/dist/character-entities.d.mts.map +1 -0
- package/dist/character-entities.mjs +2132 -0
- package/dist/character-entities.mjs.map +1 -0
- package/dist/character-reference.d.mts +6 -0
- package/dist/character-reference.d.mts.map +1 -0
- package/dist/character-reference.mjs +18 -0
- package/dist/character-reference.mjs.map +1 -0
- package/dist/compile-analysis.d.mts +28 -0
- package/dist/compile-analysis.d.mts.map +1 -0
- package/dist/compile-analysis.mjs +74 -0
- package/dist/compile-analysis.mjs.map +1 -0
- package/dist/compile-emit.d.mts +9 -0
- package/dist/compile-emit.d.mts.map +1 -0
- package/dist/compile-emit.mjs +187 -0
- package/dist/compile-emit.mjs.map +1 -0
- package/dist/compile-esm.d.mts +34 -0
- package/dist/compile-esm.d.mts.map +1 -0
- package/dist/compile-esm.mjs +187 -0
- package/dist/compile-esm.mjs.map +1 -0
- package/dist/compile-names.d.mts +13 -0
- package/dist/compile-names.d.mts.map +1 -0
- package/dist/compile-names.mjs +32 -0
- package/dist/compile-names.mjs.map +1 -0
- package/dist/compiler.d.mts +69 -85
- package/dist/compiler.d.mts.map +1 -1
- package/dist/compiler.mjs +185 -418
- package/dist/compiler.mjs.map +1 -1
- package/dist/diagnostics.d.mts +37 -0
- package/dist/diagnostics.d.mts.map +1 -0
- package/dist/diagnostics.mjs +57 -0
- package/dist/diagnostics.mjs.map +1 -0
- package/dist/errors.d.mts +157 -0
- package/dist/errors.d.mts.map +1 -0
- package/dist/errors.mjs +263 -0
- package/dist/errors.mjs.map +1 -0
- package/dist/footnote-numbering.d.mts +27 -0
- package/dist/footnote-numbering.d.mts.map +1 -0
- package/dist/footnote-numbering.mjs +49 -0
- package/dist/footnote-numbering.mjs.map +1 -0
- package/dist/format-context.d.mts +46 -0
- package/dist/format-context.d.mts.map +1 -0
- package/dist/format-context.mjs +26 -0
- package/dist/format-context.mjs.map +1 -0
- package/dist/format-directive.d.mts +9 -0
- package/dist/format-directive.d.mts.map +1 -0
- package/dist/format-directive.mjs +99 -0
- package/dist/format-directive.mjs.map +1 -0
- package/dist/format-jsx.d.mts +8 -0
- package/dist/format-jsx.d.mts.map +1 -0
- package/dist/format-jsx.mjs +47 -0
- package/dist/format-jsx.mjs.map +1 -0
- package/dist/format-math.d.mts +9 -0
- package/dist/format-math.d.mts.map +1 -0
- package/dist/format-math.mjs +79 -0
- package/dist/format-math.mjs.map +1 -0
- package/dist/format-safe.d.mts +25 -0
- package/dist/format-safe.d.mts.map +1 -0
- package/dist/format-safe.mjs +366 -0
- package/dist/format-safe.mjs.map +1 -0
- package/dist/format-table.d.mts +8 -0
- package/dist/format-table.d.mts.map +1 -0
- package/dist/format-table.mjs +55 -0
- package/dist/format-table.mjs.map +1 -0
- package/dist/format-track.d.mts +18 -0
- package/dist/format-track.d.mts.map +1 -0
- package/dist/format-track.mjs +34 -0
- package/dist/format-track.mjs.map +1 -0
- package/dist/format.d.mts +7 -0
- package/dist/format.d.mts.map +1 -0
- package/dist/format.mjs +549 -0
- package/dist/format.mjs.map +1 -0
- package/dist/frontmatter.d.mts +15 -0
- package/dist/frontmatter.d.mts.map +1 -0
- package/dist/frontmatter.mjs +187 -0
- package/dist/frontmatter.mjs.map +1 -0
- package/dist/heading.d.mts +6 -0
- package/dist/heading.d.mts.map +1 -0
- package/dist/heading.mjs +19 -0
- package/dist/heading.mjs.map +1 -0
- package/dist/html-format.d.mts +32 -0
- package/dist/html-format.d.mts.map +1 -0
- package/dist/html-format.mjs +127 -0
- package/dist/html-format.mjs.map +1 -0
- package/dist/html-lower.d.mts +78 -0
- package/dist/html-lower.d.mts.map +1 -0
- package/dist/html-lower.mjs +583 -0
- package/dist/html-lower.mjs.map +1 -0
- package/dist/html-stream.d.mts +13 -0
- package/dist/html-stream.d.mts.map +1 -0
- package/dist/html-stream.mjs +32 -0
- package/dist/html-stream.mjs.map +1 -0
- package/dist/html.d.mts +120 -0
- package/dist/html.d.mts.map +1 -0
- package/dist/html.mjs +77 -0
- package/dist/html.mjs.map +1 -0
- package/dist/identifier.d.mts +4 -0
- package/dist/identifier.d.mts.map +1 -0
- package/dist/identifier.mjs +8 -0
- package/dist/identifier.mjs.map +1 -0
- package/dist/javascript-ast.d.mts +16 -0
- package/dist/javascript-ast.d.mts.map +1 -0
- package/dist/javascript-ast.mjs +39 -0
- package/dist/javascript-ast.mjs.map +1 -0
- package/dist/javascript-jsx.d.mts +24 -0
- package/dist/javascript-jsx.d.mts.map +1 -0
- package/dist/javascript-jsx.mjs +189 -0
- package/dist/javascript-jsx.mjs.map +1 -0
- package/dist/javascript.d.mts +9 -0
- package/dist/javascript.d.mts.map +1 -0
- package/dist/javascript.mjs +31 -0
- package/dist/javascript.mjs.map +1 -0
- package/dist/jsx-reference.d.mts +15 -0
- package/dist/jsx-reference.d.mts.map +1 -0
- package/dist/jsx-reference.mjs +31 -0
- package/dist/jsx-reference.mjs.map +1 -0
- package/dist/mod.d.mts +25 -9
- package/dist/mod.mjs +19 -8
- package/dist/model.d.mts +196 -0
- package/dist/model.d.mts.map +1 -0
- package/dist/model.mjs +113 -0
- package/dist/model.mjs.map +1 -0
- package/dist/parser/block-container-recognizers.d.mts +40 -0
- package/dist/parser/block-container-recognizers.d.mts.map +1 -0
- package/dist/parser/block-container-recognizers.mjs +90 -0
- package/dist/parser/block-container-recognizers.mjs.map +1 -0
- package/dist/parser/block-directive-recognizers.d.mts +22 -0
- package/dist/parser/block-directive-recognizers.d.mts.map +1 -0
- package/dist/parser/block-directive-recognizers.mjs +77 -0
- package/dist/parser/block-directive-recognizers.mjs.map +1 -0
- package/dist/parser/block-leaf-recognizers.d.mts +53 -0
- package/dist/parser/block-leaf-recognizers.d.mts.map +1 -0
- package/dist/parser/block-leaf-recognizers.mjs +386 -0
- package/dist/parser/block-leaf-recognizers.mjs.map +1 -0
- package/dist/parser/block-parser.d.mts +38 -0
- package/dist/parser/block-parser.d.mts.map +1 -0
- package/dist/parser/block-parser.mjs +895 -0
- package/dist/parser/block-parser.mjs.map +1 -0
- package/dist/parser/block-syntax.d.mts +240 -0
- package/dist/parser/block-syntax.d.mts.map +1 -0
- package/dist/parser/characters.d.mts +19 -0
- package/dist/parser/characters.d.mts.map +1 -0
- package/dist/parser/characters.mjs +52 -0
- package/dist/parser/characters.mjs.map +1 -0
- package/dist/parser/config.d.mts +16 -0
- package/dist/parser/config.d.mts.map +1 -0
- package/dist/parser/config.mjs +25 -0
- package/dist/parser/config.mjs.map +1 -0
- package/dist/parser/directive-attributes.d.mts +9 -0
- package/dist/parser/directive-attributes.d.mts.map +1 -0
- package/dist/parser/directive-attributes.mjs +24 -0
- package/dist/parser/directive-attributes.mjs.map +1 -0
- package/dist/parser/embedded-scanner.d.mts +18 -0
- package/dist/parser/embedded-scanner.d.mts.map +1 -0
- package/dist/parser/embedded-scanner.mjs +199 -0
- package/dist/parser/embedded-scanner.mjs.map +1 -0
- package/dist/parser/inline-autolink.d.mts +7 -0
- package/dist/parser/inline-autolink.d.mts.map +1 -0
- package/dist/parser/inline-autolink.mjs +42 -0
- package/dist/parser/inline-autolink.mjs.map +1 -0
- package/dist/parser/inline-character-reference.d.mts +7 -0
- package/dist/parser/inline-character-reference.d.mts.map +1 -0
- package/dist/parser/inline-character-reference.mjs +22 -0
- package/dist/parser/inline-character-reference.mjs.map +1 -0
- package/dist/parser/inline-code.d.mts +7 -0
- package/dist/parser/inline-code.d.mts.map +1 -0
- package/dist/parser/inline-code.mjs +29 -0
- package/dist/parser/inline-code.mjs.map +1 -0
- package/dist/parser/inline-directive.d.mts +9 -0
- package/dist/parser/inline-directive.d.mts.map +1 -0
- package/dist/parser/inline-directive.mjs +45 -0
- package/dist/parser/inline-directive.mjs.map +1 -0
- package/dist/parser/inline-embedded.d.mts +19 -0
- package/dist/parser/inline-embedded.d.mts.map +1 -0
- package/dist/parser/inline-embedded.mjs +92 -0
- package/dist/parser/inline-embedded.mjs.map +1 -0
- package/dist/parser/inline-emphasis.d.mts +11 -0
- package/dist/parser/inline-emphasis.d.mts.map +1 -0
- package/dist/parser/inline-emphasis.mjs +79 -0
- package/dist/parser/inline-emphasis.mjs.map +1 -0
- package/dist/parser/inline-input.d.mts +46 -0
- package/dist/parser/inline-input.d.mts.map +1 -0
- package/dist/parser/inline-input.mjs +137 -0
- package/dist/parser/inline-input.mjs.map +1 -0
- package/dist/parser/inline-link.d.mts +12 -0
- package/dist/parser/inline-link.d.mts.map +1 -0
- package/dist/parser/inline-link.mjs +187 -0
- package/dist/parser/inline-link.mjs.map +1 -0
- package/dist/parser/inline-math.d.mts +10 -0
- package/dist/parser/inline-math.d.mts.map +1 -0
- package/dist/parser/inline-math.mjs +46 -0
- package/dist/parser/inline-math.mjs.map +1 -0
- package/dist/parser/inline-output.d.mts +34 -0
- package/dist/parser/inline-output.d.mts.map +1 -0
- package/dist/parser/inline-output.mjs +62 -0
- package/dist/parser/inline-output.mjs.map +1 -0
- package/dist/parser/inline-parser.d.mts +14 -0
- package/dist/parser/inline-parser.d.mts.map +1 -0
- package/dist/parser/inline-parser.mjs +328 -0
- package/dist/parser/inline-parser.mjs.map +1 -0
- package/dist/parser/inline-pending.d.mts +23 -0
- package/dist/parser/inline-pending.d.mts.map +1 -0
- package/dist/parser/inline-pending.mjs +100 -0
- package/dist/parser/inline-pending.mjs.map +1 -0
- package/dist/parser/inline-syntax.d.mts +118 -0
- package/dist/parser/inline-syntax.d.mts.map +1 -0
- package/dist/parser/inline-syntax.mjs +1 -0
- package/dist/parser/javascript-boundary.d.mts +16 -0
- package/dist/parser/javascript-boundary.d.mts.map +1 -0
- package/dist/parser/javascript-boundary.mjs +42 -0
- package/dist/parser/javascript-boundary.mjs.map +1 -0
- package/dist/parser/javascript-scanner.d.mts +22 -0
- package/dist/parser/javascript-scanner.d.mts.map +1 -0
- package/dist/parser/javascript-scanner.mjs +122 -0
- package/dist/parser/javascript-scanner.mjs.map +1 -0
- package/dist/parser/materialize-cache.d.mts +34 -0
- package/dist/parser/materialize-cache.d.mts.map +1 -0
- package/dist/parser/materialize-cache.mjs +12 -0
- package/dist/parser/materialize-cache.mjs.map +1 -0
- package/dist/parser/materialize-jsx.d.mts +14 -0
- package/dist/parser/materialize-jsx.d.mts.map +1 -0
- package/dist/parser/materialize-jsx.mjs +76 -0
- package/dist/parser/materialize-jsx.mjs.map +1 -0
- package/dist/parser/materialize.d.mts +61 -0
- package/dist/parser/materialize.d.mts.map +1 -0
- package/dist/parser/materialize.mjs +736 -0
- package/dist/parser/materialize.mjs.map +1 -0
- package/dist/parser/recognizer.d.mts +20 -0
- package/dist/parser/recognizer.d.mts.map +1 -0
- package/dist/parser/recognizer.mjs +24 -0
- package/dist/parser/recognizer.mjs.map +1 -0
- package/dist/parser/session.d.mts +42 -0
- package/dist/parser/session.d.mts.map +1 -0
- package/dist/parser/session.mjs +89 -0
- package/dist/parser/session.mjs.map +1 -0
- package/dist/parser.d.mts +25 -0
- package/dist/parser.d.mts.map +1 -0
- package/dist/parser.mjs +37 -0
- package/dist/parser.mjs.map +1 -0
- package/dist/plugin-internal.d.mts +25 -0
- package/dist/plugin-internal.d.mts.map +1 -0
- package/dist/plugin-internal.mjs +99 -0
- package/dist/plugin-internal.mjs.map +1 -0
- package/dist/plugin.d.mts +37 -0
- package/dist/plugin.d.mts.map +1 -0
- package/dist/plugin.mjs +1 -0
- package/dist/plugins/code-block-metadata.d.mts +42 -0
- package/dist/plugins/code-block-metadata.d.mts.map +1 -0
- package/dist/plugins/code-block-metadata.mjs +133 -0
- package/dist/plugins/code-block-metadata.mjs.map +1 -0
- package/dist/plugins/heading-id.d.mts +15 -0
- package/dist/plugins/heading-id.d.mts.map +1 -0
- package/dist/plugins/heading-id.mjs +45 -0
- package/dist/plugins/heading-id.mjs.map +1 -0
- package/dist/plugins/lower-heading.d.mts +16 -0
- package/dist/plugins/lower-heading.d.mts.map +1 -0
- package/dist/plugins/lower-heading.mjs +28 -0
- package/dist/plugins/lower-heading.mjs.map +1 -0
- package/dist/plugins/math-render.d.mts +26 -0
- package/dist/plugins/math-render.d.mts.map +1 -0
- package/dist/plugins/math-render.mjs +51 -0
- package/dist/plugins/math-render.mjs.map +1 -0
- package/dist/plugins/mod.d.mts +9 -6
- package/dist/plugins/mod.mjs +8 -6
- package/dist/plugins/remove-esm.d.mts +10 -0
- package/dist/plugins/remove-esm.d.mts.map +1 -0
- package/dist/plugins/remove-esm.mjs +12 -0
- package/dist/plugins/remove-esm.mjs.map +1 -0
- package/dist/plugins/shiki.d.mts +21 -0
- package/dist/plugins/shiki.d.mts.map +1 -0
- package/dist/plugins/shiki.mjs +144 -0
- package/dist/plugins/shiki.mjs.map +1 -0
- package/dist/plugins/syntax-highlight.d.mts +38 -0
- package/dist/plugins/syntax-highlight.d.mts.map +1 -0
- package/dist/plugins/syntax-highlight.mjs +106 -0
- package/dist/plugins/syntax-highlight.mjs.map +1 -0
- package/dist/processor.d.mts +60 -0
- package/dist/processor.d.mts.map +1 -0
- package/dist/processor.mjs +106 -0
- package/dist/processor.mjs.map +1 -0
- package/dist/ranges.d.mts +10 -0
- package/dist/ranges.d.mts.map +1 -0
- package/dist/ranges.mjs +22 -0
- package/dist/ranges.mjs.map +1 -0
- package/dist/source-map.d.mts +28 -0
- package/dist/source-map.d.mts.map +1 -0
- package/dist/source-map.mjs +90 -0
- package/dist/source-map.mjs.map +1 -0
- package/dist/source-text.d.mts +35 -0
- package/dist/source-text.d.mts.map +1 -0
- package/dist/source-text.mjs +132 -0
- package/dist/source-text.mjs.map +1 -0
- package/dist/source.d.mts +86 -0
- package/dist/source.d.mts.map +1 -0
- package/dist/source.mjs +264 -0
- package/dist/source.mjs.map +1 -0
- package/dist/stream-events.d.mts +59 -0
- package/dist/stream-events.d.mts.map +1 -0
- package/dist/stream-events.mjs +115 -0
- package/dist/stream-events.mjs.map +1 -0
- package/dist/stream-session.d.mts +79 -0
- package/dist/stream-session.d.mts.map +1 -0
- package/dist/stream-session.mjs +904 -0
- package/dist/stream-session.mjs.map +1 -0
- package/dist/stream-tail.d.mts +84 -0
- package/dist/stream-tail.d.mts.map +1 -0
- package/dist/stream-tail.mjs +359 -0
- package/dist/stream-tail.mjs.map +1 -0
- package/dist/stream-types.d.mts +89 -0
- package/dist/stream-types.d.mts.map +1 -0
- package/dist/stream-types.mjs +1 -0
- package/dist/stream.d.mts +28 -0
- package/dist/stream.d.mts.map +1 -0
- package/dist/stream.mjs +68 -0
- package/dist/stream.mjs.map +1 -0
- package/dist/syntax-options.d.mts +21 -0
- package/dist/syntax-options.d.mts.map +1 -0
- package/dist/syntax-options.mjs +26 -0
- package/dist/syntax-options.mjs.map +1 -0
- package/dist/traversal.d.mts +25 -0
- package/dist/traversal.d.mts.map +1 -0
- package/dist/traversal.mjs +136 -0
- package/dist/traversal.mjs.map +1 -0
- package/dist/tree.d.mts +18 -0
- package/dist/tree.d.mts.map +1 -0
- package/dist/tree.mjs +43 -0
- package/dist/tree.mjs.map +1 -0
- package/dist/unified/adapter.d.mts +24 -0
- package/dist/unified/adapter.d.mts.map +1 -0
- package/dist/unified/adapter.mjs +44 -0
- package/dist/unified/adapter.mjs.map +1 -0
- package/dist/unified/mod.d.mts +2 -0
- package/dist/unified/mod.mjs +1 -0
- package/dist/unified/runtime.d.mts +10 -0
- package/dist/unified/runtime.d.mts.map +1 -0
- package/dist/unified/runtime.mjs +115 -0
- package/dist/unified/runtime.mjs.map +1 -0
- package/dist/unified/tree-bridge.d.mts +63 -0
- package/dist/unified/tree-bridge.d.mts.map +1 -0
- package/dist/unified/tree-bridge.mjs +876 -0
- package/dist/unified/tree-bridge.mjs.map +1 -0
- package/dist/uri.d.mts +5 -0
- package/dist/uri.d.mts.map +1 -0
- package/dist/uri.mjs +32 -0
- package/dist/uri.mjs.map +1 -0
- package/package.json +56 -30
- package/dist/plugins/heading-id/plugin.d.mts +0 -17
- package/dist/plugins/heading-id/plugin.d.mts.map +0 -1
- package/dist/plugins/heading-id/plugin.mjs +0 -23
- package/dist/plugins/heading-id/plugin.mjs.map +0 -1
- package/dist/plugins/katex/plugin.d.mts +0 -39
- package/dist/plugins/katex/plugin.d.mts.map +0 -1
- package/dist/plugins/katex/plugin.mjs +0 -107
- package/dist/plugins/katex/plugin.mjs.map +0 -1
- package/dist/plugins/remove-imports-exports.d.mts +0 -10
- package/dist/plugins/remove-imports-exports.d.mts.map +0 -1
- package/dist/plugins/remove-imports-exports.mjs +0 -15
- package/dist/plugins/remove-imports-exports.mjs.map +0 -1
- package/dist/plugins/syntax-highlight/code-meta.d.mts +0 -22
- package/dist/plugins/syntax-highlight/code-meta.d.mts.map +0 -1
- package/dist/plugins/syntax-highlight/code-meta.mjs +0 -38
- package/dist/plugins/syntax-highlight/code-meta.mjs.map +0 -1
- package/dist/plugins/syntax-highlight/plugin.d.mts +0 -57
- package/dist/plugins/syntax-highlight/plugin.d.mts.map +0 -1
- package/dist/plugins/syntax-highlight/plugin.mjs +0 -93
- package/dist/plugins/syntax-highlight/plugin.mjs.map +0 -1
- package/dist/plugins/tree-processor/plugin.d.mts +0 -19
- package/dist/plugins/tree-processor/plugin.d.mts.map +0 -1
- package/dist/plugins/tree-processor/plugin.mjs +0 -21
- package/dist/plugins/tree-processor/plugin.mjs.map +0 -1
- package/dist/types.d.mts +0 -2
- /package/dist/{types.mjs → parser/block-syntax.mjs} +0 -0
|
@@ -0,0 +1,904 @@
|
|
|
1
|
+
import { createDiagnostic } from "./diagnostics.mjs";
|
|
2
|
+
import { LimitError, ParseError } from "./errors.mjs";
|
|
3
|
+
import { FootnoteNumbering } from "./footnote-numbering.mjs";
|
|
4
|
+
import { mdxChildren } from "./model.mjs";
|
|
5
|
+
import { rangesIntersect, shiftRange } from "./ranges.mjs";
|
|
6
|
+
import { SourceBuffer, sourceText } from "./source.mjs";
|
|
7
|
+
import { createHtmlLoweringCache, lowerFootnoteSection, lowerNodes } from "./html-lower.mjs";
|
|
8
|
+
import { createMaterializeCache } from "./parser/materialize-cache.mjs";
|
|
9
|
+
import { materializeDocument } from "./parser/materialize.mjs";
|
|
10
|
+
import { ParserSession } from "./parser/session.mjs";
|
|
11
|
+
import { FenceText, OpenParagraph, lowerOpenLeaf, trimOpenTail } from "./stream-tail.mjs";
|
|
12
|
+
import { rewriteMdx } from "./traversal.mjs";
|
|
13
|
+
//#region src/stream-session.ts
|
|
14
|
+
const EMPTY_DEFINITIONS = {
|
|
15
|
+
links: /* @__PURE__ */ new Map(),
|
|
16
|
+
footnotes: /* @__PURE__ */ new Map()
|
|
17
|
+
};
|
|
18
|
+
const NO_OCCURRENCES = Object.freeze([]);
|
|
19
|
+
const NO_DEPENDENCIES = Object.freeze({
|
|
20
|
+
definitions: Object.freeze([]),
|
|
21
|
+
footnotes: Object.freeze([])
|
|
22
|
+
});
|
|
23
|
+
/**
|
|
24
|
+
* Owns the parser and the rendered blocks of one stream. A top-level block
|
|
25
|
+
* settles once later input cannot change it, and then materializes and lowers
|
|
26
|
+
* once. Each append renders only the open tail; a settled block renders again
|
|
27
|
+
* only when a definition or footnote number it uses changes.
|
|
28
|
+
*/
|
|
29
|
+
var StreamSession = class {
|
|
30
|
+
#limits;
|
|
31
|
+
#maximumPendingBlockLength;
|
|
32
|
+
#parser;
|
|
33
|
+
/** The stream owns its source; each version is an immutable file. */
|
|
34
|
+
#source;
|
|
35
|
+
#file;
|
|
36
|
+
/** Settled parser output that has not been rendered yet. */
|
|
37
|
+
#queue = [];
|
|
38
|
+
#settled = [];
|
|
39
|
+
/** The settled blocks' renderings, kept beside the entries so a snapshot copies one array. */
|
|
40
|
+
#blocks = [];
|
|
41
|
+
#tail = [];
|
|
42
|
+
#definitions = EMPTY_DEFINITIONS;
|
|
43
|
+
#dependents = /* @__PURE__ */ new Map();
|
|
44
|
+
#nodes = 0;
|
|
45
|
+
#diagnostics = [];
|
|
46
|
+
#limited;
|
|
47
|
+
#referenceLimits = /* @__PURE__ */ new Map();
|
|
48
|
+
#numbering = new FootnoteNumbering();
|
|
49
|
+
#occurrences = /* @__PURE__ */ new WeakMap();
|
|
50
|
+
#tailDefinitions = EMPTY_DEFINITIONS;
|
|
51
|
+
#tailNumbering = new FootnoteNumbering();
|
|
52
|
+
#tailOccurrences = /* @__PURE__ */ new WeakMap();
|
|
53
|
+
#definitionsVersion = 0;
|
|
54
|
+
#footnotes;
|
|
55
|
+
#footnotesKey = [];
|
|
56
|
+
#materializeCache = createMaterializeCache();
|
|
57
|
+
#loweringCache = createHtmlLoweringCache();
|
|
58
|
+
#fence = new FenceText();
|
|
59
|
+
#paragraph = new OpenParagraph();
|
|
60
|
+
#phrasing = /* @__PURE__ */ new WeakMap();
|
|
61
|
+
#nextId = 0;
|
|
62
|
+
#current;
|
|
63
|
+
#lastValid;
|
|
64
|
+
/** The settled numbering must restart, because settled blocks were dropped. */
|
|
65
|
+
#renumber = false;
|
|
66
|
+
#limitedPreview = false;
|
|
67
|
+
constructor(options) {
|
|
68
|
+
this.#limits = options.limits;
|
|
69
|
+
this.#maximumPendingBlockLength = options.maximumPendingBlockLength;
|
|
70
|
+
this.#source = new SourceBuffer({
|
|
71
|
+
name: options.name,
|
|
72
|
+
text: options.source
|
|
73
|
+
});
|
|
74
|
+
this.#file = this.#source.file;
|
|
75
|
+
this.#parser = new ParserSession({
|
|
76
|
+
source: this.#file,
|
|
77
|
+
syntax: options.syntax,
|
|
78
|
+
onSettled: (syntax, index) => this.#queue.push({
|
|
79
|
+
syntax,
|
|
80
|
+
index
|
|
81
|
+
})
|
|
82
|
+
});
|
|
83
|
+
this.#current = this.update(0);
|
|
84
|
+
}
|
|
85
|
+
/** The latest change, whose snapshot is the current preview. */
|
|
86
|
+
get current() {
|
|
87
|
+
return this.#current;
|
|
88
|
+
}
|
|
89
|
+
append(text) {
|
|
90
|
+
const start = this.#settled.length;
|
|
91
|
+
this.#file = this.#source.append(text);
|
|
92
|
+
this.#parser.append(text, sourceText(this.#file));
|
|
93
|
+
this.#current = this.update(start);
|
|
94
|
+
return this.#current;
|
|
95
|
+
}
|
|
96
|
+
edit(edit) {
|
|
97
|
+
const retired = this.retiredIds(edit);
|
|
98
|
+
this.#file = this.#source.replace(edit.start, edit.end, edit.text);
|
|
99
|
+
this.#parser.edit(edit);
|
|
100
|
+
this.#current = this.update(this.#settled.length, retired);
|
|
101
|
+
return this.#current;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Finishes the tail strictly and assembles the document from the settled
|
|
105
|
+
* blocks' nodes, so only the tail materializes again.
|
|
106
|
+
*/
|
|
107
|
+
complete() {
|
|
108
|
+
const limited = this.limitState();
|
|
109
|
+
if (limited !== void 0 && limited.limit !== "maximumPendingBlockLength") throw this.limitError(limited);
|
|
110
|
+
const tail = this.#parser.tailDraft().blocks;
|
|
111
|
+
const settled = this.#settled;
|
|
112
|
+
const diagnostics = [];
|
|
113
|
+
const errors = [];
|
|
114
|
+
const parts = [];
|
|
115
|
+
let nodes = 1 + this.#nodes;
|
|
116
|
+
for (const entry of settled) if (entry.materialized.kind === "invalid") errors.push(...entry.materialized.diagnostics);
|
|
117
|
+
else if (entry.materialized.kind === "ok") {
|
|
118
|
+
diagnostics.push(...entry.materialized.diagnostics);
|
|
119
|
+
parts.push({
|
|
120
|
+
id: entry.id,
|
|
121
|
+
origin: entry.origin,
|
|
122
|
+
node: entry.materialized.node
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
const tailIds = new Map(this.#tail.map((entry) => [entry.origin.start, entry.id]));
|
|
126
|
+
for (const syntax of tail) {
|
|
127
|
+
const origin = blockOrigin(sourceText(this.#file), syntax);
|
|
128
|
+
const materialized = materializeDocument(this.#file, [syntax], this.#parser.syntax, {
|
|
129
|
+
...this.#limits,
|
|
130
|
+
maximumNodes: Math.max(1, this.#limits.maximumNodes - nodes + 1)
|
|
131
|
+
}, {
|
|
132
|
+
keepReferences: true,
|
|
133
|
+
cache: this.#materializeCache,
|
|
134
|
+
definitionLookup: this.effectiveDefinitions().links
|
|
135
|
+
});
|
|
136
|
+
if (materialized.kind === "limitExceeded") throw this.limitError({
|
|
137
|
+
limit: materialized.limit,
|
|
138
|
+
offset: origin.end
|
|
139
|
+
});
|
|
140
|
+
if (materialized.kind === "invalid") {
|
|
141
|
+
errors.push(...materialized.diagnostics);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
diagnostics.push(...materialized.diagnostics);
|
|
145
|
+
for (const block of materialized.blocks) {
|
|
146
|
+
nodes += block.nodeCount;
|
|
147
|
+
parts.push({
|
|
148
|
+
id: tailIds.get(origin.start) ?? this.newId(),
|
|
149
|
+
origin,
|
|
150
|
+
node: block.node
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const [firstError, ...otherErrors] = errors;
|
|
155
|
+
if (firstError !== void 0) throw ParseError.invalidSyntax(this.#file, [firstError, ...otherErrors]);
|
|
156
|
+
if (nodes > this.#limits.maximumNodes) throw this.limitError({
|
|
157
|
+
limit: "maximumNodes",
|
|
158
|
+
offset: this.#file.length
|
|
159
|
+
});
|
|
160
|
+
const definitions = collectDefinitions(parts.map((part) => part.node));
|
|
161
|
+
const document = {
|
|
162
|
+
kind: "document",
|
|
163
|
+
children: parts.map((part) => resolveReferences(part.node, definitions, this.#file)),
|
|
164
|
+
origin: {
|
|
165
|
+
start: 0,
|
|
166
|
+
end: this.#file.length
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
return Object.freeze({
|
|
170
|
+
kind: "complete",
|
|
171
|
+
file: this.#file,
|
|
172
|
+
document,
|
|
173
|
+
blocks: Object.freeze(parts.map((part) => Object.freeze({
|
|
174
|
+
id: part.id,
|
|
175
|
+
origin: part.origin
|
|
176
|
+
}))),
|
|
177
|
+
diagnostics: Object.freeze(diagnostics)
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Settles queued blocks, renders the blocks whose definitions or footnote
|
|
182
|
+
* numbers changed, renders the open tail, and assembles the snapshot.
|
|
183
|
+
*/
|
|
184
|
+
update(previousSettled, retired) {
|
|
185
|
+
if (this.#file.length > this.#limits.maximumSourceLength) return this.limitChange({
|
|
186
|
+
limit: "maximumSourceLength",
|
|
187
|
+
offset: this.#file.length
|
|
188
|
+
});
|
|
189
|
+
const before = this.effectiveDefinitions();
|
|
190
|
+
const previousTail = this.#tail;
|
|
191
|
+
const start = Math.min(previousSettled, this.dropChangedSettled());
|
|
192
|
+
const firstAdded = this.#settled.length;
|
|
193
|
+
const adopted = this.settleQueued(previousTail, retired);
|
|
194
|
+
const draft = this.#parser.tailDraft();
|
|
195
|
+
const parts = draft.blocks.map((syntax) => this.materializeTail(syntax, draft.pending));
|
|
196
|
+
this.#tailDefinitions = collectDefinitions(parts.flatMap(materializedNodes));
|
|
197
|
+
const after = this.effectiveDefinitions();
|
|
198
|
+
const changed = changedDefinitions(before, after);
|
|
199
|
+
const refreshed = this.refreshSettled(changed, after, firstAdded, adopted, start);
|
|
200
|
+
const settledDefinitions = this.effectiveDefinitions();
|
|
201
|
+
const resolvedParts = parts.map((part) => {
|
|
202
|
+
if (part.materialized.kind !== "ok" || !part.materialized.references.some((id) => changed.links.has(id))) return part;
|
|
203
|
+
return {
|
|
204
|
+
...part,
|
|
205
|
+
materialized: this.materialize(part.syntax, this.#limits.maximumNodes - 1 - this.#nodes, part.pending !== void 0 && containsRange(part.syntax.range, part.pending.range) ? part.pending.range : void 0, settledDefinitions.links)
|
|
206
|
+
};
|
|
207
|
+
});
|
|
208
|
+
this.#tailDefinitions = collectDefinitions(resolvedParts.flatMap(materializedNodes));
|
|
209
|
+
const resolvedDefinitions = this.effectiveDefinitions();
|
|
210
|
+
this.renderTail(resolvedParts, previousTail, retired, resolvedDefinitions, changed.links);
|
|
211
|
+
const footnotes = this.footnoteSection(resolvedDefinitions);
|
|
212
|
+
const limited = this.limitState(draft.pending);
|
|
213
|
+
if (limited !== void 0) return this.limitChange(limited);
|
|
214
|
+
const snapshot = Object.freeze({
|
|
215
|
+
kind: "preview",
|
|
216
|
+
file: this.#file,
|
|
217
|
+
blocks: Object.freeze([...this.#blocks, ...this.#tail.map((entry) => entry.block)]),
|
|
218
|
+
footnotes,
|
|
219
|
+
diagnostics: Object.freeze([...this.#diagnostics, ...this.#tail.flatMap((entry) => entry.block.diagnostics)]),
|
|
220
|
+
limit: void 0
|
|
221
|
+
});
|
|
222
|
+
const continuous = !this.#limitedPreview;
|
|
223
|
+
this.#limitedPreview = false;
|
|
224
|
+
const previous = this.#lastValid;
|
|
225
|
+
this.#lastValid = snapshot;
|
|
226
|
+
return Object.freeze({
|
|
227
|
+
snapshot,
|
|
228
|
+
start: previous !== void 0 && continuous ? start : 0,
|
|
229
|
+
refreshed: Object.freeze(continuous ? refreshed : []),
|
|
230
|
+
footnotesChanged: footnotes !== previous?.footnotes
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Drops settled blocks that an edit replaced, which settle again from the
|
|
235
|
+
* queue, and returns how many settled blocks remain.
|
|
236
|
+
*/
|
|
237
|
+
dropChangedSettled() {
|
|
238
|
+
const keep = Math.min(this.#settled.length, this.#parser.settledCount, this.#queue[0]?.index ?? Infinity);
|
|
239
|
+
if (keep < this.#settled.length) this.truncate(keep);
|
|
240
|
+
return this.#settled.length;
|
|
241
|
+
}
|
|
242
|
+
/** Settles queued parser output and returns the indexes of blocks adopted from the tail. */
|
|
243
|
+
settleQueued(previousTail, retired) {
|
|
244
|
+
const adopted = /* @__PURE__ */ new Set();
|
|
245
|
+
for (const settlement of this.#queue) {
|
|
246
|
+
if (settlement.index !== this.#settled.length) continue;
|
|
247
|
+
const entry = this.settle(settlement.syntax, previousTail, retired);
|
|
248
|
+
if (entry.block !== void 0) adopted.add(this.#settled.length);
|
|
249
|
+
this.addSettled(entry);
|
|
250
|
+
}
|
|
251
|
+
this.#queue = [];
|
|
252
|
+
return adopted;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Renders newly settled blocks, and settled blocks whose definitions or
|
|
256
|
+
* footnote numbers changed. Returns the re-rendered blocks before `start`.
|
|
257
|
+
*/
|
|
258
|
+
refreshSettled(changed, definitions, firstAdded, adopted, start) {
|
|
259
|
+
const dirty = /* @__PURE__ */ new Set();
|
|
260
|
+
if (changed.links.size > 0) {
|
|
261
|
+
this.#loweringCache = createHtmlLoweringCache();
|
|
262
|
+
this.#materializeCache = createMaterializeCache();
|
|
263
|
+
this.#definitionsVersion++;
|
|
264
|
+
for (const identifier of changed.links) for (const index of this.#dependents.get(identifier) ?? []) dirty.add(index);
|
|
265
|
+
}
|
|
266
|
+
for (let index = firstAdded; index < this.#settled.length; index++) if (!adopted.has(index)) dirty.add(index);
|
|
267
|
+
let rematerializedFootnotes = false;
|
|
268
|
+
for (const index of this.#referenceLimits.keys()) dirty.add(index);
|
|
269
|
+
for (const index of dirty) {
|
|
270
|
+
const entry = this.#settled[index];
|
|
271
|
+
if (entry.materialized.kind === "ok" && (entry.materialized.references.some((id) => changed.links.has(id)) || this.#referenceLimits.has(index))) {
|
|
272
|
+
const old = entry.materialized;
|
|
273
|
+
const oldCount = old.nodeCount;
|
|
274
|
+
const materialized = this.materialize(entry.syntax, this.#limits.maximumNodes - 1 - this.#nodes + oldCount, void 0, definitions.links);
|
|
275
|
+
if (materialized.kind === "limitExceeded") {
|
|
276
|
+
this.#referenceLimits.set(index, {
|
|
277
|
+
limit: materialized.limit,
|
|
278
|
+
offset: entry.origin.end
|
|
279
|
+
});
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
this.#referenceLimits.delete(index);
|
|
283
|
+
if (materialized.kind === "ok") this.#definitions = {
|
|
284
|
+
links: replaceDefinitions(this.#definitions.links, old.contents.definitions, materialized.contents.definitions),
|
|
285
|
+
footnotes: replaceDefinitions(this.#definitions.footnotes, old.contents.footnotes, materialized.contents.footnotes)
|
|
286
|
+
};
|
|
287
|
+
this.#nodes += (materialized.kind === "ok" ? materialized.nodeCount : 0) - oldCount;
|
|
288
|
+
for (const identifier of old.contents.definitionReferences) this.#dependents.get(identifier)?.delete(index);
|
|
289
|
+
if (materialized.kind === "ok") for (const identifier of materialized.contents.definitionReferences) {
|
|
290
|
+
const dependents = this.#dependents.get(identifier) ?? /* @__PURE__ */ new Set();
|
|
291
|
+
dependents.add(index);
|
|
292
|
+
this.#dependents.set(identifier, dependents);
|
|
293
|
+
}
|
|
294
|
+
this.#settled[index] = {
|
|
295
|
+
...entry,
|
|
296
|
+
materialized
|
|
297
|
+
};
|
|
298
|
+
rematerializedFootnotes ||= old.contents.footnoteReferences.length > 0;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
definitions = this.effectiveDefinitions();
|
|
302
|
+
const renumberAll = changed.footnotes || this.#renumber || rematerializedFootnotes;
|
|
303
|
+
this.#renumber = false;
|
|
304
|
+
for (const index of this.renumber(renumberAll ? 0 : firstAdded)) dirty.add(index);
|
|
305
|
+
const refreshed = [];
|
|
306
|
+
for (const index of dirty) {
|
|
307
|
+
this.#settled[index] = this.render(this.#settled[index], definitions, this.#occurrences, true);
|
|
308
|
+
this.#blocks[index] = renderedBlock(this.#settled[index]);
|
|
309
|
+
if (index < start) refreshed.push(renderedBlock(this.#settled[index]));
|
|
310
|
+
}
|
|
311
|
+
for (const index of adopted) {
|
|
312
|
+
const entry = this.#settled[index];
|
|
313
|
+
const block = renderedBlock(entry);
|
|
314
|
+
if (!dirty.has(index) && !block.settled) {
|
|
315
|
+
this.#settled[index] = {
|
|
316
|
+
...entry,
|
|
317
|
+
block: Object.freeze({
|
|
318
|
+
...block,
|
|
319
|
+
settled: true
|
|
320
|
+
})
|
|
321
|
+
};
|
|
322
|
+
this.#blocks[index] = renderedBlock(this.#settled[index]);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return refreshed;
|
|
326
|
+
}
|
|
327
|
+
/** Adopts the tail's rendering for a block that settled unchanged, or queues it to render. */
|
|
328
|
+
settle(syntax, previousTail, retired) {
|
|
329
|
+
const adopted = previousTail.find((entry) => entry.syntax === syntax && entry.pending === void 0);
|
|
330
|
+
if (adopted !== void 0) return adopted;
|
|
331
|
+
const origin = blockOrigin(sourceText(this.#file), syntax);
|
|
332
|
+
return {
|
|
333
|
+
syntax,
|
|
334
|
+
id: this.blockId(origin, previousTail, retired),
|
|
335
|
+
origin,
|
|
336
|
+
materialized: this.materialize(syntax, this.#limits.maximumNodes - 1 - this.#nodes),
|
|
337
|
+
pending: void 0,
|
|
338
|
+
pendingNodes: 0,
|
|
339
|
+
occurrences: NO_OCCURRENCES,
|
|
340
|
+
block: void 0
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
materializeTail(syntax, pending) {
|
|
344
|
+
const open = pending !== void 0 && containsRange(syntax.range, pending.range) ? pending : void 0;
|
|
345
|
+
return {
|
|
346
|
+
syntax,
|
|
347
|
+
origin: blockOrigin(sourceText(this.#file), syntax),
|
|
348
|
+
materialized: this.materialize(syntax, this.#limits.maximumNodes - 1 - this.#nodes, open?.range),
|
|
349
|
+
pending: open
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
materialize(syntax, budget, open, definitions = this.effectiveDefinitions().links) {
|
|
353
|
+
if (budget < 1) return {
|
|
354
|
+
kind: "limitExceeded",
|
|
355
|
+
limit: "maximumNodes"
|
|
356
|
+
};
|
|
357
|
+
const result = materializeDocument(this.#file, [syntax], this.#parser.syntax, {
|
|
358
|
+
...this.#limits,
|
|
359
|
+
maximumNodes: budget + 1
|
|
360
|
+
}, {
|
|
361
|
+
keepReferences: true,
|
|
362
|
+
allowIncomplete: true,
|
|
363
|
+
cache: this.#materializeCache,
|
|
364
|
+
open,
|
|
365
|
+
definitionLookup: definitions
|
|
366
|
+
});
|
|
367
|
+
if (result.kind === "limitExceeded") return {
|
|
368
|
+
kind: "limitExceeded",
|
|
369
|
+
limit: result.limit
|
|
370
|
+
};
|
|
371
|
+
if (result.kind === "invalid") return {
|
|
372
|
+
kind: "invalid",
|
|
373
|
+
diagnostics: result.diagnostics
|
|
374
|
+
};
|
|
375
|
+
const [block] = result.blocks;
|
|
376
|
+
if (block === void 0) throw new Error("A stream block materialized to no node");
|
|
377
|
+
const contents = blockContents(block.node);
|
|
378
|
+
return {
|
|
379
|
+
kind: "ok",
|
|
380
|
+
node: block.node,
|
|
381
|
+
nodeCount: block.nodeCount,
|
|
382
|
+
references: block.references,
|
|
383
|
+
diagnostics: result.diagnostics,
|
|
384
|
+
contents: {
|
|
385
|
+
...contents,
|
|
386
|
+
definitionReferences: [.../* @__PURE__ */ new Set([...contents.definitionReferences, ...block.references])]
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
/** Adds one settled block to the running totals. Its rendering may still be pending. */
|
|
391
|
+
addSettled(entry) {
|
|
392
|
+
const index = this.#settled.length;
|
|
393
|
+
this.#settled.push(entry);
|
|
394
|
+
this.#blocks.push(entry.block ?? unrendered);
|
|
395
|
+
const { materialized } = entry;
|
|
396
|
+
if (materialized.kind === "limitExceeded") {
|
|
397
|
+
this.#limited ??= {
|
|
398
|
+
limit: materialized.limit,
|
|
399
|
+
offset: entry.origin.end
|
|
400
|
+
};
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
this.#diagnostics.push(...materialized.diagnostics);
|
|
404
|
+
if (materialized.kind === "invalid") return;
|
|
405
|
+
const { contents } = materialized;
|
|
406
|
+
this.#nodes += materialized.nodeCount;
|
|
407
|
+
if (contents.definitions.length > 0 || contents.footnotes.length > 0) {
|
|
408
|
+
const links = new Map(this.#definitions.links);
|
|
409
|
+
const footnotes = new Map(this.#definitions.footnotes);
|
|
410
|
+
addFirst(links, contents.definitions);
|
|
411
|
+
addFirst(footnotes, contents.footnotes);
|
|
412
|
+
this.#definitions = {
|
|
413
|
+
links,
|
|
414
|
+
footnotes
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
for (const identifier of contents.definitionReferences) {
|
|
418
|
+
let dependents = this.#dependents.get(identifier);
|
|
419
|
+
if (dependents === void 0) {
|
|
420
|
+
dependents = /* @__PURE__ */ new Set();
|
|
421
|
+
this.#dependents.set(identifier, dependents);
|
|
422
|
+
}
|
|
423
|
+
dependents.add(index);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
/** Drops the settled blocks from `length` on, after an edit before them. */
|
|
427
|
+
truncate(length) {
|
|
428
|
+
const kept = this.#settled.slice(0, length);
|
|
429
|
+
this.#settled = [];
|
|
430
|
+
this.#blocks = [];
|
|
431
|
+
this.#definitions = EMPTY_DEFINITIONS;
|
|
432
|
+
this.#dependents = /* @__PURE__ */ new Map();
|
|
433
|
+
this.#nodes = 0;
|
|
434
|
+
this.#diagnostics = [];
|
|
435
|
+
this.#limited = void 0;
|
|
436
|
+
for (const index of this.#referenceLimits.keys()) if (index >= length) this.#referenceLimits.delete(index);
|
|
437
|
+
for (const entry of kept) this.addSettled(entry);
|
|
438
|
+
this.#renumber = true;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Numbers footnote references in settled blocks from `from` on, continuing
|
|
442
|
+
* the numbering before them, and returns the blocks whose numbers changed.
|
|
443
|
+
*/
|
|
444
|
+
renumber(from) {
|
|
445
|
+
if (from === 0) {
|
|
446
|
+
this.#numbering = new FootnoteNumbering();
|
|
447
|
+
this.#occurrences = /* @__PURE__ */ new WeakMap();
|
|
448
|
+
}
|
|
449
|
+
const changed = [];
|
|
450
|
+
for (let index = from; index < this.#settled.length; index++) {
|
|
451
|
+
const entry = this.#settled[index];
|
|
452
|
+
const occurrences = numberReferences(entry.materialized, this.#numbering, this.#occurrences, (identifier) => this.isFootnoteDefined(identifier));
|
|
453
|
+
if (!sameOccurrences(entry.occurrences, occurrences)) {
|
|
454
|
+
changed.push(index);
|
|
455
|
+
this.#settled[index] = {
|
|
456
|
+
...entry,
|
|
457
|
+
occurrences
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
return changed;
|
|
462
|
+
}
|
|
463
|
+
renderTail(parts, previousTail, retired, definitions, changedLinks) {
|
|
464
|
+
this.#tailNumbering = this.#numbering.fork();
|
|
465
|
+
this.#tailOccurrences = /* @__PURE__ */ new WeakMap();
|
|
466
|
+
this.#tail = parts.map((part) => {
|
|
467
|
+
const occurrences = numberReferences(part.materialized, this.#tailNumbering, this.#tailOccurrences, (identifier) => this.isFootnoteDefined(identifier));
|
|
468
|
+
const reusable = previousTail.find((entry) => entry.syntax === part.syntax && entry.pending === void 0 && part.pending === void 0 && sameOccurrences(entry.occurrences, occurrences) && !dependsOn(entry, changedLinks));
|
|
469
|
+
if (reusable !== void 0) return reusable;
|
|
470
|
+
return this.render({
|
|
471
|
+
...part,
|
|
472
|
+
id: this.blockId(part.origin, previousTail, retired),
|
|
473
|
+
pendingNodes: 0,
|
|
474
|
+
occurrences,
|
|
475
|
+
block: void 0
|
|
476
|
+
}, definitions, this.#tailOccurrences, false);
|
|
477
|
+
});
|
|
478
|
+
const last = this.#tail.at(-1);
|
|
479
|
+
if (last !== void 0) {
|
|
480
|
+
const nodes = trimOpenTail(last.block.nodes);
|
|
481
|
+
if (nodes !== last.block.nodes) this.#tail[this.#tail.length - 1] = {
|
|
482
|
+
...last,
|
|
483
|
+
block: Object.freeze({
|
|
484
|
+
...last.block,
|
|
485
|
+
nodes: Object.freeze(nodes)
|
|
486
|
+
})
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
/** Lowers one block in the stream's scope. */
|
|
491
|
+
render(entry, definitions, occurrences, settled) {
|
|
492
|
+
const { materialized, pending } = entry;
|
|
493
|
+
if (materialized.kind !== "ok") {
|
|
494
|
+
const invalid = materialized.kind === "invalid";
|
|
495
|
+
return {
|
|
496
|
+
...entry,
|
|
497
|
+
block: Object.freeze({
|
|
498
|
+
id: entry.id,
|
|
499
|
+
origin: entry.origin,
|
|
500
|
+
nodes: Object.freeze(invalid ? inertSource(this.#file, entry.origin) : []),
|
|
501
|
+
status: invalid ? "invalid" : "valid",
|
|
502
|
+
settled,
|
|
503
|
+
diagnostics: invalid ? materialized.diagnostics : Object.freeze([]),
|
|
504
|
+
dependencies: NO_DEPENDENCIES
|
|
505
|
+
})
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
let pendingNodes = 0;
|
|
509
|
+
const references = new Set(materialized.references);
|
|
510
|
+
const scope = {
|
|
511
|
+
definition: (identifier) => definitions.links.get(identifier),
|
|
512
|
+
footnote: (identifier) => definitions.footnotes.get(identifier),
|
|
513
|
+
occurrence: (node) => occurrences.get(node),
|
|
514
|
+
options: { source: this.#file },
|
|
515
|
+
provisional: true,
|
|
516
|
+
cache: this.#loweringCache
|
|
517
|
+
};
|
|
518
|
+
const nodes = lowerNodes([materialized.node], pending === void 0 ? scope : {
|
|
519
|
+
...scope,
|
|
520
|
+
replace: (node) => {
|
|
521
|
+
const open = lowerOpenLeaf(node, pending, {
|
|
522
|
+
file: this.#file,
|
|
523
|
+
definitions: definitions.links,
|
|
524
|
+
references,
|
|
525
|
+
syntax: this.#parser.syntax,
|
|
526
|
+
limits: this.#limits,
|
|
527
|
+
fence: this.#fence,
|
|
528
|
+
paragraph: this.#paragraph,
|
|
529
|
+
phrasing: this.#phrasing,
|
|
530
|
+
lowering: this.#loweringCache
|
|
531
|
+
}, (children, previous) => lowerNodes(children, scope, previous));
|
|
532
|
+
pendingNodes += open?.nodeCount ?? 0;
|
|
533
|
+
return open?.nodes;
|
|
534
|
+
}
|
|
535
|
+
});
|
|
536
|
+
const contents = {
|
|
537
|
+
...materialized.contents,
|
|
538
|
+
definitionReferences: [.../* @__PURE__ */ new Set([...materialized.contents.definitionReferences, ...references])]
|
|
539
|
+
};
|
|
540
|
+
return {
|
|
541
|
+
...entry,
|
|
542
|
+
materialized: {
|
|
543
|
+
...materialized,
|
|
544
|
+
contents,
|
|
545
|
+
references: [...references]
|
|
546
|
+
},
|
|
547
|
+
pendingNodes,
|
|
548
|
+
block: Object.freeze({
|
|
549
|
+
id: entry.id,
|
|
550
|
+
origin: entry.origin,
|
|
551
|
+
nodes: Object.freeze(nodes),
|
|
552
|
+
status: "valid",
|
|
553
|
+
settled,
|
|
554
|
+
diagnostics: materialized.diagnostics,
|
|
555
|
+
dependencies: dependenciesOf(contents)
|
|
556
|
+
})
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
isFootnoteDefined(identifier) {
|
|
560
|
+
return this.#definitions.footnotes.has(identifier) || this.#tailDefinitions.footnotes.has(identifier);
|
|
561
|
+
}
|
|
562
|
+
effectiveDefinitions() {
|
|
563
|
+
const tail = this.#tailDefinitions;
|
|
564
|
+
if (tail.links.size === 0 && tail.footnotes.size === 0) return this.#definitions;
|
|
565
|
+
const links = new Map(this.#definitions.links);
|
|
566
|
+
const footnotes = new Map(this.#definitions.footnotes);
|
|
567
|
+
addFirst(links, [...tail.links.values()]);
|
|
568
|
+
addFirst(footnotes, [...tail.footnotes.values()]);
|
|
569
|
+
return {
|
|
570
|
+
links,
|
|
571
|
+
footnotes
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
/** The footnote section, rebuilt only when its numbering or definitions change. */
|
|
575
|
+
footnoteSection(definitions) {
|
|
576
|
+
const numbering = this.#tailNumbering;
|
|
577
|
+
const key = [this.#definitionsVersion, ...numbering.order.flatMap((identifier) => [
|
|
578
|
+
identifier,
|
|
579
|
+
numbering.count(identifier),
|
|
580
|
+
definitions.footnotes.get(identifier)
|
|
581
|
+
])];
|
|
582
|
+
if (key.length === this.#footnotesKey.length && key.every((value, index) => value === this.#footnotesKey[index])) return this.#footnotes;
|
|
583
|
+
this.#footnotesKey = key;
|
|
584
|
+
this.#footnotes = lowerFootnoteSection(numbering, {
|
|
585
|
+
definition: (identifier) => definitions.links.get(identifier),
|
|
586
|
+
footnote: (identifier) => definitions.footnotes.get(identifier),
|
|
587
|
+
occurrence: (node) => this.#occurrences.get(node) ?? this.#tailOccurrences.get(node),
|
|
588
|
+
options: { source: this.#file },
|
|
589
|
+
provisional: true
|
|
590
|
+
});
|
|
591
|
+
return this.#footnotes;
|
|
592
|
+
}
|
|
593
|
+
/** The first limit the stream exceeds, if any. */
|
|
594
|
+
limitState(pending) {
|
|
595
|
+
if (this.#file.length > this.#limits.maximumSourceLength) return {
|
|
596
|
+
limit: "maximumSourceLength",
|
|
597
|
+
offset: this.#file.length
|
|
598
|
+
};
|
|
599
|
+
if (this.#limited !== void 0) return this.#limited;
|
|
600
|
+
const referenceLimit = this.#referenceLimits.values().next().value;
|
|
601
|
+
if (referenceLimit !== void 0) return referenceLimit;
|
|
602
|
+
let nodes = 1 + this.#nodes;
|
|
603
|
+
for (const entry of this.#tail) {
|
|
604
|
+
if (entry.materialized.kind === "limitExceeded") return {
|
|
605
|
+
limit: entry.materialized.limit,
|
|
606
|
+
offset: entry.origin.end
|
|
607
|
+
};
|
|
608
|
+
nodes += (entry.materialized.kind === "ok" ? entry.materialized.nodeCount : 0) + entry.pendingNodes;
|
|
609
|
+
}
|
|
610
|
+
if (nodes > this.#limits.maximumNodes) return {
|
|
611
|
+
limit: "maximumNodes",
|
|
612
|
+
offset: this.#tail.at(-1)?.origin.end ?? 0
|
|
613
|
+
};
|
|
614
|
+
const owner = pending === void 0 ? void 0 : this.#tail.find((entry) => entry.pending !== void 0);
|
|
615
|
+
if (owner !== void 0 && owner.syntax.range.end - owner.syntax.range.start > this.#maximumPendingBlockLength) return {
|
|
616
|
+
limit: "maximumPendingBlockLength",
|
|
617
|
+
offset: owner.syntax.range.end
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
/** Keeps the last preview within limits, with its block identities. */
|
|
621
|
+
limitChange(state) {
|
|
622
|
+
this.#limitedPreview = true;
|
|
623
|
+
const snapshot = Object.freeze({
|
|
624
|
+
kind: "preview",
|
|
625
|
+
file: this.#file,
|
|
626
|
+
blocks: this.#lastValid?.blocks ?? Object.freeze([]),
|
|
627
|
+
footnotes: this.#lastValid?.footnotes,
|
|
628
|
+
diagnostics: Object.freeze([limitDiagnostic(this.#file, state)]),
|
|
629
|
+
limit: state.limit
|
|
630
|
+
});
|
|
631
|
+
return Object.freeze({
|
|
632
|
+
snapshot,
|
|
633
|
+
start: snapshot.blocks.length,
|
|
634
|
+
refreshed: Object.freeze([]),
|
|
635
|
+
footnotesChanged: false
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
limitError(state) {
|
|
639
|
+
const maximum = state.limit === "maximumPendingBlockLength" ? this.#maximumPendingBlockLength : this.#limits[state.limit];
|
|
640
|
+
return LimitError.exceeded(this.#file, state.limit, maximum, {
|
|
641
|
+
start: state.offset,
|
|
642
|
+
end: state.offset
|
|
643
|
+
}, state.limit === "maximumSourceLength" ? this.#file.length : void 0);
|
|
644
|
+
}
|
|
645
|
+
/** A block keeps its identity across appends, and across edits that do not touch it. */
|
|
646
|
+
blockId(origin, previousTail, retired) {
|
|
647
|
+
if (retired !== void 0) return retired.get(rangeKey(origin)) ?? this.newId();
|
|
648
|
+
return previousTail.find((entry) => entry.origin.start === origin.start)?.id ?? this.newId();
|
|
649
|
+
}
|
|
650
|
+
/** Identities of blocks an edit does not touch, keyed by their range after the edit. */
|
|
651
|
+
retiredIds(edit) {
|
|
652
|
+
const retired = /* @__PURE__ */ new Map();
|
|
653
|
+
const delta = edit.text.length - (edit.end - edit.start);
|
|
654
|
+
for (const entry of [...this.#settled, ...this.#tail]) if (!rangesIntersect(entry.origin, edit)) retired.set(rangeKey(entry.origin.start >= edit.end ? shiftRange(entry.origin, delta) : entry.origin), entry.id);
|
|
655
|
+
return retired;
|
|
656
|
+
}
|
|
657
|
+
newId() {
|
|
658
|
+
const value = `block-${this.#nextId++}`;
|
|
659
|
+
if (!isBlockId(value)) throw new Error("Internal block identity invariant failed");
|
|
660
|
+
return value;
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
/** Stands in for a settled block until it renders later in the same update. */
|
|
664
|
+
const unrendered = Object.freeze({
|
|
665
|
+
id: placeholderId(),
|
|
666
|
+
origin: Object.freeze({
|
|
667
|
+
start: 0,
|
|
668
|
+
end: 0
|
|
669
|
+
}),
|
|
670
|
+
nodes: Object.freeze([]),
|
|
671
|
+
status: "valid",
|
|
672
|
+
settled: true,
|
|
673
|
+
diagnostics: Object.freeze([]),
|
|
674
|
+
dependencies: NO_DEPENDENCIES
|
|
675
|
+
});
|
|
676
|
+
/** Every settled entry renders before an update publishes its snapshot. */
|
|
677
|
+
function renderedBlock(entry) {
|
|
678
|
+
if (entry.block === void 0) throw new Error("A settled stream block was not rendered");
|
|
679
|
+
return entry.block;
|
|
680
|
+
}
|
|
681
|
+
function materializedNodes(part) {
|
|
682
|
+
return part.materialized.kind === "ok" ? [part.materialized.node] : [];
|
|
683
|
+
}
|
|
684
|
+
const emptyContents = Object.freeze({
|
|
685
|
+
definitionReferences: Object.freeze([]),
|
|
686
|
+
footnoteReferences: Object.freeze([]),
|
|
687
|
+
definitions: Object.freeze([]),
|
|
688
|
+
footnotes: Object.freeze([])
|
|
689
|
+
});
|
|
690
|
+
/** Contents by node identity. Trees are immutable, so a reused subtree is walked once. */
|
|
691
|
+
const contentsCache = /* @__PURE__ */ new WeakMap();
|
|
692
|
+
/** The references a node makes and the definitions it contains, in document order. */
|
|
693
|
+
function blockContents(node) {
|
|
694
|
+
const hit = contentsCache.get(node);
|
|
695
|
+
if (hit !== void 0) return hit;
|
|
696
|
+
if (node.kind === "list") return listContents(node);
|
|
697
|
+
const parts = mdxChildren(node).map(blockContents);
|
|
698
|
+
switch (node.kind) {
|
|
699
|
+
case "linkReference":
|
|
700
|
+
case "imageReference":
|
|
701
|
+
parts.unshift({
|
|
702
|
+
...emptyContents,
|
|
703
|
+
definitionReferences: [node.identifier]
|
|
704
|
+
});
|
|
705
|
+
break;
|
|
706
|
+
case "footnoteReference":
|
|
707
|
+
parts.unshift({
|
|
708
|
+
...emptyContents,
|
|
709
|
+
footnoteReferences: [node]
|
|
710
|
+
});
|
|
711
|
+
break;
|
|
712
|
+
case "definition":
|
|
713
|
+
parts.unshift({
|
|
714
|
+
...emptyContents,
|
|
715
|
+
definitions: [node]
|
|
716
|
+
});
|
|
717
|
+
break;
|
|
718
|
+
case "footnoteDefinition": parts.unshift({
|
|
719
|
+
...emptyContents,
|
|
720
|
+
footnotes: [node]
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
const filled = parts.filter((part) => part !== emptyContents);
|
|
724
|
+
const contents = filled.length === 0 ? emptyContents : filled.length === 1 ? filled[0] : {
|
|
725
|
+
definitionReferences: [...new Set(filled.flatMap((part) => part.definitionReferences))],
|
|
726
|
+
footnoteReferences: filled.flatMap((part) => part.footnoteReferences),
|
|
727
|
+
definitions: filled.flatMap((part) => part.definitions),
|
|
728
|
+
footnotes: filled.flatMap((part) => part.footnotes)
|
|
729
|
+
};
|
|
730
|
+
contentsCache.set(node, contents);
|
|
731
|
+
return contents;
|
|
732
|
+
}
|
|
733
|
+
/** A list's contents after each of its last items, by item. */
|
|
734
|
+
const listContentsCache = /* @__PURE__ */ new WeakMap();
|
|
735
|
+
/** A growing list combines the contents of its unchanged leading items once. */
|
|
736
|
+
function listContents(node) {
|
|
737
|
+
const items = node.children;
|
|
738
|
+
let start = 0;
|
|
739
|
+
let contents = emptyContents;
|
|
740
|
+
for (let index = items.length - 1; index >= Math.max(0, items.length - 8); index--) {
|
|
741
|
+
const prefix = listContentsCache.get(items[index]);
|
|
742
|
+
if (prefix?.index === index) {
|
|
743
|
+
start = index + 1;
|
|
744
|
+
contents = prefix.contents;
|
|
745
|
+
break;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
for (let index = start; index < items.length; index++) {
|
|
749
|
+
contents = mergeContents(contents, blockContents(items[index]));
|
|
750
|
+
if (index >= items.length - 8) listContentsCache.set(items[index], {
|
|
751
|
+
index,
|
|
752
|
+
contents
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
contentsCache.set(node, contents);
|
|
756
|
+
return contents;
|
|
757
|
+
}
|
|
758
|
+
function mergeContents(left, right) {
|
|
759
|
+
if (right === emptyContents) return left;
|
|
760
|
+
if (left === emptyContents) return right;
|
|
761
|
+
return {
|
|
762
|
+
definitionReferences: [.../* @__PURE__ */ new Set([...left.definitionReferences, ...right.definitionReferences])],
|
|
763
|
+
footnoteReferences: [...left.footnoteReferences, ...right.footnoteReferences],
|
|
764
|
+
definitions: [...left.definitions, ...right.definitions],
|
|
765
|
+
footnotes: [...left.footnotes, ...right.footnotes]
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
function collectDefinitions(nodes) {
|
|
769
|
+
const links = /* @__PURE__ */ new Map();
|
|
770
|
+
const footnotes = /* @__PURE__ */ new Map();
|
|
771
|
+
for (const node of nodes) {
|
|
772
|
+
const contents = blockContents(node);
|
|
773
|
+
addFirst(links, contents.definitions);
|
|
774
|
+
addFirst(footnotes, contents.footnotes);
|
|
775
|
+
}
|
|
776
|
+
return {
|
|
777
|
+
links,
|
|
778
|
+
footnotes
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
/** Replaces re-materialized definitions only when their old node was the winning definition. */
|
|
782
|
+
function replaceDefinitions(current, previous, next) {
|
|
783
|
+
if (previous.length === 0) return current;
|
|
784
|
+
const old = new Set(previous);
|
|
785
|
+
const updated = new Map(current);
|
|
786
|
+
for (const node of next) {
|
|
787
|
+
const winner = updated.get(node.identifier);
|
|
788
|
+
if (winner !== void 0 && old.has(winner)) updated.set(node.identifier, node);
|
|
789
|
+
}
|
|
790
|
+
return updated;
|
|
791
|
+
}
|
|
792
|
+
function addFirst(target, nodes) {
|
|
793
|
+
for (const node of nodes) if (!target.has(node.identifier)) target.set(node.identifier, node);
|
|
794
|
+
}
|
|
795
|
+
function changedDefinitions(before, after) {
|
|
796
|
+
const links = /* @__PURE__ */ new Set();
|
|
797
|
+
if (before.links !== after.links) for (const identifier of /* @__PURE__ */ new Set([...before.links.keys(), ...after.links.keys()])) {
|
|
798
|
+
const previous = before.links.get(identifier);
|
|
799
|
+
const next = after.links.get(identifier);
|
|
800
|
+
if (previous?.url !== next?.url || previous?.title !== next?.title) links.add(identifier);
|
|
801
|
+
}
|
|
802
|
+
let footnotes = before.footnotes.size !== after.footnotes.size;
|
|
803
|
+
for (const identifier of after.footnotes.keys()) footnotes ||= !before.footnotes.has(identifier);
|
|
804
|
+
return {
|
|
805
|
+
links,
|
|
806
|
+
footnotes
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
function numberReferences(materialized, numbering, occurrences, defined) {
|
|
810
|
+
if (materialized.kind !== "ok" || materialized.contents.footnoteReferences.length === 0) return NO_OCCURRENCES;
|
|
811
|
+
return materialized.contents.footnoteReferences.map((node) => {
|
|
812
|
+
if (!defined(node.identifier)) return;
|
|
813
|
+
const occurrence = numbering.reference(node.identifier);
|
|
814
|
+
occurrences.set(node, occurrence);
|
|
815
|
+
return occurrence;
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
function sameOccurrences(left, right) {
|
|
819
|
+
return left === right || left.length === right.length && left.every((occurrence, index) => occurrence?.ordinal === right[index]?.ordinal && occurrence?.occurrence === right[index]?.occurrence);
|
|
820
|
+
}
|
|
821
|
+
function dependsOn(entry, identifiers) {
|
|
822
|
+
return identifiers.size > 0 && entry.materialized.kind === "ok" && entry.materialized.contents.definitionReferences.some((identifier) => identifiers.has(identifier));
|
|
823
|
+
}
|
|
824
|
+
function dependenciesOf(contents) {
|
|
825
|
+
if (contents.definitionReferences.length === 0 && contents.footnoteReferences.length === 0) return NO_DEPENDENCIES;
|
|
826
|
+
return Object.freeze({
|
|
827
|
+
definitions: Object.freeze([...contents.definitionReferences]),
|
|
828
|
+
footnotes: Object.freeze([...new Set(contents.footnoteReferences.map((node) => node.identifier))])
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
/** Turns references without definitions into their authored text, like batch parsing. */
|
|
832
|
+
function resolveReferences(node, definitions, file) {
|
|
833
|
+
const contents = blockContents(node);
|
|
834
|
+
if (!(contents.definitionReferences.some((identifier) => !definitions.links.has(identifier)) || contents.footnoteReferences.some((reference) => !definitions.footnotes.has(reference.identifier)))) return node;
|
|
835
|
+
const authored = (reference) => reference.origin === void 0 ? void 0 : {
|
|
836
|
+
kind: "text",
|
|
837
|
+
value: file.slice(reference.origin),
|
|
838
|
+
origin: reference.origin
|
|
839
|
+
};
|
|
840
|
+
const [result] = rewriteMdx({
|
|
841
|
+
kind: "document",
|
|
842
|
+
children: [node]
|
|
843
|
+
}, {
|
|
844
|
+
linkReference: ({ node: reference }) => definitions.links.has(reference.identifier) ? void 0 : authored(reference),
|
|
845
|
+
imageReference: ({ node: reference }) => definitions.links.has(reference.identifier) ? void 0 : authored(reference),
|
|
846
|
+
footnoteReference: ({ node: reference }) => definitions.footnotes.has(reference.identifier) ? void 0 : authored(reference)
|
|
847
|
+
}).children;
|
|
848
|
+
if (result === void 0) throw new Error("Reference resolution removed a stream block");
|
|
849
|
+
return result;
|
|
850
|
+
}
|
|
851
|
+
/** Invalid authored source renders as inert text. */
|
|
852
|
+
function inertSource(file, origin) {
|
|
853
|
+
return [{
|
|
854
|
+
kind: "element",
|
|
855
|
+
tagName: "p",
|
|
856
|
+
attributes: {},
|
|
857
|
+
children: [{
|
|
858
|
+
kind: "text",
|
|
859
|
+
value: file.semanticSlice(origin).trimEnd(),
|
|
860
|
+
origin
|
|
861
|
+
}],
|
|
862
|
+
origin
|
|
863
|
+
}];
|
|
864
|
+
}
|
|
865
|
+
function limitDiagnostic(file, state) {
|
|
866
|
+
return createDiagnostic({
|
|
867
|
+
code: "mdx-limit-exceeded",
|
|
868
|
+
severity: "error",
|
|
869
|
+
message: `${state.limit} was exceeded at source offset ${state.offset}`,
|
|
870
|
+
span: {
|
|
871
|
+
file,
|
|
872
|
+
start: state.offset,
|
|
873
|
+
end: state.offset
|
|
874
|
+
}
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
/** A block starts at the start of its first physical line. */
|
|
878
|
+
function blockOrigin(text, syntax) {
|
|
879
|
+
let start = syntax.range.start;
|
|
880
|
+
while (start > 0 && text.char(start - 1) !== "\n" && text.char(start - 1) !== "\r") start--;
|
|
881
|
+
return {
|
|
882
|
+
start,
|
|
883
|
+
end: syntax.range.end
|
|
884
|
+
};
|
|
885
|
+
}
|
|
886
|
+
function containsRange(outer, inner) {
|
|
887
|
+
return outer.start <= inner.start && inner.end <= outer.end;
|
|
888
|
+
}
|
|
889
|
+
function rangeKey(range) {
|
|
890
|
+
return `${range.start}:${range.end}`;
|
|
891
|
+
}
|
|
892
|
+
/** The placeholder never reaches a snapshot, so its identity never meets a real block. */
|
|
893
|
+
function placeholderId() {
|
|
894
|
+
const value = "block-0";
|
|
895
|
+
if (!isBlockId(value)) throw new Error("Internal block identity invariant failed");
|
|
896
|
+
return value;
|
|
897
|
+
}
|
|
898
|
+
function isBlockId(value) {
|
|
899
|
+
return /^block-\d+$/u.test(value);
|
|
900
|
+
}
|
|
901
|
+
//#endregion
|
|
902
|
+
export { StreamSession };
|
|
903
|
+
|
|
904
|
+
//# sourceMappingURL=stream-session.mjs.map
|