@vscode/markdown-editor 0.0.2-0 → 0.0.2-10

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.
Files changed (106) hide show
  1. package/dist/_observables/assert.d.ts +2 -0
  2. package/dist/_observables/deps.d.ts +28 -0
  3. package/dist/_observables/disposables.d.ts +19 -0
  4. package/dist/_observables/equals.d.ts +32 -0
  5. package/dist/_observables/index.d.ts +2 -0
  6. package/dist/_observables/observableInternal/base.d.ts +172 -0
  7. package/dist/_observables/observableInternal/changeTracker.d.ts +44 -0
  8. package/dist/_observables/observableInternal/commonFacade/cancellation.d.ts +24 -0
  9. package/dist/_observables/observableInternal/commonFacade/deps.d.ts +24 -0
  10. package/dist/_observables/observableInternal/debugLocation.d.ts +21 -0
  11. package/dist/_observables/observableInternal/debugName.d.ts +33 -0
  12. package/dist/_observables/observableInternal/experimental/deferUnobserve.d.ts +16 -0
  13. package/dist/_observables/observableInternal/experimental/reducer.d.ts +37 -0
  14. package/dist/_observables/observableInternal/experimental/utils.d.ts +15 -0
  15. package/dist/_observables/observableInternal/index.d.ts +25 -0
  16. package/dist/_observables/observableInternal/logging/consoleObservableLogger.d.ts +40 -0
  17. package/dist/_observables/observableInternal/logging/debugGetDependencyGraph.d.ts +4 -0
  18. package/dist/_observables/observableInternal/logging/debugger/debuggerRpc.d.ts +4 -0
  19. package/dist/_observables/observableInternal/logging/debugger/devToolsLogger.d.ts +43 -0
  20. package/dist/_observables/observableInternal/logging/debugger/rpc.d.ts +41 -0
  21. package/dist/_observables/observableInternal/logging/debugger/utils.d.ts +13 -0
  22. package/dist/_observables/observableInternal/logging/logging.d.ts +30 -0
  23. package/dist/_observables/observableInternal/map.d.ts +18 -0
  24. package/dist/_observables/observableInternal/observables/baseObservable.d.ts +58 -0
  25. package/dist/_observables/observableInternal/observables/constObservable.d.ts +5 -0
  26. package/dist/_observables/observableInternal/observables/derived.d.ts +46 -0
  27. package/dist/_observables/observableInternal/observables/derivedImpl.d.ts +83 -0
  28. package/dist/_observables/observableInternal/observables/lazyObservableValue.d.ts +27 -0
  29. package/dist/_observables/observableInternal/observables/observableFromEvent.d.ts +37 -0
  30. package/dist/_observables/observableInternal/observables/observableSignal.d.ts +11 -0
  31. package/dist/_observables/observableInternal/observables/observableSignalFromEvent.d.ts +5 -0
  32. package/dist/_observables/observableInternal/observables/observableValue.d.ts +37 -0
  33. package/dist/_observables/observableInternal/observables/observableValueOpts.d.ts +8 -0
  34. package/dist/_observables/observableInternal/reactions/autorun.d.ts +56 -0
  35. package/dist/_observables/observableInternal/reactions/autorunImpl.d.ts +53 -0
  36. package/dist/_observables/observableInternal/set.d.ts +17 -0
  37. package/dist/_observables/observableInternal/transaction.d.ts +27 -0
  38. package/dist/_observables/observableInternal/utils/promise.d.ts +75 -0
  39. package/dist/_observables/observableInternal/utils/runOnChange.d.ts +7 -0
  40. package/dist/_observables/observableInternal/utils/utils.d.ts +43 -0
  41. package/dist/_observables/observableInternal/utils/utilsCancellation.d.ts +10 -0
  42. package/dist/_observables/observableInternal/utils/valueWithChangeEvent.d.ts +10 -0
  43. package/dist/_observables/utils.d.ts +15 -0
  44. package/dist/index.d.ts +2057 -6
  45. package/dist/index.js +1674 -1175
  46. package/dist/index.js.map +1 -1
  47. package/dist/observables.d.ts +4 -1
  48. package/dist/observables.js +90 -114
  49. package/dist/observables.js.map +1 -1
  50. package/dist/{runOnChange-owE1SMC0.js → runOnChange-C00UIwqQ.js} +130 -106
  51. package/dist/runOnChange-C00UIwqQ.js.map +1 -0
  52. package/package.json +14 -7
  53. package/src/view/editor.css +146 -19
  54. package/src/view/themes/github.css +0 -5
  55. package/src/view/themes/vscode.css +331 -0
  56. package/dist/commands/cursorCommands.d.ts +0 -13
  57. package/dist/commands/editCommands.d.ts +0 -14
  58. package/dist/commands/index.d.ts +0 -4
  59. package/dist/commands/selectionCommands.d.ts +0 -6
  60. package/dist/commands/types.d.ts +0 -26
  61. package/dist/core/geometry.d.ts +0 -37
  62. package/dist/core/index.d.ts +0 -8
  63. package/dist/core/lengthEdit.d.ts +0 -38
  64. package/dist/core/offsetRange.d.ts +0 -26
  65. package/dist/core/selection.d.ts +0 -13
  66. package/dist/core/sourceOffset.d.ts +0 -1
  67. package/dist/core/stringEdit.d.ts +0 -27
  68. package/dist/core/stringValue.d.ts +0 -8
  69. package/dist/core/wordUtils.d.ts +0 -6
  70. package/dist/highlighter/defaultMonacoSyntaxHighlighter.d.ts +0 -20
  71. package/dist/highlighter/index.d.ts +0 -3
  72. package/dist/highlighter/monacoSyntaxHighlighter.d.ts +0 -38
  73. package/dist/highlighter/syntaxHighlighter.d.ts +0 -67
  74. package/dist/model/cursorNavigation.d.ts +0 -7
  75. package/dist/model/editorModel.d.ts +0 -54
  76. package/dist/model/index.d.ts +0 -4
  77. package/dist/model/measuredLayoutModel.d.ts +0 -50
  78. package/dist/parser/_micromarkAdapter.d.ts +0 -7
  79. package/dist/parser/ast.d.ts +0 -274
  80. package/dist/parser/index.d.ts +0 -4
  81. package/dist/parser/parse.d.ts +0 -2
  82. package/dist/parser/parser.d.ts +0 -14
  83. package/dist/parser/reconcile.d.ts +0 -33
  84. package/dist/parser/test/getAnnotatedSource.d.ts +0 -2
  85. package/dist/parser/test/snapshot.d.ts +0 -9
  86. package/dist/parser/visualizeAst.d.ts +0 -33
  87. package/dist/runOnChange-owE1SMC0.js.map +0 -1
  88. package/dist/test/random.d.ts +0 -16
  89. package/dist/view/content/blockView.d.ts +0 -179
  90. package/dist/view/content/documentView.d.ts +0 -41
  91. package/dist/view/content/dom.d.ts +0 -16
  92. package/dist/view/content/katexEditableIdentifiers.d.ts +0 -36
  93. package/dist/view/content/viewNode.d.ts +0 -93
  94. package/dist/view/editorController.d.ts +0 -34
  95. package/dist/view/editorView.d.ts +0 -100
  96. package/dist/view/fixture/astViewerView.d.ts +0 -27
  97. package/dist/view/fixture/cyclingTsHighlighter.d.ts +0 -17
  98. package/dist/view/fixture/debugColors.d.ts +0 -26
  99. package/dist/view/fixture/monacoDebugPanel.d.ts +0 -7
  100. package/dist/view/index.d.ts +0 -9
  101. package/dist/view/measuredLayoutDebugView.d.ts +0 -70
  102. package/dist/view/parts/cursorView.d.ts +0 -29
  103. package/dist/view/parts/selectionView.d.ts +0 -57
  104. package/dist/view/viewData.d.ts +0 -251
  105. package/dist/view/visualLineMap.d.ts +0 -157
  106. package/dist/view/visualizeViewTree.d.ts +0 -5
package/dist/index.d.ts CHANGED
@@ -1,6 +1,2057 @@
1
- export * from './core/index.js';
2
- export * from './parser/index.js';
3
- export * from './model/index.js';
4
- export * from './commands/index.js';
5
- export * from './view/index.js';
6
- export * from './highlighter/index.js';
1
+ import { Disposable } from './_observables/index';
2
+ import { IDisposable } from './_observables/index';
3
+ import { IObservable } from './_observables/index';
4
+ import { IObservableWithChange } from './_observables/index';
5
+ import { ISettableObservable } from './_observables/index';
6
+ import { ITransaction } from './_observables/index';
7
+ import { MonarchTokenizer } from 'monaco-editor/esm/vs/editor/standalone/common/monarch/monarchLexer.js';
8
+
9
+ /** Every concrete node kind, for exhaustive consumer-side dispatch. */
10
+ export declare type AnyAstNode = TextAstNode | MarkerAstNode | GlueAstNode | ThematicBreakAstNode | StrongAstNode | EmphasisAstNode | StrikethroughAstNode | InlineCodeAstNode | InlineMathAstNode | LinkAstNode | ImageAstNode | HeadingAstNode | ParagraphAstNode | CodeBlockAstNode | MathBlockAstNode | BlockQuoteAstNode | ListAstNode | ListItemAstNode | TableAstNode | TableRowAstNode | TableCellAstNode | DocumentAstNode;
11
+
12
+ declare type AnyViewData = DocumentViewData | BlockViewData | InlineViewData | ListItemViewData | TableRowViewData | TableCellViewData | MarkerViewData | GlueViewData;
13
+
14
+ export declare abstract class AstNode {
15
+ abstract readonly kind: string;
16
+ abstract get children(): readonly AstNode[];
17
+ /**
18
+ * A stable identity. Every node has one: it is minted on construction and
19
+ * carried across edits by reconciliation, so a node that survives an edit
20
+ * (even with changed content) keeps the same id.
21
+ */
22
+ readonly id: number;
23
+ /** Rebuild this node with each child replaced by `map.get(child) ?? child`. */
24
+ abstract mapChildren(map: ReadonlyMap<AstNode, AstNode>): AstNode;
25
+ private _length;
26
+ get length(): number;
27
+ /**
28
+ * True when `other` has the same content. Containers compare children *by
29
+ * identity* (`===`): bottom-up reconciliation substitutes reused old
30
+ * instances into the fresh tree first, so equal children already share
31
+ * instances — keeping this O(children), not O(subtree). Leaves have no
32
+ * children, so {@link _localEquals} is their whole comparison.
33
+ */
34
+ equalsShallow(other: AstNode): boolean;
35
+ /** Compares only this node's own scalar fields (kind/length already match). */
36
+ protected _localEquals(_other: this): boolean;
37
+ /**
38
+ * A copy of this node that adopts `id`. Reconciliation uses this to carry an
39
+ * old identity onto a node whose content changed. Nodes are immutable value
40
+ * holders, so a shallow prototype copy with `id` overridden is sound.
41
+ */
42
+ cloneWithId(id: number): this;
43
+ }
44
+
45
+ export declare interface AstVisualization {
46
+ $fileExtension: 'ast.w';
47
+ source: string;
48
+ root: AstVisualizationNode;
49
+ }
50
+
51
+ declare interface AstVisualizationNode {
52
+ label: string;
53
+ range: [start: number, endExclusive: number];
54
+ children?: AstVisualizationNode[];
55
+ }
56
+
57
+ /**
58
+ * Strategy for hosts that never deliver native clipboard events to the editor
59
+ * — most importantly VS Code webviews, whose preload calls `preventDefault()`
60
+ * on the Ctrl/Cmd+C/X/V keydowns, so no `copy`/`cut`/`paste` event is ever
61
+ * dispatched. Here the keystrokes are the only signal, so this strategy
62
+ * listens for them directly and drives the async {@link Clipboard} API
63
+ * (`navigator.clipboard`), which webviews are granted.
64
+ *
65
+ * Cut deletes synchronously once the text is captured; the clipboard write is
66
+ * fire-and-forget. Paste must wait for the async read before inserting.
67
+ */
68
+ export declare class AsyncClipboardStrategy implements IClipboardStrategy {
69
+ private readonly _clipboard;
70
+ constructor(_clipboard?: Clipboard);
71
+ connect(context: IClipboardContext): IDisposable;
72
+ }
73
+
74
+ export declare type BlockAstNode = HeadingAstNode | ParagraphAstNode | CodeBlockAstNode | MathBlockAstNode | ThematicBreakAstNode | BlockQuoteAstNode | ListAstNode | TableAstNode;
75
+
76
+ /**
77
+ * A block-level node. Every block may carry a {@link leadingTrivia} glue — the
78
+ * whitespace that precedes it on its own line (a nested list's indentation, the
79
+ * leading space of a continued paragraph). It is owned by the block it precedes
80
+ * (not the one it trails), so the view reveals it exactly when *this* block is
81
+ * active, and it tiles at the block's front: {@link children} prepends it to the
82
+ * block's own content while `content` stays the block's real payload.
83
+ */
84
+ declare abstract class BlockAstNodeBase extends AstNode {
85
+ abstract readonly leadingTrivia?: GlueAstNode;
86
+ /** This block with its leading trivia replaced — re-homes a leading glue onto it. */
87
+ abstract withLeadingTrivia(trivia: GlueAstNode | undefined): BlockAstNode;
88
+ /** Prepends {@link leadingTrivia}, if any, ahead of the block's own children. */
89
+ protected _withLeading(own: readonly AstNode[]): readonly AstNode[];
90
+ }
91
+
92
+ /**
93
+ * One block's place in the rendered document.
94
+ *
95
+ * `height` is in CSS pixels. It is either a real DOM measurement
96
+ * (`isMeasured: true`) or an estimate produced when the block is not
97
+ * currently mounted (`isMeasured: false`). Estimates exist so virtual
98
+ * rendering can size the scroll container without mounting every block.
99
+ *
100
+ * `visualLineMap` and `viewNode` are set only when the block is mounted
101
+ * and measured. Cursor positioning, selection painting and up/down
102
+ * navigation read through `visualLineMap`; the debug view walks
103
+ * `viewNode` to enumerate text leaves for per-character introspection.
104
+ * Unmeasured blocks have neither.
105
+ */
106
+ export declare interface BlockMeasurement {
107
+ readonly block: BlockAstNode;
108
+ readonly absoluteStart: number;
109
+ readonly height: number;
110
+ readonly isMeasured: boolean;
111
+ readonly visualLineMap: VisualLineMap | undefined;
112
+ readonly viewNode: ViewNode | undefined;
113
+ }
114
+
115
+ export declare class BlockQuoteAstNode extends BlockAstNodeBase {
116
+ readonly content: readonly (MarkerAstNode | BlockAstNode | GlueAstNode)[];
117
+ readonly leadingTrivia?: GlueAstNode | undefined;
118
+ readonly kind = "blockQuote";
119
+ constructor(content: readonly (MarkerAstNode | BlockAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
120
+ get children(): readonly AstNode[];
121
+ get blocks(): readonly BlockAstNode[];
122
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
123
+ withLeadingTrivia(trivia: GlueAstNode | undefined): BlockQuoteAstNode;
124
+ }
125
+
126
+ declare class BlockQuoteViewData {
127
+ readonly ast: BlockQuoteAstNode;
128
+ readonly content: readonly AnyViewData[];
129
+ readonly kind = "blockQuote";
130
+ constructor(ast: BlockQuoteAstNode, content: readonly AnyViewData[]);
131
+ }
132
+
133
+ declare type BlockViewData = HeadingViewData | ParagraphViewData | CodeBlockViewData | MathBlockViewData | ThematicBreakViewData | BlockQuoteViewData | ListViewData | TableViewData;
134
+
135
+ /**
136
+ * Base view node for everything the editor renders, generic over the
137
+ * {@link AnyViewData view-data} it renders so subclasses get a precisely-typed
138
+ * {@link data} (e.g. `BlockViewNode<HeadingViewData>`). Every view-data kind has
139
+ * a subclass whose constructor builds the node's DOM and, recursively,
140
+ * constructs its child view nodes — so *constructing a node is rendering it*.
141
+ * There is no separate render pass: the view tree is the result of construction,
142
+ * and {@link createViewNode} is the single entry point that turns a `ViewData`
143
+ * into a node (reusing a `previous` node untouched when it still matches).
144
+ *
145
+ * The name is historical — it is the base for inline and leaf nodes too — but
146
+ * top-level blocks are always instances of it, and {@link element}/{@link block}
147
+ * are the conveniences {@link EditorView} uses for those.
148
+ */
149
+ export declare class BlockViewNode<T extends AnyViewData = AnyViewData> extends ViewNode {
150
+ readonly data: T;
151
+ constructor(data: T, dom: globalThis.Node, children: readonly ViewNode[]);
152
+ get block(): BlockAstNode;
153
+ get element(): HTMLElement;
154
+ /**
155
+ * Whether this already-built node can stand in for `data` unchanged. The
156
+ * builder preserves view-data identity for any subtree whose ast and
157
+ * selection-derived flags are unchanged (see `buildDocumentViewData`), so a
158
+ * single identity check captures "nothing in my subtree changed" — and its
159
+ * whole subtree, and any session it owns, are kept as-is.
160
+ */
161
+ canReuse(data: AnyViewData): boolean;
162
+ /**
163
+ * Called by the view after this block is mounted and measured, with the
164
+ * block's rendered height in px. The default is a no-op; subclasses whose
165
+ * active/inactive renderings have different intrinsic heights (e.g. a math
166
+ * block) override this to remember a height to reserve across the toggle.
167
+ */
168
+ recordMeasuredHeight(_height: number): void;
169
+ }
170
+
171
+ export declare interface BlockViewOptions {
172
+ readonly renderCustomCodeBlock?: (language: string, content: string) => HTMLElement | undefined;
173
+ readonly onToggleCheckbox?: (item: ListItemAstNode, newChecked: boolean) => void;
174
+ /**
175
+ * Opens a link's URL. Called when the user activates a link: a plain click
176
+ * while the link's block is inactive (rendered), or a Ctrl/Cmd+click while it
177
+ * is active (source shown). Defaults to `window.open(url, '_blank')`.
178
+ */
179
+ readonly onOpenLink?: (url: string, event: MouseEvent) => void;
180
+ /**
181
+ * Colours fenced code blocks. When set, a code block's content is rendered
182
+ * as a sequence of token spans instead of one plain text node. This is the
183
+ * non-incremental path: the snapshot is read once at render time.
184
+ */
185
+ readonly syntaxHighlighter?: ISyntaxHighlighter;
186
+ /**
187
+ * Pluggable renderer for the *inactive* (rendered) form of a math node —
188
+ * both `$$…$$` blocks and inline `$…$`. When set and it returns a result,
189
+ * its {@link MathRendering.dom} replaces the default opaque `katex.render`
190
+ * output, and its {@link MathRendering.segments} let parts of the rendered
191
+ * math (e.g. individual identifier glyphs) map back to source ranges so the
192
+ * caret can land inside them. Returning `undefined` falls back to the
193
+ * default whole-node KaTeX leaf. The active (source) form is unaffected.
194
+ *
195
+ * This is the seam used to explore in-place editing of rendered math (see
196
+ * `katexEditableIdentifiers.ts`).
197
+ */
198
+ readonly renderMath?: (request: MathRenderRequest) => MathRendering | undefined;
199
+ }
200
+
201
+ export declare class CodeBlockAstNode extends BlockAstNodeBase {
202
+ readonly language: string;
203
+ readonly content: readonly (MarkerAstNode | GlueAstNode)[];
204
+ readonly leadingTrivia?: GlueAstNode | undefined;
205
+ readonly kind = "codeBlock";
206
+ private _previous?;
207
+ private _contentEdit?;
208
+ constructor(language: string, content: readonly (MarkerAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
209
+ get children(): readonly AstNode[];
210
+ get openFence(): MarkerAstNode | undefined;
211
+ get closeFence(): MarkerAstNode | undefined;
212
+ get code(): MarkerAstNode | undefined;
213
+ /** Relative start offset of the {@link code} marker within this block. */
214
+ get codeOffset(): number;
215
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
216
+ withLeadingTrivia(trivia: GlueAstNode | undefined): CodeBlockAstNode;
217
+ protected _localEquals(o: this): boolean;
218
+ /**
219
+ * A copy of this block carrying an incremental link to `previous`:
220
+ * `contentEdit` (in the block's *content* coordinates) turns `previous`'s
221
+ * content into this one. Uses a weak reference so the previous tree can be
222
+ * garbage-collected.
223
+ */
224
+ withCodeDiff(previous: CodeBlockAstNode, contentEdit: StringEdit): CodeBlockAstNode;
225
+ /**
226
+ * When this block was incrementally derived from `previous` (same
227
+ * fences/language, edit entirely within the content), returns the
228
+ * content-coordinate edit; otherwise `undefined`.
229
+ */
230
+ getDiff(previous: CodeBlockAstNode): CodeBlockDiff | undefined;
231
+ }
232
+
233
+ /**
234
+ * Describes how a {@link CodeBlockAstNode} was incrementally derived from a previous
235
+ * one: {@link stringEdit} (in the block's *content* coordinates) turns the
236
+ * previous content into this one.
237
+ */
238
+ declare interface CodeBlockDiff {
239
+ readonly stringEdit: StringEdit;
240
+ }
241
+
242
+ declare class CodeBlockViewData {
243
+ readonly ast: CodeBlockAstNode;
244
+ /** Active: render the fenced source; inactive: the (custom/highlighted) block. */
245
+ readonly showMarkup: boolean;
246
+ readonly content: readonly AnyViewData[];
247
+ readonly kind = "codeBlock";
248
+ constructor(ast: CodeBlockAstNode,
249
+ /** Active: render the fenced source; inactive: the (custom/highlighted) block. */
250
+ showMarkup: boolean, content: readonly AnyViewData[]);
251
+ }
252
+
253
+ /**
254
+ * A fenced code block. It owns its incremental
255
+ * {@link ISyntaxHighlighterDocument} session: constructing the node creates (or
256
+ * adopts from `previous`) the session, and disposing the node disposes it, so
257
+ * colouring stays incremental across edits — the session is reused and
258
+ * `update`d rather than rebuilt. A node at any depth owns a session; the only
259
+ * difference today is that the parser links `getDiff` for top-level code blocks
260
+ * only, so a nested block currently builds a fresh session on each rebuild.
261
+ */
262
+ export declare class CodeBlockViewNode extends BlockViewNode<CodeBlockViewData> {
263
+ private _session;
264
+ /**
265
+ * Subscription that re-tokenises the rendered `<code>` in place whenever the
266
+ * session advances its {@link ISyntaxHighlighterDocument.snapshot} *without*
267
+ * a source edit (an async grammar finishing, a live recolour). It is tied to
268
+ * this node's lifetime, but like {@link _session} it must be disposed
269
+ * manually: a node reused as `previous` for a rebuild is never `dispose`d
270
+ * (see {@link reconcileDomChildren}), so the rebuilding constructor disposes
271
+ * its predecessor's subscription explicitly.
272
+ */
273
+ private _snapshotSub;
274
+ constructor(data: CodeBlockViewData, options: BlockViewOptions | undefined, previous: ViewNode | undefined);
275
+ dispose(): void;
276
+ }
277
+
278
+ /**
279
+ * A {@link MonacoSyntaxHighlighter} preloaded with a handful of common Monarch
280
+ * grammars (plus the usual short aliases). Unknown languages fall back to an
281
+ * unstyled single token, so the highlighter is always safe to call.
282
+ *
283
+ * The Monarch runtime and grammar definitions are injected so this package
284
+ * depends on `monaco-editor` for types only.
285
+ */
286
+ export declare function createDefaultMonacoSyntaxHighlighter(monaco: IMonarchApi, grammars: IDefaultMonarchGrammars): MonacoSyntaxHighlighter;
287
+
288
+ export declare type CursorCommand = (ctx: CursorCommandContext) => SourceOffset;
289
+
290
+ export declare interface CursorCommandContext {
291
+ readonly text: string;
292
+ readonly selection: Selection_2;
293
+ readonly document: DocumentAstNode;
294
+ readonly activeBlock: BlockAstNode | undefined;
295
+ }
296
+
297
+ export declare const cursorDocumentEnd: CursorCommand;
298
+
299
+ export declare const cursorDocumentStart: CursorCommand;
300
+
301
+ export declare const cursorDown: VisualCursorCommand;
302
+
303
+ export declare const cursorLeft: CursorCommand;
304
+
305
+ export declare const cursorLineEnd: CursorCommand;
306
+
307
+ export declare const cursorLineStart: CursorCommand;
308
+
309
+ export declare const cursorMoveLeft: CursorCommand;
310
+
311
+ export declare interface CursorMoveResult {
312
+ readonly offset: SourceOffset;
313
+ readonly desiredColumn: number | undefined;
314
+ }
315
+
316
+ export declare const cursorMoveRight: CursorCommand;
317
+
318
+ export declare const cursorRight: CursorCommand;
319
+
320
+ export declare const cursorUp: VisualCursorCommand;
321
+
322
+ /**
323
+ * Owns the blinking cursor DOM element.
324
+ *
325
+ * The rendering pipeline is a single `derived` whose compute callback
326
+ * asks the {@link VisualLineMap} for the caret rect at the current
327
+ * offset, writes it to {@link element}, and returns a
328
+ * {@link CursorViewRendering} value as proof. An autorun keeps the
329
+ * derived subscribed.
330
+ */
331
+ export declare class CursorView extends Disposable {
332
+ private readonly _parent;
333
+ readonly element: HTMLElement;
334
+ readonly rendering: IObservable<CursorViewRendering>;
335
+ constructor(_parent: HTMLElement, options: CursorViewOptions);
336
+ }
337
+
338
+ export declare interface CursorViewOptions {
339
+ readonly offset: IObservable<SourceOffset | undefined>;
340
+ readonly visualLineMap: IObservable<VisualLineMap>;
341
+ /**
342
+ * When set, the caret is drawn over the transient empty paragraph instead
343
+ * of at {@link offset} — its rect (in client coordinates) comes straight
344
+ * from that synthetic element's geometry, since it has no visual-line-map
345
+ * entry. Takes priority over the normal offset-based placement.
346
+ */
347
+ readonly pendingCaretRect?: IObservable<Rect2D | undefined>;
348
+ }
349
+
350
+ export declare class CursorViewRendering {
351
+ readonly offset: SourceOffset;
352
+ readonly visible: boolean;
353
+ readonly rect: Rect2D;
354
+ constructor(offset: SourceOffset, visible: boolean, rect: Rect2D);
355
+ }
356
+
357
+ export declare const cursorWordLeft: CursorCommand;
358
+
359
+ export declare const cursorWordRight: CursorCommand;
360
+
361
+ export declare const deleteLeft: EditCommand;
362
+
363
+ export declare const deleteRight: EditCommand;
364
+
365
+ export declare const deleteWordLeft: EditCommand;
366
+
367
+ export declare const deleteWordRight: EditCommand;
368
+
369
+ export declare class DocumentAstNode extends AstNode {
370
+ readonly content: readonly (BlockAstNode | GlueAstNode)[];
371
+ readonly kind = "document";
372
+ constructor(content: readonly (BlockAstNode | GlueAstNode)[]);
373
+ get children(): readonly AstNode[];
374
+ get blocks(): readonly BlockAstNode[];
375
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
376
+ }
377
+
378
+ /** A mounted block: its view node paired with where it starts in the source. */
379
+ export declare interface DocumentBlock {
380
+ readonly node: BlockViewNode;
381
+ readonly absoluteStart: number;
382
+ }
383
+
384
+ /** A top-level block plus the document-level state the renderer applies to it. */
385
+ declare interface DocumentBlockViewData {
386
+ readonly ast: BlockAstNode;
387
+ readonly absoluteStart: number;
388
+ /** Whether the selection reaches this block (drives `md-block-active`). */
389
+ readonly isActive: boolean;
390
+ readonly view: BlockViewData;
391
+ }
392
+
393
+ /** A mounted document child: a block, a run of inter-block glue, or the
394
+ * transient empty paragraph (see {@link PendingParagraphViewData}). */
395
+ declare interface DocumentChildViewData {
396
+ readonly absoluteStart: number;
397
+ /** For a block: selection reaches it. For glue: always false (unowned, hidden). */
398
+ readonly isActive: boolean;
399
+ readonly view: BlockViewData | GlueViewData | PendingParagraphViewData;
400
+ readonly kind: 'block' | 'glue' | 'pendingParagraph';
401
+ }
402
+
403
+ /**
404
+ * The view-data root. Mirrors {@link DocumentAstNode}: {@link blocks} holds only
405
+ * its top-level blocks (each wrapped with where it starts and whether it is
406
+ * active), while {@link children} additionally interleaves the rendered
407
+ * document-level glue (the blank lines between blocks) in source order.
408
+ */
409
+ declare class DocumentViewData {
410
+ readonly ast: DocumentAstNode;
411
+ readonly blocks: readonly DocumentBlockViewData[];
412
+ /**
413
+ * Blocks and inter-block glue interleaved in source order — the actual
414
+ * mount sequence. {@link blocks} is the block-only projection used for
415
+ * measurement and selection.
416
+ */
417
+ readonly children: readonly DocumentChildViewData[];
418
+ readonly kind = "document";
419
+ constructor(ast: DocumentAstNode, blocks: readonly DocumentBlockViewData[],
420
+ /**
421
+ * Blocks and inter-block glue interleaved in source order — the actual
422
+ * mount sequence. {@link blocks} is the block-only projection used for
423
+ * measurement and selection.
424
+ */
425
+ children: readonly DocumentChildViewData[]);
426
+ }
427
+
428
+ /**
429
+ * Immutable view of the document's block sequence — the document-level
430
+ * analogue of {@link BlockViewNode}. Each {@link create} maps the
431
+ * {@link DocumentViewData} (the AST overlaid with selection-derived flags) to
432
+ * the block sequence, reusing the previous node's blocks by view-data identity,
433
+ * rebuilding only what changed, and patching its {@link contentDomNode}'s
434
+ * children to match.
435
+ *
436
+ * Like a {@link BlockViewNode}, it owns its DOM: the first `create` allocates
437
+ * the content element, and every later `create` keeps the previous node's
438
+ * element rather than making a new one. The element is therefore stable
439
+ * across rebuilds:
440
+ *
441
+ * create(viewData, …, old).contentDomNode === old.contentDomNode
442
+ *
443
+ * so a parent can mount it once and never re-parent it.
444
+ *
445
+ * Because it is rebuilt rather than mutated, {@link EditorView} can hold the
446
+ * whole block cache as one value and simply swap it each frame, instead of
447
+ * carrying a mutable entry array and the reconcile bookkeeping itself.
448
+ *
449
+ * It is itself a {@link ViewNode} (the root of the view-node tree), so DOM ↔
450
+ * source mapping such as {@link ViewNode.resolveSource} is inherited: a hit on
451
+ * any descendant lifts up the parent chain to here, yielding an absolute
452
+ * document offset.
453
+ */
454
+ export declare class DocumentViewNode extends ViewNode {
455
+ readonly blocks: readonly DocumentBlock[];
456
+ /** The transient empty-paragraph element, when one is armed. */
457
+ readonly pendingElement?: HTMLElement | undefined;
458
+ static create(viewData: DocumentViewData, options: BlockViewOptions | undefined, previous: DocumentViewNode | undefined): DocumentViewNode;
459
+ private constructor();
460
+ /** The stable content element this document mounts its children into. */
461
+ get contentDomNode(): HTMLElement;
462
+ }
463
+
464
+ /**
465
+ * A DOM node paired with a caret offset inside it. The node is an arbitrary
466
+ * {@link globalThis.Node} (a Text node for a caret inside text, an Element for
467
+ * a hit on element-only content), and `offset` is the caret offset within it.
468
+ */
469
+ export declare interface DomPosition {
470
+ readonly node: globalThis.Node;
471
+ readonly offset: number;
472
+ }
473
+
474
+ export declare type EditCommand = (ctx: CursorCommandContext) => {
475
+ readonly edit: StringEdit;
476
+ readonly selection: Selection_2;
477
+ } | undefined;
478
+
479
+ /**
480
+ * Translates raw browser input (mouse, keyboard, EditContext) into model
481
+ * mutations. Knows about DOM event types but never reads/writes the DOM
482
+ * directly — it asks the {@link EditorView} to broker DOM↔source-offset
483
+ * conversions so the model stays free of view types.
484
+ *
485
+ * Owns the only non-derivable controller state:
486
+ * - `_desiredColumn` — sticky column for up/down navigation
487
+ */
488
+ export declare class EditorController extends Disposable {
489
+ private readonly _model;
490
+ private readonly _view;
491
+ private _desiredColumn;
492
+ constructor(_model: EditorModel, _view: EditorView, options?: EditorControllerOptions);
493
+ private readonly _handleTextUpdate;
494
+ private readonly _handleMouseDown;
495
+ private _makeCursorContext;
496
+ private _makeVisualCursorContext;
497
+ private _executeCursorCommand;
498
+ private _executeEditCommand;
499
+ private _executeVisualCursorCommand;
500
+ /** Move the cursor down one visual line (Arrow Down). */
501
+ cursorDown(extend?: boolean): void;
502
+ /** Move the cursor up one visual line (Arrow Up). */
503
+ cursorUp(extend?: boolean): void;
504
+ private _selectedText;
505
+ private readonly _updateModifierState;
506
+ private readonly _clearModifierState;
507
+ private readonly _handleKeyDown;
508
+ /**
509
+ * Context-aware Enter: splits / line-breaks via {@link insertSmartEnter}, or
510
+ * arms a transient empty paragraph when at the end of a paragraph.
511
+ */
512
+ private _smartEnter;
513
+ }
514
+
515
+ /** Options for an {@link EditorController}. */
516
+ export declare interface EditorControllerOptions {
517
+ /**
518
+ * How copy/cut/paste is handled. Defaults to {@link NativeClipboardStrategy},
519
+ * which reads the browser's native clipboard events — pass a different
520
+ * strategy (e.g. `AsyncClipboardStrategy`) in hosts that swallow them.
521
+ */
522
+ readonly clipboardStrategy?: IClipboardStrategy;
523
+ }
524
+
525
+ export declare class EditorModel {
526
+ private readonly _parser;
527
+ /**
528
+ * The most recent edit applied to {@link sourceText}, used by
529
+ * {@link document} to let the parser link incrementally edited code
530
+ * blocks. Only trusted when it exactly bridges the previous and current
531
+ * source text (see {@link document}).
532
+ */
533
+ private _pendingEdit;
534
+ readonly sourceText: ISettableObservable<StringValue, void>;
535
+ /**
536
+ * The current selection, or `undefined` when the editor has no caret
537
+ * (e.g. an inactive/unfocused rendering).
538
+ */
539
+ readonly selection: ISettableObservable<Selection_2 | undefined, void>;
540
+ /**
541
+ * Whether a Ctrl/Cmd modifier is currently held. Set by the controller from
542
+ * live keyboard state; the view reads it to show the link-open affordance
543
+ * (underline + pointer cursor) only while a Ctrl/Cmd+click would open a link
544
+ * whose block is active.
545
+ */
546
+ readonly ctrlOrMetaDown: ISettableObservable<boolean, void>;
547
+ /**
548
+ * Gutter markers (source-control style change indicators) painted in the
549
+ * left gutter. Each entry maps a source {@link OffsetRange} to a change kind
550
+ * — see {@link GutterMarker}. Purely decorative: markers never affect the
551
+ * parsed {@link document}, selection, or layout. Empty by default.
552
+ */
553
+ readonly gutterMarkers: ISettableObservable<readonly GutterMarker[], void>;
554
+ /**
555
+ * Forces the rendered active-block set. `undefined` (the default)
556
+ * derives the set from the current selection range (see
557
+ * {@link activeBlocks}). The sentinel {@link NO_ACTIVE_BLOCKS} forces
558
+ * "no active block" — useful in fixtures that always want the
559
+ * collapsed/inactive rendering.
560
+ */
561
+ readonly activeBlocksOverride: ISettableObservable<readonly BlockAstNode[] | typeof NO_ACTIVE_BLOCKS | undefined, void>;
562
+ /**
563
+ * The transient empty-paragraph editing state, or `undefined` when none is
564
+ * armed. See {@link PendingParagraph}. This is *not* document data — it is
565
+ * cleared by any source edit and lives only between the Enter that armed it
566
+ * and the next keystroke.
567
+ */
568
+ readonly pendingParagraph: ISettableObservable<PendingParagraph | undefined, void>;
569
+ readonly cursorOffset: IObservableWithChange<number | undefined, void>;
570
+ /**
571
+ * The parsed document. Threads the previous document into the parser so
572
+ * unchanged blocks keep their object identity across reparses (see
573
+ * {@link MarkdownParser.parse}). Writing `previous` inside the compute is
574
+ * a safe optimization: `derived` only recomputes when `sourceText`
575
+ * changes, and the result is structurally identical to a full reparse.
576
+ */
577
+ readonly document: IObservableWithChange<DocumentAstNode, void>;
578
+ /**
579
+ * Block that contains the cursor (selection's active end). Used by
580
+ * cursor navigation to know which block's marker ranges count as
581
+ * visible. Unaffected by {@link activeBlocksOverride} because
582
+ * navigation is independent of rendering.
583
+ */
584
+ readonly activeBlock: IObservableWithChange<BlockAstNode | undefined, void>;
585
+ /**
586
+ * All blocks whose source range intersects the current selection.
587
+ * The rendering side uses this to decide which blocks render in
588
+ * their expanded (markers-visible) form. When the selection is
589
+ * collapsed this is a one-element set holding {@link activeBlock}.
590
+ */
591
+ readonly activeBlocks: IObservableWithChange<Set<BlockAstNode>, void>;
592
+ /**
593
+ * Arm a {@link PendingParagraph} at the given gap, minting a fresh synthetic
594
+ * AST node for it, and park the caret at the gap start. No source edit is
595
+ * applied — the blank line exists only in the view until it is materialized.
596
+ */
597
+ armPendingParagraph(req: {
598
+ anchorBlock: BlockAstNode;
599
+ replaceRange: OffsetRange;
600
+ atEof: boolean;
601
+ }): void;
602
+ /** Discard the pending paragraph (if any) without touching the source. */
603
+ cancelPendingParagraph(): void;
604
+ /**
605
+ * Turn the pending paragraph into real source: rewrite its gap so the typed
606
+ * `text` becomes its own paragraph, separated from its neighbours by blank
607
+ * lines, and place the caret after the inserted text.
608
+ */
609
+ materializePendingParagraph(text: string): void;
610
+ applyEdit(edit: StringEdit): void;
611
+ applyEditForSelection(edit: StringEdit): void;
612
+ }
613
+
614
+ /**
615
+ * Pure-render view of an {@link EditorModel}.
616
+ *
617
+ * Invariant (the whole point of this file):
618
+ *
619
+ * view(model + Δ) = view(model) + Δ
620
+ *
621
+ * The DOM the view produces is a function of the model. The only state the
622
+ * view holds is *DOM management*: the cached `BlockViewNode` instances and the
623
+ * `EditContext`. Anything that influences correctness but is not derivable
624
+ * from the model lives elsewhere:
625
+ *
626
+ * - measured heights and per-block visual line maps → {@link MeasuredLayoutModel}
627
+ * - desired column, drag-time freeze → EditorController
628
+ *
629
+ * The view does not own a controller — callers construct an
630
+ * `EditorController` separately and pass it the view, so input handling is
631
+ * explicit and the view stays a pure renderer.
632
+ *
633
+ * The view writes into the measured-layout model as a side effect of
634
+ * rendering. It never reads its own measurements during rendering, so
635
+ * there is no feedback loop.
636
+ */
637
+ export declare class EditorView extends Disposable {
638
+ private readonly _model;
639
+ private readonly _options?;
640
+ readonly element: HTMLElement;
641
+ readonly editContext: EditContext;
642
+ readonly measuredLayout: MeasuredLayoutModel;
643
+ /**
644
+ * Inner container that holds the rendered document and the cursor/selection
645
+ * overlays. The outer {@link element} spans the full width; this container
646
+ * is what limited-width mode caps and centers, so the overlays (which anchor
647
+ * to their parent's box) stay aligned with the content.
648
+ */
649
+ private readonly _contentContainer;
650
+ private readonly _cursorView;
651
+ private readonly _selectionView;
652
+ private readonly _gutterMarkersView;
653
+ /**
654
+ * The mounted block sequence, in source order. Rebuilt (not mutated) each
655
+ * frame by {@link DocumentViewNode.create}; the view just swaps one
656
+ * immutable node for the next. Never used for source-of-truth lookups
657
+ * (those go through the measured-layout model).
658
+ */
659
+ private readonly _document;
660
+ /** The current view-node tree (AST overlaid with rendered DOM), for debugging. */
661
+ get documentViewNode(): IObservable<DocumentViewNode | undefined>;
662
+ /**
663
+ * Last frame's view-data overlay, threaded back into
664
+ * {@link buildDocumentViewData} so any subtree whose ast and selection flags
665
+ * are unchanged keeps its view-data object — which lets the renderer reuse
666
+ * its DOM by identity.
667
+ */
668
+ private _previousViewData;
669
+ /** The current view-data tree (AST overlaid with selection flags), for debugging. */
670
+ private readonly _viewData;
671
+ get viewData(): IObservable<DocumentViewData | undefined>;
672
+ /**
673
+ * Caret rect (client coords) for the transient empty paragraph, or
674
+ * `undefined` when none is armed. Set each frame from the synthetic
675
+ * paragraph element's geometry and fed to the {@link CursorView}, which has
676
+ * no visual-line-map entry to place the caret from otherwise.
677
+ */
678
+ private readonly _pendingCaretRect;
679
+ /**
680
+ * The block cache projected for views (selection painting) that need to
681
+ * react to mount/unmount. Derived from {@link _document}, so it stays in
682
+ * lock-step without any manual bookkeeping.
683
+ */
684
+ private readonly _selectionBlocksObs;
685
+ constructor(_model: EditorModel, _options?: EditorViewOptions | undefined);
686
+ /**
687
+ * Mirrors the model's live Ctrl/Cmd state onto the editor root as
688
+ * `.md-mod-down` so CSS can show the link-open underline and pointer cursor
689
+ * only while a click would actually open the link: an inactive link opens on
690
+ * a plain click, but an active link only opens with the modifier held.
691
+ */
692
+ private _setupModifierTracking;
693
+ focus(): void;
694
+ /**
695
+ * Client coordinates → absolute source offset (any block). Used during
696
+ * drag to keep extending the selection even when the pointer leaves the
697
+ * original block.
698
+ */
699
+ resolveOffsetFromPoint(point: Point2D): SourceOffset | undefined;
700
+ /**
701
+ * Whether a client point falls on the rendered document content, as
702
+ * opposed to the surrounding editor padding (the green area). Uses DOM
703
+ * containment rather than the content node's bounding box so that markers
704
+ * which overflow into the padding (e.g. a heading's `##`, which renders in
705
+ * the left margin) still count as content. Overlays (cursor, selection)
706
+ * have `pointer-events: none`, so the hit-test sees through them.
707
+ */
708
+ isPointInContent(point: Point2D): boolean;
709
+ private readonly _renderAutorun;
710
+ /** Current mounted blocks, or empty before the first render. */
711
+ private get _blocks();
712
+ /**
713
+ * Measure each mounted block's rect and per-block visual line map, then
714
+ * publish the result into the {@link MeasuredLayoutModel}. The model
715
+ * is not read here, so there is no feedback loop into the render autorun.
716
+ */
717
+ private _publishMeasurements;
718
+ }
719
+
720
+ export declare interface EditorViewOptions extends BlockViewOptions {
721
+ /**
722
+ * Extra class names added to the editor root element, e.g. a theme class
723
+ * such as `'md-theme-default'` or `'github-markdown-theme'`. Theme styles
724
+ * are scoped under these classes, so the editor is unstyled (base chrome
725
+ * only) unless a theme class is supplied.
726
+ */
727
+ readonly classNames?: readonly string[];
728
+ /**
729
+ * Controls "limited width mode". The observable yields the maximum content
730
+ * width in pixels, or `undefined` to let the content fill the available
731
+ * width. When the option is omitted, the width is capped at
732
+ * {@link DEFAULT_LIMITED_WIDTH}px (limited mode is on by default).
733
+ *
734
+ * The cap and centering apply to an inner content container; the editor
735
+ * root ({@link element}) always spans the full available width.
736
+ */
737
+ readonly limitedWidth?: IObservable<number | undefined>;
738
+ }
739
+
740
+ export declare class EmphasisAstNode extends AstNode {
741
+ readonly openMarker: MarkerAstNode;
742
+ readonly content: readonly (InlineAstNode | GlueAstNode)[];
743
+ readonly closeMarker: MarkerAstNode;
744
+ readonly kind = "emphasis";
745
+ constructor(openMarker: MarkerAstNode, content: readonly (InlineAstNode | GlueAstNode)[], closeMarker: MarkerAstNode);
746
+ get children(): readonly AstNode[];
747
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
748
+ }
749
+
750
+ declare class EmphasisViewData {
751
+ readonly ast: EmphasisAstNode;
752
+ readonly content: readonly AnyViewData[];
753
+ readonly kind = "emphasis";
754
+ constructor(ast: EmphasisAstNode, content: readonly AnyViewData[]);
755
+ }
756
+
757
+ /**
758
+ * Source offset (relative to `root`) of the node with `target`'s id, or
759
+ * `undefined` when it is not in the tree. Ids are stable across edits, so this
760
+ * locates a node even after reconciliation has rebuilt the tree around it.
761
+ */
762
+ export declare function findNodeOffsetById(root: AstNode, target: AstNode): number | undefined;
763
+
764
+ export declare function findWordAt(text: string, offset: number): {
765
+ start: number;
766
+ end: number;
767
+ };
768
+
769
+ export declare function findWordBoundaryLeft(text: string, offset: number): number;
770
+
771
+ export declare function findWordBoundaryRight(text: string, offset: number): number;
772
+
773
+ export declare function getAnnotatedSource(node: AstNode, source: string, offset?: number): string;
774
+
775
+ /** Non-semantic syntactic glue: whitespace, padding, table pipes. */
776
+ export declare class GlueAstNode extends LeafAstNode {
777
+ readonly content: string;
778
+ readonly glueKind?: string | undefined;
779
+ readonly kind = "glue";
780
+ constructor(content: string, glueKind?: string | undefined);
781
+ protected _localEquals(o: this): boolean;
782
+ }
783
+
784
+ declare class GlueViewData {
785
+ readonly ast: GlueAstNode;
786
+ readonly visible: boolean;
787
+ /**
788
+ * Whether a source newline in this glue gets a visible `↵`. True only in
789
+ * inline flow, where the newline collapses to a space and the `↵` reveals
790
+ * the line ending hiding there; between block-level siblings (list items,
791
+ * block children) the break is already visible, so no `↵` is drawn.
792
+ */
793
+ readonly decorateNewline: boolean;
794
+ readonly kind = "glue";
795
+ constructor(ast: GlueAstNode, visible: boolean,
796
+ /**
797
+ * Whether a source newline in this glue gets a visible `↵`. True only in
798
+ * inline flow, where the newline collapses to a space and the `↵` reveals
799
+ * the line ending hiding there; between block-level siblings (list items,
800
+ * block children) the break is already visible, so no `↵` is drawn.
801
+ */
802
+ decorateNewline: boolean);
803
+ }
804
+
805
+ /**
806
+ * A single gutter marker: a source {@link OffsetRange} tagged with a
807
+ * {@link GutterMarkerType}. The view resolves the range to the visual lines it
808
+ * covers and paints a bar (or, for `deleted`, a wedge at the range position) in
809
+ * the left gutter.
810
+ *
811
+ * A `deleted` marker is normally an empty range (`range.isEmpty`) sitting at the
812
+ * boundary where the removed text used to be — there is nothing left to span,
813
+ * so it is drawn as a caret between lines rather than a bar.
814
+ */
815
+ export declare interface GutterMarker {
816
+ readonly range: OffsetRange;
817
+ readonly type: GutterMarkerType;
818
+ }
819
+
820
+ /**
821
+ * The kind of change a gutter marker represents, mirroring the three states a
822
+ * source-control diff distinguishes (the git change markers in the editor
823
+ * gutter): a freshly inserted region, an edited region, and a point where
824
+ * content was removed.
825
+ */
826
+ export declare type GutterMarkerType = 'added' | 'modified' | 'deleted';
827
+
828
+ export declare class HeadingAstNode extends BlockAstNodeBase {
829
+ readonly level: 1 | 2 | 3 | 4 | 5 | 6;
830
+ readonly marker: MarkerAstNode;
831
+ readonly content: readonly (InlineAstNode | GlueAstNode)[];
832
+ readonly leadingTrivia?: GlueAstNode | undefined;
833
+ readonly kind = "heading";
834
+ constructor(level: 1 | 2 | 3 | 4 | 5 | 6, marker: MarkerAstNode, content: readonly (InlineAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
835
+ get children(): readonly AstNode[];
836
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
837
+ withLeadingTrivia(trivia: GlueAstNode | undefined): HeadingAstNode;
838
+ protected _localEquals(o: this): boolean;
839
+ }
840
+
841
+ declare class HeadingViewData {
842
+ readonly ast: HeadingAstNode;
843
+ readonly content: readonly AnyViewData[];
844
+ readonly kind = "heading";
845
+ constructor(ast: HeadingAstNode, content: readonly AnyViewData[]);
846
+ }
847
+
848
+ /**
849
+ * The editor operations a clipboard strategy drives. The strategy never
850
+ * touches the model or the DOM directly — it asks through this seam, so the
851
+ * same strategy works regardless of how the editor is wired up.
852
+ */
853
+ export declare interface IClipboardContext {
854
+ /** The element that owns focus and receives clipboard/keyboard events. */
855
+ readonly element: HTMLElement;
856
+ /** The selected source text, or `undefined` when the selection is empty. */
857
+ getSelectedText(): string | undefined;
858
+ /** Delete the current selection (the cut half of cut). */
859
+ deleteSelection(): void;
860
+ /** Insert text at the caret, replacing any selection (the paste action). */
861
+ insertText(text: string): void;
862
+ }
863
+
864
+ /**
865
+ * How copy/cut/paste intent reaches the editor. Host environments deliver it
866
+ * differently, so the controller owns no clipboard logic itself — it
867
+ * {@link connect}s a strategy and lets it install whatever listeners it needs.
868
+ *
869
+ * Two implementations ship:
870
+ * - {@link NativeClipboardStrategy} (default) reads the browser's native
871
+ * `copy`/`cut`/`paste` events and their synchronous `clipboardData`.
872
+ * - {@link AsyncClipboardStrategy} drives the async `navigator.clipboard` API
873
+ * from Ctrl/Cmd+C/X/V keystrokes, for hosts (e.g. VS Code webviews) that
874
+ * swallow the native clipboard events before they reach the editor.
875
+ */
876
+ export declare interface IClipboardStrategy {
877
+ /**
878
+ * Wire up clipboard handling against `context`. The returned disposable
879
+ * tears down every listener the strategy installed.
880
+ */
881
+ connect(context: IClipboardContext): IDisposable;
882
+ }
883
+
884
+ /** The Monarch language definitions the default highlighter wires up. */
885
+ export declare interface IDefaultMonarchGrammars {
886
+ typescript: unknown;
887
+ javascript: unknown;
888
+ css: unknown;
889
+ html: unknown;
890
+ python: unknown;
891
+ rust: unknown;
892
+ shell: unknown;
893
+ }
894
+
895
+ export declare class ImageAstNode extends AstNode {
896
+ readonly alt: string;
897
+ readonly url: string;
898
+ readonly content: readonly (MarkerAstNode | GlueAstNode)[];
899
+ readonly kind = "image";
900
+ constructor(alt: string, url: string, content: readonly (MarkerAstNode | GlueAstNode)[]);
901
+ get children(): readonly AstNode[];
902
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
903
+ protected _localEquals(o: this): boolean;
904
+ }
905
+
906
+ declare class ImageViewData {
907
+ readonly ast: ImageAstNode;
908
+ /** Active: render the `![alt](url)` source; inactive: the `<img>`. */
909
+ readonly showMarkup: boolean;
910
+ readonly content: readonly AnyViewData[];
911
+ readonly kind = "image";
912
+ constructor(ast: ImageAstNode,
913
+ /** Active: render the `![alt](url)` source; inactive: the `<img>`. */
914
+ showMarkup: boolean, content: readonly AnyViewData[]);
915
+ }
916
+
917
+ /**
918
+ * The slice of monaco's Monarch internals the highlighter needs at runtime.
919
+ *
920
+ * `monaco-editor` is only a *type* dependency of this package; the caller (who
921
+ * owns a real monaco runtime) passes these in, keeping monaco out of the bundle.
922
+ */
923
+ export declare interface IMonarchApi {
924
+ /** Compiles a Monarch language definition into the internal lexer form. */
925
+ compile(languageId: string, json: unknown): unknown;
926
+ MonarchTokenizer: new (languageService: unknown, standaloneThemeService: unknown, languageId: string, lexer: unknown, configurationService: unknown) => MonarchTokenizer;
927
+ }
928
+
929
+ export declare type InlineAstNode = TextAstNode | StrongAstNode | EmphasisAstNode | StrikethroughAstNode | InlineCodeAstNode | InlineMathAstNode | LinkAstNode | ImageAstNode;
930
+
931
+ export declare class InlineCodeAstNode extends AstNode {
932
+ readonly content: readonly (MarkerAstNode | GlueAstNode)[];
933
+ readonly kind = "inlineCode";
934
+ constructor(content: readonly (MarkerAstNode | GlueAstNode)[]);
935
+ get children(): readonly AstNode[];
936
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
937
+ }
938
+
939
+ declare class InlineCodeViewData {
940
+ readonly ast: InlineCodeAstNode;
941
+ readonly content: readonly AnyViewData[];
942
+ readonly kind = "inlineCode";
943
+ constructor(ast: InlineCodeAstNode, content: readonly AnyViewData[]);
944
+ }
945
+
946
+ export declare class InlineMathAstNode extends AstNode {
947
+ readonly content: readonly (MarkerAstNode | GlueAstNode)[];
948
+ readonly kind = "inlineMath";
949
+ constructor(content: readonly (MarkerAstNode | GlueAstNode)[]);
950
+ get children(): readonly AstNode[];
951
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
952
+ }
953
+
954
+ declare class InlineMathViewData {
955
+ readonly ast: InlineMathAstNode;
956
+ /** Active: render the `$…$` source; inactive: the KaTeX output. */
957
+ readonly showMarkup: boolean;
958
+ readonly content: readonly AnyViewData[];
959
+ readonly kind = "inlineMath";
960
+ constructor(ast: InlineMathAstNode,
961
+ /** Active: render the `$…$` source; inactive: the KaTeX output. */
962
+ showMarkup: boolean, content: readonly AnyViewData[]);
963
+ }
964
+
965
+ declare type InlineViewData = TextViewData | StrongViewData | EmphasisViewData | StrikethroughViewData | InlineCodeViewData | InlineMathViewData | LinkViewData | ImageViewData;
966
+
967
+ /**
968
+ * A Markdown hard line break: a `\n` whose preceding line ends with two spaces.
969
+ * Any spaces already trailing the insertion point count toward the two, so the
970
+ * line never accumulates more than the two needed to form the break.
971
+ */
972
+ export declare const insertHardLineBreak: EditCommand;
973
+
974
+ export declare const insertLineBreak: EditCommand;
975
+
976
+ export declare const insertParagraph: EditCommand;
977
+
978
+ /**
979
+ * Context-aware Enter. The behaviour is chosen from the active block:
980
+ * - paragraph / heading / thematic break — the "rich text" thing: at the
981
+ * block's end arm a transient empty paragraph (see {@link SmartEnterResult});
982
+ * elsewhere split into two paragraphs (`\n\n`).
983
+ * - code block — insert a newline that preserves the current line's indentation,
984
+ * staying inside the fence.
985
+ * - block quote — continue the quote (`\n> `); an empty quote line exits it.
986
+ * - list — continue the list with the next marker (incrementing ordered
987
+ * numbers, re-emitting task checkboxes); an empty item exits the list.
988
+ * A non-collapsed selection, or any other block, falls back to a plain soft line
989
+ * break, preserving today's behaviour.
990
+ */
991
+ export declare const insertSmartEnter: (ctx: CursorCommandContext) => SmartEnterResult;
992
+
993
+ export declare function insertText(text: string): EditCommand;
994
+
995
+ /**
996
+ * An immutable view of one document's tokens at a point in time. It may be a
997
+ * thin view over the highlighter's mutable state: once the underlying document
998
+ * advances, calling a stale snapshot is allowed to throw.
999
+ *
1000
+ * Token stability: across snapshots `S1 -> S2` (with the change delivered as a
1001
+ * {@link LengthEdit}), `getTokens(r)` returns the same tokens for any range `r`
1002
+ * not touched by that edit. Only ranges the edit reports as changed may recolour.
1003
+ */
1004
+ export declare interface ISyntaxHighlightedSnapshot {
1005
+ /**
1006
+ * Tokens covering a region that contains `queryRange`. Tokens are never
1007
+ * split: the returned {@link SnapshotTokens.range} is `queryRange` *grown*
1008
+ * to whole-token boundaries, so a token that straddles an end of
1009
+ * `queryRange` is returned in full. The result is dense over that grown
1010
+ * range — `sum(token.length) === range.length` — which is why the range is
1011
+ * returned alongside the tokens.
1012
+ */
1013
+ getTokens(queryRange: OffsetRange): SnapshotTokens;
1014
+ }
1015
+
1016
+ export declare interface ISyntaxHighlighter {
1017
+ create(language: string, initialText: string): ISyntaxHighlighterDocument;
1018
+ }
1019
+
1020
+ export declare interface ISyntaxHighlighterDocument extends IDisposable {
1021
+ /**
1022
+ * Apply a source edit. The {@link snapshot} updates synchronously within
1023
+ * `tx`, and the change it carries is the *minimal* {@link LengthEdit} that
1024
+ * actually re-coloured — not the whole document.
1025
+ */
1026
+ update(edit: StringEdit, tx: ITransaction): void;
1027
+ /**
1028
+ * The current snapshot. Its change reason is a {@link LengthEdit} mapping
1029
+ * the previous snapshot's offsets to this one's wherever tokens changed.
1030
+ */
1031
+ readonly snapshot: IObservableWithChange<ISyntaxHighlightedSnapshot, LengthEdit>;
1032
+ }
1033
+
1034
+ declare abstract class LeafAstNode extends AstNode {
1035
+ abstract readonly content: string;
1036
+ get children(): readonly AstNode[];
1037
+ get length(): number;
1038
+ mapChildren(): AstNode;
1039
+ }
1040
+
1041
+ /**
1042
+ * A set of disjoint, sorted {@link LengthReplacement}s — the length-only
1043
+ * counterpart of {@link StringEdit}. Used as the change reason of an
1044
+ * observable so observers learn which offset ranges of the previous value map
1045
+ * to which ranges of the new value (and thus what to invalidate) without
1046
+ * carrying the new content itself.
1047
+ */
1048
+ export declare class LengthEdit {
1049
+ static readonly empty: LengthEdit;
1050
+ static single(replacement: LengthReplacement): LengthEdit;
1051
+ static replace(replaceRange: OffsetRange, newLength: number): LengthEdit;
1052
+ readonly replacements: readonly LengthReplacement[];
1053
+ constructor(replacements: readonly LengthReplacement[]);
1054
+ get isEmpty(): boolean;
1055
+ equals(other: LengthEdit): boolean;
1056
+ toString(): string;
1057
+ }
1058
+
1059
+ /**
1060
+ * A single "the text in `replaceRange` now spans `newLength` characters"
1061
+ * statement. Unlike {@link StringReplacement} it carries no text — it only
1062
+ * describes *where* and *by how much* something changed, not *what to*.
1063
+ *
1064
+ * For syntax highlighting it means: the characters that used to occupy
1065
+ * `replaceRange` are replaced by `newLength` characters whose tokens may now
1066
+ * be coloured differently. A same-length replacement (`replaceRange.length ===
1067
+ * newLength`) therefore means "these characters kept their positions but got
1068
+ * re-coloured".
1069
+ */
1070
+ export declare class LengthReplacement {
1071
+ readonly replaceRange: OffsetRange;
1072
+ readonly newLength: number;
1073
+ static replace(replaceRange: OffsetRange, newLength: number): LengthReplacement;
1074
+ constructor(replaceRange: OffsetRange, newLength: number);
1075
+ get lengthDelta(): number;
1076
+ equals(other: LengthReplacement): boolean;
1077
+ toString(): string;
1078
+ }
1079
+
1080
+ export declare class LinkAstNode extends AstNode {
1081
+ readonly url: string;
1082
+ readonly content: readonly (MarkerAstNode | InlineAstNode | GlueAstNode)[];
1083
+ readonly kind = "link";
1084
+ constructor(url: string, content: readonly (MarkerAstNode | InlineAstNode | GlueAstNode)[]);
1085
+ get children(): readonly AstNode[];
1086
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
1087
+ protected _localEquals(o: this): boolean;
1088
+ }
1089
+
1090
+ declare class LinkViewData {
1091
+ readonly ast: LinkAstNode;
1092
+ readonly content: readonly AnyViewData[];
1093
+ readonly kind = "link";
1094
+ constructor(ast: LinkAstNode, content: readonly AnyViewData[]);
1095
+ }
1096
+
1097
+ export declare class ListAstNode extends BlockAstNodeBase {
1098
+ readonly ordered: boolean;
1099
+ readonly content: readonly (ListItemAstNode | GlueAstNode)[];
1100
+ readonly leadingTrivia?: GlueAstNode | undefined;
1101
+ readonly kind = "list";
1102
+ constructor(ordered: boolean, content: readonly (ListItemAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
1103
+ get children(): readonly AstNode[];
1104
+ get items(): readonly ListItemAstNode[];
1105
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
1106
+ withLeadingTrivia(trivia: GlueAstNode | undefined): ListAstNode;
1107
+ protected _localEquals(o: this): boolean;
1108
+ }
1109
+
1110
+ export declare class ListItemAstNode extends AstNode {
1111
+ readonly marker: MarkerAstNode;
1112
+ readonly content: readonly (BlockAstNode | GlueAstNode)[];
1113
+ readonly checked?: boolean | undefined;
1114
+ readonly leadingTrivia?: GlueAstNode | undefined;
1115
+ readonly kind = "listItem";
1116
+ constructor(marker: MarkerAstNode, content: readonly (BlockAstNode | GlueAstNode)[], checked?: boolean | undefined, leadingTrivia?: GlueAstNode | undefined);
1117
+ get children(): readonly AstNode[];
1118
+ get blocks(): readonly BlockAstNode[];
1119
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
1120
+ withLeadingTrivia(trivia: GlueAstNode | undefined): ListItemAstNode;
1121
+ protected _localEquals(o: this): boolean;
1122
+ }
1123
+
1124
+ declare class ListItemViewData {
1125
+ readonly ast: ListItemAstNode;
1126
+ /** Whether the selection reaches this item (reveals its markers). */
1127
+ readonly isActive: boolean;
1128
+ readonly content: readonly AnyViewData[];
1129
+ /** 1-based list nesting depth, used to size the indentation gutter. */
1130
+ readonly level: number;
1131
+ readonly kind = "listItem";
1132
+ constructor(ast: ListItemAstNode,
1133
+ /** Whether the selection reaches this item (reveals its markers). */
1134
+ isActive: boolean, content: readonly AnyViewData[],
1135
+ /** 1-based list nesting depth, used to size the indentation gutter. */
1136
+ level: number);
1137
+ }
1138
+
1139
+ declare class ListViewData {
1140
+ readonly ast: ListAstNode;
1141
+ readonly content: readonly AnyViewData[];
1142
+ readonly kind = "list";
1143
+ constructor(ast: ListAstNode, content: readonly AnyViewData[]);
1144
+ }
1145
+
1146
+ /**
1147
+ * Parses markdown into a {@link DocumentAstNode}.
1148
+ *
1149
+ * When given the `previous` document and the `edit` that produced the new
1150
+ * text, it reuses unchanged subtrees and carries node identities across the
1151
+ * edit (see {@link parseIncremental}), so views can diff cheaply and code
1152
+ * blocks keep their incremental highlighting sessions.
1153
+ */
1154
+ export declare class MarkdownParser {
1155
+ parse(text: StringValue, previous?: DocumentAstNode, edit?: StringEdit): DocumentAstNode;
1156
+ }
1157
+
1158
+ /** A semantic syntax marker (heading `#`, fences, brackets, list bullet, …). */
1159
+ export declare class MarkerAstNode extends LeafAstNode {
1160
+ readonly markerKind: string;
1161
+ readonly content: string;
1162
+ readonly kind = "marker";
1163
+ constructor(markerKind: string, content: string);
1164
+ protected _localEquals(o: this): boolean;
1165
+ }
1166
+
1167
+ declare class MarkerViewData {
1168
+ readonly ast: MarkerAstNode;
1169
+ readonly visible: boolean;
1170
+ readonly kind = "marker";
1171
+ constructor(ast: MarkerAstNode, visible: boolean);
1172
+ }
1173
+
1174
+ export declare class MathBlockAstNode extends BlockAstNodeBase {
1175
+ readonly content: readonly (MarkerAstNode | GlueAstNode)[];
1176
+ readonly leadingTrivia?: GlueAstNode | undefined;
1177
+ readonly kind = "mathBlock";
1178
+ constructor(content: readonly (MarkerAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
1179
+ get children(): readonly AstNode[];
1180
+ get code(): MarkerAstNode | undefined;
1181
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
1182
+ withLeadingTrivia(trivia: GlueAstNode | undefined): MathBlockAstNode;
1183
+ }
1184
+
1185
+ declare class MathBlockViewData {
1186
+ readonly ast: MathBlockAstNode;
1187
+ /** Active: render the source; inactive: the KaTeX output. */
1188
+ readonly showMarkup: boolean;
1189
+ readonly content: readonly AnyViewData[];
1190
+ readonly kind = "mathBlock";
1191
+ constructor(ast: MathBlockAstNode,
1192
+ /** Active: render the source; inactive: the KaTeX output. */
1193
+ showMarkup: boolean, content: readonly AnyViewData[]);
1194
+ }
1195
+
1196
+ /** Result of a {@link BlockViewOptions.renderMath} renderer. */
1197
+ export declare interface MathRendering {
1198
+ /** Host element to mount (the rendered math output). */
1199
+ readonly dom: HTMLElement;
1200
+ /** Source-mapped spans within {@link dom} (need not tile the whole node). */
1201
+ readonly segments: readonly MathSourceSegment[];
1202
+ }
1203
+
1204
+ /** Input to a {@link BlockViewOptions.renderMath} renderer. */
1205
+ export declare interface MathRenderRequest {
1206
+ /** The LaTeX source of the math content (without the `$$`/`$` fences). */
1207
+ readonly latex: string;
1208
+ /** `true` for a `$$…$$` block, `false` for inline `$…$`. */
1209
+ readonly displayMode: boolean;
1210
+ /** CSS class the host element must carry (editor styling/measurement hooks). */
1211
+ readonly className: string;
1212
+ /** Full source length of the math node (fences/`$` included). */
1213
+ readonly nodeLength: number;
1214
+ /** Offset of {@link latex} within the node (i.e. after the opening fence/`$`). */
1215
+ readonly contentStart: number;
1216
+ }
1217
+
1218
+ /**
1219
+ * A span of the rendered math output that maps to a slice of source. The
1220
+ * renderer reports these for the parts it can map (e.g. identifier glyphs);
1221
+ * the editor tiles the gaps between them so the whole math node stays mapped.
1222
+ */
1223
+ export declare interface MathSourceSegment {
1224
+ /** A DOM node (ideally a Text node) within the rendered output. */
1225
+ readonly dom: globalThis.Node;
1226
+ /** Start offset of the mapped slice, relative to the math node's start. */
1227
+ readonly start: number;
1228
+ /** Source length of the mapped slice. */
1229
+ readonly length: number;
1230
+ }
1231
+
1232
+ /**
1233
+ * Immutable record of one rendered debug frame.
1234
+ */
1235
+ export declare class MeasuredLayoutDebugRendering {
1236
+ readonly blockCount: number;
1237
+ readonly mountedCount: number;
1238
+ readonly lineCount: number;
1239
+ /** Absolute source offsets that map to a rendered DOM character. */
1240
+ readonly mappedOffsets: ReadonlySet<number>;
1241
+ constructor(blockCount: number, mountedCount: number, lineCount: number,
1242
+ /** Absolute source offsets that map to a rendered DOM character. */
1243
+ mappedOffsets: ReadonlySet<number>);
1244
+ }
1245
+
1246
+ /**
1247
+ * Debug view for a {@link MeasuredLayoutModel}.
1248
+ *
1249
+ * Exposes two DOM nodes the caller can place independently:
1250
+ *
1251
+ * - {@link overlayElement} — absolutely positioned; the caller mounts it
1252
+ * inside the editor element so dashed line-bands and run-boxes line up
1253
+ * with the editor's client coordinates.
1254
+ * - {@link infoElement} — block-flow; the caller mounts it as a sibling
1255
+ * *below* the editor. Contains the per-block summary table that used
1256
+ * to live on the overlay.
1257
+ *
1258
+ * Same pattern as `CursorView` / `SelectionView`: the rendering pipeline
1259
+ * is a single `derived` whose compute callback writes the DOM and returns
1260
+ * a {@link MeasuredLayoutDebugRendering} value as proof. An autorun keeps
1261
+ * the derived subscribed.
1262
+ */
1263
+ export declare class MeasuredLayoutDebugView extends Disposable {
1264
+ private readonly _overlayParent;
1265
+ readonly overlayElement: HTMLElement;
1266
+ readonly infoElement: HTMLElement;
1267
+ readonly rendering: IObservable<MeasuredLayoutDebugRendering>;
1268
+ /** Absolute source offsets that map to a rendered DOM character. */
1269
+ readonly mappedOffsets: IObservable<ReadonlySet<number>>;
1270
+ /** Whether the dashed line-bands and run boxes are drawn (persisted). */
1271
+ private readonly _showLineRects;
1272
+ constructor(_overlayParent: HTMLElement, options: MeasuredLayoutDebugViewOptions);
1273
+ }
1274
+
1275
+ export declare interface MeasuredLayoutDebugViewOptions {
1276
+ readonly model: MeasuredLayoutModel;
1277
+ /**
1278
+ * DEBUG ONLY. Maps an absolute source offset to a fill color for that
1279
+ * character's glyph rect. The fixture passes the same function to the
1280
+ * raw-source view so a character and its rect share one color — a
1281
+ * mismatch exposes a source ↔ DOM mapping bug.
1282
+ */
1283
+ readonly colorForOffset?: (offset: number) => string | undefined;
1284
+ /**
1285
+ * DEBUG ONLY. Shared "currently hovered source offset". When set, the
1286
+ * overlay isolates the matching glyph rect; the fixture passes the same
1287
+ * observable to the raw-source view so hovering either side highlights the
1288
+ * same character in both. Hovering a rect writes this; `undefined` clears.
1289
+ */
1290
+ readonly hoveredOffset?: ISettableObservable<number | undefined>;
1291
+ }
1292
+
1293
+ /**
1294
+ * The set of measurements/estimates the view has produced for the current
1295
+ * document. This is the "view → derived facts about layout" channel: the
1296
+ * view writes here as a side effect of rendering and measuring; the
1297
+ * controller (and selection/cursor rendering) reads from here.
1298
+ *
1299
+ * Keeping these facts in their own observable model — instead of as ad-hoc
1300
+ * fields on the view — preserves the invariant
1301
+ *
1302
+ * view(model + Δ) = view(model) + Δ
1303
+ *
1304
+ * i.e. the view becomes a pure function of (EditorModel, MeasuredLayoutModel).
1305
+ * Everything else that depends on layout (controller, commands) goes
1306
+ * through this model and never touches view fields directly.
1307
+ */
1308
+ export declare class MeasuredLayoutModel {
1309
+ readonly measurements: ISettableObservable<readonly BlockMeasurement[], void>;
1310
+ /**
1311
+ * Concatenated visual line map across all mounted blocks. Lines are
1312
+ * left in DOM (client-coordinate) y order — each per-block map already
1313
+ * uses absolute client coordinates from `getClientRects()`, so the
1314
+ * concatenation is well-formed without re-sorting.
1315
+ */
1316
+ readonly visualLineMap: IObservableWithChange<VisualLineMap, void>;
1317
+ }
1318
+
1319
+ /**
1320
+ * {@link ISyntaxHighlighter} backed by monaco's Monarch tokenizer.
1321
+ *
1322
+ * Highlighting is synchronous and incremental: an edit only re-runs the
1323
+ * tokenizer from the first changed line onward (earlier lines and their saved
1324
+ * end-states are reused), and the {@link LengthEdit} delivered with the new
1325
+ * snapshot is the minimal char range whose colour actually changed.
1326
+ *
1327
+ * Only Monarch's *classic* tokenizer path is used, which needs neither a theme
1328
+ * nor the DOM, so this runs headless (Node, workers) as well as in the browser.
1329
+ */
1330
+ export declare class MonacoSyntaxHighlighter implements ISyntaxHighlighter {
1331
+ private readonly _monaco;
1332
+ private readonly _grammars;
1333
+ private readonly _tokenizers;
1334
+ /**
1335
+ * @param _monaco The Monarch runtime ({@link IMonarchApi}), injected so this
1336
+ * package depends on `monaco-editor` for types only.
1337
+ * @param _grammars Maps a language id to its Monarch language definition.
1338
+ */
1339
+ constructor(_monaco: IMonarchApi, _grammars: ReadonlyMap<string, unknown>);
1340
+ create(language: string, initialText: string): ISyntaxHighlighterDocument;
1341
+ dispose(): void;
1342
+ private _tokenizerFor;
1343
+ }
1344
+
1345
+ /**
1346
+ * Default strategy: handle the browser's native `copy`/`cut`/`paste` events,
1347
+ * reading and writing the synchronous {@link ClipboardEvent.clipboardData}.
1348
+ * This is the standard rich-editor approach and works wherever the browser
1349
+ * actually dispatches those events to the focused element (e.g. a standalone
1350
+ * web page).
1351
+ */
1352
+ export declare class NativeClipboardStrategy implements IClipboardStrategy {
1353
+ connect(context: IClipboardContext): IDisposable;
1354
+ }
1355
+
1356
+ /**
1357
+ * Move the cursor one position left or right, skipping over hidden marker
1358
+ * ranges in inactive blocks (and inactive items of an active list).
1359
+ */
1360
+ export declare function nextCursorPosition(doc: DocumentAstNode, activeBlock: BlockAstNode | undefined, cursor: number, direction: 'left' | 'right'): number;
1361
+
1362
+ declare const NO_ACTIVE_BLOCKS: unique symbol;
1363
+
1364
+ export declare class OffsetRange {
1365
+ readonly start: number;
1366
+ readonly endExclusive: number;
1367
+ static fromTo(start: number, endExclusive: number): OffsetRange;
1368
+ static ofLength(length: number): OffsetRange;
1369
+ static ofStartAndLength(start: number, length: number): OffsetRange;
1370
+ static emptyAt(offset: number): OffsetRange;
1371
+ constructor(start: number, endExclusive: number);
1372
+ get isEmpty(): boolean;
1373
+ get length(): number;
1374
+ delta(offset: number): OffsetRange;
1375
+ deltaStart(offset: number): OffsetRange;
1376
+ deltaEnd(offset: number): OffsetRange;
1377
+ contains(offset: number): boolean;
1378
+ containsRange(other: OffsetRange): boolean;
1379
+ intersects(other: OffsetRange): boolean;
1380
+ intersectsOrTouches(other: OffsetRange): boolean;
1381
+ intersect(other: OffsetRange): OffsetRange | undefined;
1382
+ join(other: OffsetRange): OffsetRange;
1383
+ isBefore(other: OffsetRange): boolean;
1384
+ isAfter(other: OffsetRange): boolean;
1385
+ substring(str: string): string;
1386
+ slice<T>(arr: readonly T[]): T[];
1387
+ equals(other: OffsetRange): boolean;
1388
+ toString(): string;
1389
+ }
1390
+
1391
+ export declare class ParagraphAstNode extends BlockAstNodeBase {
1392
+ readonly content: readonly (InlineAstNode | GlueAstNode)[];
1393
+ readonly leadingTrivia?: GlueAstNode | undefined;
1394
+ readonly kind = "paragraph";
1395
+ constructor(content: readonly (InlineAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
1396
+ get children(): readonly AstNode[];
1397
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
1398
+ withLeadingTrivia(trivia: GlueAstNode | undefined): ParagraphAstNode;
1399
+ }
1400
+
1401
+ declare class ParagraphViewData {
1402
+ readonly ast: ParagraphAstNode;
1403
+ readonly content: readonly AnyViewData[];
1404
+ readonly kind = "paragraph";
1405
+ constructor(ast: ParagraphAstNode, content: readonly AnyViewData[]);
1406
+ }
1407
+
1408
+ /**
1409
+ * A *transient* editing state: the empty paragraph the user conjured by
1410
+ * pressing Enter at the end of a paragraph. Markdown has no empty-paragraph
1411
+ * node, so this never lives in {@link EditorModel.sourceText} or the parsed
1412
+ * {@link EditorModel.document} — it is pure edit intent that the view renders
1413
+ * as a synthetic blank line and that the controller either *materializes* (the
1414
+ * user types) or *cancels* (the user navigates away / backspaces).
1415
+ */
1416
+ declare interface PendingParagraph {
1417
+ /** The paragraph the blank line is rendered directly after. */
1418
+ readonly anchorBlock: BlockAstNode;
1419
+ /**
1420
+ * Source region rewritten when the pending paragraph is materialized — the
1421
+ * gap between {@link anchorBlock}'s text and whatever follows it.
1422
+ */
1423
+ readonly replaceRange: OffsetRange;
1424
+ /** Whether {@link replaceRange} ends at the end of the document. */
1425
+ readonly atEof: boolean;
1426
+ /**
1427
+ * A throwaway AST node that exists only to give the synthetic view child a
1428
+ * stable identity across render frames (the view pairs nodes by `ast.id`).
1429
+ * It is never part of {@link document}.
1430
+ */
1431
+ readonly syntheticAst: ParagraphAstNode;
1432
+ }
1433
+
1434
+ /**
1435
+ * View-data for the transient empty paragraph (see `PendingParagraph` in the
1436
+ * model). It carries only the throwaway {@link ParagraphAstNode} that gives the
1437
+ * rendered blank line a stable identity across frames; it has no content and is
1438
+ * never measured or part of the selection geometry — the caret is positioned
1439
+ * over it via a dedicated rect, not via the visual-line map.
1440
+ */
1441
+ declare class PendingParagraphViewData {
1442
+ readonly ast: ParagraphAstNode;
1443
+ readonly kind = "pendingParagraph";
1444
+ constructor(ast: ParagraphAstNode);
1445
+ }
1446
+
1447
+ /**
1448
+ * Immutable point in 2D space, in CSS-pixel client coordinates.
1449
+ */
1450
+ export declare class Point2D {
1451
+ readonly x: number;
1452
+ readonly y: number;
1453
+ static readonly ZERO: Point2D;
1454
+ constructor(x: number, y: number);
1455
+ translate(dx: number, dy: number): Point2D;
1456
+ }
1457
+
1458
+ /**
1459
+ * Immutable axis-aligned rectangle in 2D space, in CSS-pixel client
1460
+ * coordinates. `x`/`y` is the top-left corner, growing right/down.
1461
+ *
1462
+ * Half-open in both dimensions: `right` and `bottom` are excluded.
1463
+ */
1464
+ export declare class Rect2D {
1465
+ readonly x: number;
1466
+ readonly y: number;
1467
+ readonly width: number;
1468
+ readonly height: number;
1469
+ static readonly EMPTY: Rect2D;
1470
+ static fromPointPoint(left: number, top: number, right: number, bottom: number): Rect2D;
1471
+ static fromPointSize(x: number, y: number, width: number, height: number): Rect2D;
1472
+ private constructor();
1473
+ get left(): number;
1474
+ get top(): number;
1475
+ get right(): number;
1476
+ get bottom(): number;
1477
+ get topLeft(): Point2D;
1478
+ containsX(x: number): boolean;
1479
+ containsY(y: number): boolean;
1480
+ containsPoint(p: Point2D): boolean;
1481
+ /** Same y/height, zero-width band at `x = this.left`. Useful for caret rects derived from a line. */
1482
+ withZeroWidthAt(x: number): Rect2D;
1483
+ translate(dx: number, dy: number): Rect2D;
1484
+ }
1485
+
1486
+ export declare const selectAll: SelectionCommand;
1487
+
1488
+ export declare function selectBlock(ctx: CursorCommandContext, blockRange: OffsetRange): Selection_2;
1489
+
1490
+ declare class Selection_2 {
1491
+ readonly anchor: SourceOffset;
1492
+ readonly active: SourceOffset;
1493
+ static collapsed(offset: SourceOffset): Selection_2;
1494
+ constructor(anchor: SourceOffset, active: SourceOffset);
1495
+ get isCollapsed(): boolean;
1496
+ get isForward(): boolean;
1497
+ get range(): OffsetRange;
1498
+ collapseToActive(): Selection_2;
1499
+ withActive(active: SourceOffset): Selection_2;
1500
+ }
1501
+ export { Selection_2 as Selection }
1502
+
1503
+ /**
1504
+ * One mounted block, as far as selection painting is concerned. The view
1505
+ * supplies its block cache in this shape so the selection layer never has
1506
+ * to reach back into private view state.
1507
+ */
1508
+ export declare interface SelectionBlock {
1509
+ readonly block: BlockAstNode;
1510
+ readonly absoluteStart: number;
1511
+ readonly viewNode: ViewNode;
1512
+ readonly element: HTMLElement;
1513
+ }
1514
+
1515
+ export declare type SelectionCommand = (ctx: CursorCommandContext, offset: SourceOffset) => Selection_2;
1516
+
1517
+ export declare interface SelectionRect {
1518
+ readonly x: number;
1519
+ readonly y: number;
1520
+ readonly width: number;
1521
+ readonly height: number;
1522
+ }
1523
+
1524
+ /**
1525
+ * Owns the SVG overlay that paints the selection.
1526
+ *
1527
+ * Rendering is *line-based*, not glyph-based:
1528
+ *
1529
+ * 1. Each {@link VisualLine} overlapping the selection produces one rect
1530
+ * using the full line-box height (so the selection has even, line-
1531
+ * height bands instead of jagged glyph rects).
1532
+ * 2. Inter-block gaps fully inside the selection become connector rects.
1533
+ * 3. All rects are grouped into vertically-adjacent clusters and each
1534
+ * cluster is rendered as a single connected polygon with rounded
1535
+ * corners.
1536
+ *
1537
+ * To keep the polygon connected without gaps, "middle" lines (any line
1538
+ * that is neither the first nor the last selected line in the document)
1539
+ * are extended to their full line extent, while the first and last lines
1540
+ * are clipped to the actual selection start/end. This is the standard
1541
+ * envelope shape used by IDE selection rendering.
1542
+ */
1543
+ export declare class SelectionView extends Disposable {
1544
+ private readonly _parent;
1545
+ readonly element: SVGSVGElement;
1546
+ readonly rendering: IObservable<SelectionViewRendering>;
1547
+ private readonly _path;
1548
+ constructor(_parent: HTMLElement, options: SelectionViewOptions);
1549
+ }
1550
+
1551
+ export declare interface SelectionViewOptions {
1552
+ readonly selection: IObservable<Selection_2 | undefined>;
1553
+ readonly visualLineMap: IObservable<VisualLineMap>;
1554
+ readonly blocks: IObservable<readonly SelectionBlock[]>;
1555
+ }
1556
+
1557
+ export declare class SelectionViewRendering {
1558
+ readonly rects: readonly SelectionRect[];
1559
+ constructor(rects: readonly SelectionRect[]);
1560
+ }
1561
+
1562
+ export declare const selectWord: SelectionCommand;
1563
+
1564
+ /**
1565
+ * The outcome of {@link insertSmartEnter}: either a concrete source edit (the
1566
+ * ordinary cases), or a request to arm a transient empty paragraph (Enter at
1567
+ * the very end of a paragraph), which the controller turns into
1568
+ * {@link EditorModel.armPendingParagraph} rather than a source edit. Modelling
1569
+ * the empty paragraph as state instead of source keeps the document valid
1570
+ * Markdown — which has no empty-paragraph node — until the user actually types.
1571
+ */
1572
+ export declare type SmartEnterResult = {
1573
+ readonly kind: 'edit';
1574
+ readonly edit: StringEdit;
1575
+ readonly selection: Selection_2;
1576
+ } | {
1577
+ readonly kind: 'pending';
1578
+ readonly anchorBlock: BlockAstNode;
1579
+ readonly replaceRange: OffsetRange;
1580
+ readonly atEof: boolean;
1581
+ };
1582
+
1583
+ /**
1584
+ * A run of {@link Token}s together with the exact {@link OffsetRange} they
1585
+ * cover.
1586
+ *
1587
+ * Because tokens are returned whole (never clipped), this is the natural unit
1588
+ * of structural comparison: for any region untouched by an edit, two snapshots
1589
+ * return an equal `SnapshotTokens` (same `range`, same token lengths/classes).
1590
+ */
1591
+ export declare interface SnapshotTokens {
1592
+ readonly range: OffsetRange;
1593
+ readonly tokens: readonly Token[];
1594
+ }
1595
+
1596
+ export declare type SourceOffset = number;
1597
+
1598
+ export declare class StrikethroughAstNode extends AstNode {
1599
+ readonly openMarker: MarkerAstNode;
1600
+ readonly content: readonly (InlineAstNode | GlueAstNode)[];
1601
+ readonly closeMarker: MarkerAstNode;
1602
+ readonly kind = "strikethrough";
1603
+ constructor(openMarker: MarkerAstNode, content: readonly (InlineAstNode | GlueAstNode)[], closeMarker: MarkerAstNode);
1604
+ get children(): readonly AstNode[];
1605
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
1606
+ }
1607
+
1608
+ declare class StrikethroughViewData {
1609
+ readonly ast: StrikethroughAstNode;
1610
+ readonly content: readonly AnyViewData[];
1611
+ readonly kind = "strikethrough";
1612
+ constructor(ast: StrikethroughAstNode, content: readonly AnyViewData[]);
1613
+ }
1614
+
1615
+ export declare class StringEdit {
1616
+ static readonly empty: StringEdit;
1617
+ static single(replacement: StringReplacement): StringEdit;
1618
+ static replace(range: OffsetRange, text: string): StringEdit;
1619
+ static insert(offset: number, text: string): StringEdit;
1620
+ static delete(range: OffsetRange): StringEdit;
1621
+ readonly replacements: readonly StringReplacement[];
1622
+ constructor(replacements: readonly StringReplacement[]);
1623
+ get isEmpty(): boolean;
1624
+ apply(base: string): string;
1625
+ inverse(original: string): StringEdit;
1626
+ equals(other: StringEdit): boolean;
1627
+ mapOffset(offset: number): number;
1628
+ toString(): string;
1629
+ }
1630
+
1631
+ export declare class StringReplacement {
1632
+ readonly replaceRange: OffsetRange;
1633
+ readonly newText: string;
1634
+ static insert(offset: number, text: string): StringReplacement;
1635
+ static replace(range: OffsetRange, text: string): StringReplacement;
1636
+ static delete(range: OffsetRange): StringReplacement;
1637
+ constructor(replaceRange: OffsetRange, newText: string);
1638
+ get isEmpty(): boolean;
1639
+ equals(other: StringReplacement): boolean;
1640
+ toString(): string;
1641
+ }
1642
+
1643
+ export declare class StringValue {
1644
+ readonly value: string;
1645
+ constructor(value: string);
1646
+ get length(): number;
1647
+ substring(range: OffsetRange): string;
1648
+ toString(): string;
1649
+ }
1650
+
1651
+ export declare class StrongAstNode extends AstNode {
1652
+ readonly openMarker: MarkerAstNode;
1653
+ readonly content: readonly (InlineAstNode | GlueAstNode)[];
1654
+ readonly closeMarker: MarkerAstNode;
1655
+ readonly kind = "strong";
1656
+ constructor(openMarker: MarkerAstNode, content: readonly (InlineAstNode | GlueAstNode)[], closeMarker: MarkerAstNode);
1657
+ get children(): readonly AstNode[];
1658
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
1659
+ }
1660
+
1661
+ declare class StrongViewData {
1662
+ readonly ast: StrongAstNode;
1663
+ readonly content: readonly AnyViewData[];
1664
+ readonly kind = "strong";
1665
+ constructor(ast: StrongAstNode, content: readonly AnyViewData[]);
1666
+ }
1667
+
1668
+ export declare class TableAstNode extends BlockAstNodeBase {
1669
+ readonly content: readonly (TableRowAstNode | GlueAstNode)[];
1670
+ readonly leadingTrivia?: GlueAstNode | undefined;
1671
+ readonly kind = "table";
1672
+ constructor(content: readonly (TableRowAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
1673
+ get children(): readonly AstNode[];
1674
+ private get _rows();
1675
+ get headerRow(): TableRowAstNode | undefined;
1676
+ get delimiterRow(): TableRowAstNode | undefined;
1677
+ get bodyRows(): readonly TableRowAstNode[];
1678
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
1679
+ withLeadingTrivia(trivia: GlueAstNode | undefined): TableAstNode;
1680
+ }
1681
+
1682
+ export declare class TableCellAstNode extends AstNode {
1683
+ readonly content: readonly (InlineAstNode | MarkerAstNode | GlueAstNode)[];
1684
+ readonly kind = "tableCell";
1685
+ constructor(content: readonly (InlineAstNode | MarkerAstNode | GlueAstNode)[]);
1686
+ get children(): readonly AstNode[];
1687
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
1688
+ }
1689
+
1690
+ declare class TableCellViewData {
1691
+ readonly ast: TableCellAstNode;
1692
+ /** Whether the selection reaches this cell (reveals its inline markers). */
1693
+ readonly isActive: boolean;
1694
+ /** Whether the owning table is active (reveals the structural pipes). */
1695
+ readonly showTableGlue: boolean;
1696
+ readonly content: readonly AnyViewData[];
1697
+ readonly kind = "tableCell";
1698
+ constructor(ast: TableCellAstNode,
1699
+ /** Whether the selection reaches this cell (reveals its inline markers). */
1700
+ isActive: boolean,
1701
+ /** Whether the owning table is active (reveals the structural pipes). */
1702
+ showTableGlue: boolean, content: readonly AnyViewData[]);
1703
+ }
1704
+
1705
+ export declare class TableRowAstNode extends AstNode {
1706
+ readonly content: readonly (TableCellAstNode | GlueAstNode)[];
1707
+ readonly kind = "tableRow";
1708
+ constructor(content: readonly (TableCellAstNode | GlueAstNode)[]);
1709
+ get children(): readonly AstNode[];
1710
+ get cells(): readonly TableCellAstNode[];
1711
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
1712
+ }
1713
+
1714
+ declare class TableRowViewData {
1715
+ readonly ast: TableRowAstNode;
1716
+ readonly isDelimiter: boolean;
1717
+ readonly content: readonly AnyViewData[];
1718
+ readonly kind = "tableRow";
1719
+ constructor(ast: TableRowAstNode, isDelimiter: boolean, content: readonly AnyViewData[]);
1720
+ }
1721
+
1722
+ declare class TableViewData {
1723
+ readonly ast: TableAstNode;
1724
+ readonly content: readonly AnyViewData[];
1725
+ readonly kind = "table";
1726
+ constructor(ast: TableAstNode, content: readonly AnyViewData[]);
1727
+ }
1728
+
1729
+ /**
1730
+ * Source range (relative to `item`) of a task list item's `[x]`/`[ ]`
1731
+ * checkbox, or `undefined` when the item is not a task item. The checkbox is
1732
+ * plain glue in the AST, so a host that wants to toggle it locates the literal
1733
+ * `[x]`/`[ ]` token here.
1734
+ */
1735
+ export declare function taskCheckboxRange(item: ListItemAstNode): OffsetRange | undefined;
1736
+
1737
+ /** Real document text (an {@link InlineAstNode}). */
1738
+ export declare class TextAstNode extends LeafAstNode {
1739
+ readonly content: string;
1740
+ readonly kind = "text";
1741
+ constructor(content: string);
1742
+ protected _localEquals(o: this): boolean;
1743
+ }
1744
+
1745
+ declare class TextViewData {
1746
+ readonly ast: TextAstNode;
1747
+ readonly showWhitespace: boolean;
1748
+ readonly leftWordBoundary: boolean;
1749
+ readonly rightWordBoundary: boolean;
1750
+ readonly kind = "text";
1751
+ /**
1752
+ * Whether non-obvious whitespace in this text is revealed (block is active).
1753
+ * `leftWordBoundary`/`rightWordBoundary` say whether the inline sibling on
1754
+ * that side ends/starts with visible word content (e.g. inline code, a link,
1755
+ * emphasis); a single space touching such a sibling is obvious and stays
1756
+ * undecorated, just like a space between two words within this leaf.
1757
+ */
1758
+ constructor(ast: TextAstNode, showWhitespace: boolean, leftWordBoundary?: boolean, rightWordBoundary?: boolean);
1759
+ }
1760
+
1761
+ export declare class ThematicBreakAstNode extends BlockAstNodeBase {
1762
+ readonly content: readonly (MarkerAstNode | GlueAstNode)[];
1763
+ readonly leadingTrivia?: GlueAstNode | undefined;
1764
+ readonly kind = "thematicBreak";
1765
+ constructor(content: readonly (MarkerAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
1766
+ get children(): readonly AstNode[];
1767
+ get marker(): MarkerAstNode | undefined;
1768
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
1769
+ withLeadingTrivia(trivia: GlueAstNode | undefined): ThematicBreakAstNode;
1770
+ }
1771
+
1772
+ declare class ThematicBreakViewData {
1773
+ readonly ast: ThematicBreakAstNode;
1774
+ /** Active: reveal the source markup (`---`) instead of the rendered rule. */
1775
+ readonly showMarkup: boolean;
1776
+ /** Marker (and any absorbed trailing glue), rendered only when active. */
1777
+ readonly content: readonly AnyViewData[];
1778
+ readonly kind = "thematicBreak";
1779
+ constructor(ast: ThematicBreakAstNode,
1780
+ /** Active: reveal the source markup (`---`) instead of the rendered rule. */
1781
+ showMarkup: boolean,
1782
+ /** Marker (and any absorbed trailing glue), rendered only when active. */
1783
+ content: readonly AnyViewData[]);
1784
+ }
1785
+
1786
+ /**
1787
+ * A coloured run of `length` characters. Tokens are *dense* and *offset-free*:
1788
+ * a snapshot's tokens for a range cover it exactly, back to back, so
1789
+ * `sum(token.length) === range.length`. A token never stores where it is — its
1790
+ * position is implied by the lengths of the tokens before it, mirroring how the
1791
+ * rest of the editor keeps source offsets out of its data structures.
1792
+ */
1793
+ export declare class Token {
1794
+ readonly length: number;
1795
+ /** CSS class for this run, or `undefined` for an unstyled run. */
1796
+ readonly className: string | undefined;
1797
+ constructor(length: number,
1798
+ /** CSS class for this run, or `undefined` for an unstyled run. */
1799
+ className: string | undefined);
1800
+ }
1801
+
1802
+ /**
1803
+ * Immutable view of an AST node. Pairs `ast` with its rendered `dom` and a
1804
+ * mirror of `ast.children` as ViewNode children. Source offsets are NEVER
1805
+ * stored — they are recomputed by walking and summing `ast.length` of
1806
+ * preceding siblings, just like the AST itself.
1807
+ *
1808
+ * Leaves are ViewNodes with no children. A leaf whose `dom` is a Text node
1809
+ * participates in source mapping; a leaf whose `dom` is an Element does not
1810
+ * (e.g. KaTeX-rendered math, or `<hr>` for a thematic break).
1811
+ */
1812
+ export declare class ViewNode extends Disposable {
1813
+ readonly ast: AstNode;
1814
+ readonly dom: globalThis.Node;
1815
+ private _children;
1816
+ constructor(ast: AstNode, dom: globalThis.Node, children?: readonly ViewNode[]);
1817
+ /** This node's view children (a mirror of `ast.children`). */
1818
+ get children(): readonly ViewNode[];
1819
+ /**
1820
+ * Replace this node's children in place, disposing the old ones and
1821
+ * re-pointing the new ones' parent to this node. The node value is still
1822
+ * conceptually immutable with respect to its `ast`/`dom` *identity*; this
1823
+ * is used only when a node patches its own DOM subtree in place (a code
1824
+ * block re-tokenising on a highlighter recolour), where the source-mapping
1825
+ * leaves must follow the new DOM text nodes without rebuilding the node
1826
+ * itself.
1827
+ */
1828
+ protected _replaceChildren(children: readonly ViewNode[]): void;
1829
+ dispose(): void;
1830
+ /**
1831
+ * The number of source characters this node spans. Defaults to the length
1832
+ * of its {@link ast}; a synthetic leaf that subdivides one ast node (a
1833
+ * decorated-whitespace character, a code-block token span) shares that ast
1834
+ * for identity but overrides this with the length of its own slice, so the
1835
+ * renderer never has to fabricate an AST node just to carry a length.
1836
+ */
1837
+ get sourceLength(): number;
1838
+ /**
1839
+ * The DOM node a parent mounts for this child. It is {@link dom} for almost
1840
+ * everything; a marker is the exception — its `dom` is the inner Text node
1841
+ * (so source ↔ DOM mapping lands on it) while the node it mounts is the
1842
+ * wrapping `<span>`.
1843
+ */
1844
+ get mountNode(): globalThis.Node;
1845
+ /** The view node that rendered this node's parent, or `undefined` for a root. */
1846
+ get parent(): ViewNode | undefined;
1847
+ /**
1848
+ * Closest view node owning `domNode`: the node itself if registered, else
1849
+ * the nearest registered ancestor. Returns `undefined` if the DOM node is
1850
+ * outside any view tree.
1851
+ */
1852
+ static forDom(domNode: globalThis.Node | null): ViewNode | undefined;
1853
+ /**
1854
+ * This node's start offset within its parent's local source space: the sum
1855
+ * of the `ast.length` of the siblings before it. Polymorphic via
1856
+ * {@link _localOffsetOfChild} so a parent whose children do not map
1857
+ * linearly (e.g. it hides or reorders some) can override how its children
1858
+ * are placed.
1859
+ */
1860
+ localOffsetInParent(): number;
1861
+ /** Start offset of `child` within this node's local source space. */
1862
+ protected _localOffsetOfChild(child: ViewNode): number;
1863
+ /**
1864
+ * Map a DOM hit that lands on THIS node's own representation into a source
1865
+ * range in this node's local space `[0, ast.length)`. Polymorphic: a text
1866
+ * leaf maps the caret offset 1:1; an element-only node (KaTeX math, `<hr>`,
1867
+ * an image, a hidden marker) has no internal text mapping and snaps to its
1868
+ * start by default — subclasses may override (e.g. to snap to the nearer
1869
+ * edge by x).
1870
+ */
1871
+ getLocalSourceRange(pos: DomPosition): OffsetRange;
1872
+ /**
1873
+ * DOM hit (any node + offset within it) → source offset relative to THIS
1874
+ * node, or `undefined` when the hit is outside this node's subtree. Enters
1875
+ * the tree at the closest owning view node ({@link forDom}), maps the hit
1876
+ * into that node's local space ({@link getLocalSourceRange}), then lifts the
1877
+ * range up the parent chain — adding each node's {@link localOffsetInParent} —
1878
+ * until it reaches this node.
1879
+ */
1880
+ resolveSource(pos: DomPosition): number | undefined;
1881
+ /**
1882
+ * Source offset → DOM position. `nodeOffset` is the absolute source
1883
+ * offset of THIS node's start. Returns a position into a DOM Text node,
1884
+ * descending into children based on accumulated lengths.
1885
+ */
1886
+ sourceToDom(localSourceOffset: number, nodeSourceOffset?: number): DomPosition | undefined;
1887
+ /** Visit every text-bearing leaf in this subtree with its absolute offset. */
1888
+ forEachTextLeaf(nodeOffset: number, visitor: (leaf: ViewNode, leafOffset: number) => void): void;
1889
+ }
1890
+
1891
+ export declare type VisualCursorCommand = (ctx: VisualCursorCommandContext) => CursorMoveResult;
1892
+
1893
+ export declare interface VisualCursorCommandContext extends CursorCommandContext {
1894
+ readonly lineMap: VisualLineMap;
1895
+ readonly desiredColumn: number | undefined;
1896
+ }
1897
+
1898
+ export declare function visualizeAst(root: AstNode, source: string): AstVisualization;
1899
+
1900
+ /**
1901
+ * One visual line of rendered text: a horizontal band
1902
+ * (`rect.top`..`rect.bottom`) split into one or more {@link VisualRun}s
1903
+ * arranged left-to-right.
1904
+ */
1905
+ export declare class VisualLine {
1906
+ readonly rect: Rect2D;
1907
+ readonly runs: readonly VisualRun[];
1908
+ constructor(rect: Rect2D, runs: readonly VisualRun[]);
1909
+ containsOffset(offset: SourceOffset): boolean;
1910
+ /**
1911
+ * How `offset` relates to this line's runs:
1912
+ * - `'covers'`: a run starts at or strictly contains the offset
1913
+ * (`start <= offset < endExclusive`) — the caret belongs on this line.
1914
+ * - `'end'`: the offset is only some run's trailing boundary
1915
+ * (`offset === endExclusive`) with no run covering it — a line-break
1916
+ * boundary the caret should leave for the next line.
1917
+ * - `'none'`: no run touches the offset.
1918
+ */
1919
+ offsetMembership(offset: SourceOffset): 'covers' | 'end' | 'none';
1920
+ /**
1921
+ * Min `|offset - r|` over offsets `r` in any of this line's runs. Used
1922
+ * to pick the nearest line when no run actually covers the offset.
1923
+ */
1924
+ sourceDistanceTo(offset: SourceOffset): number;
1925
+ /**
1926
+ * x of the caret position before `offset` on this line. When `offset`
1927
+ * is past all runs (trailing whitespace / blank line), returns the
1928
+ * right edge of the last run; when before all runs, returns the left
1929
+ * edge of the first run.
1930
+ */
1931
+ xAtOffset(offset: SourceOffset): number;
1932
+ /**
1933
+ * Snap `x` to the nearest offset on this line. If `x` falls inside a
1934
+ * run, the offset is interpolated by character fraction; otherwise it
1935
+ * snaps to the closer edge of the nearest run.
1936
+ */
1937
+ offsetAtX(x: number): SourceOffset;
1938
+ }
1939
+
1940
+ /**
1941
+ * Geometry of the rendered document, as a map from source offsets to 2D
1942
+ * positions and back.
1943
+ *
1944
+ * Structure (top to bottom):
1945
+ *
1946
+ * VisualLineMap = ordered list of VisualLines
1947
+ * VisualLine = a horizontal band [rect.top, rect.bottom) split
1948
+ * into one or more VisualRuns
1949
+ * VisualRun = a contiguous source range painted at a rectangle
1950
+ * on the line
1951
+ *
1952
+ * Invariants:
1953
+ * - `lines[i].rect.bottom <= lines[i+1].rect.top + ε`
1954
+ * - For any offset `o` covered by some run on line `L`:
1955
+ * `xAtOffset(o)` is inside that run's horizontal range
1956
+ * `xAtOffset(o)` is inside `L.rect.left..L.rect.right`
1957
+ *
1958
+ * The "map" goes both ways:
1959
+ * - SourceOffset → (line, x) via {@link lineIndexOfOffset} + {@link xAtOffset}
1960
+ * - Point2D → SourceOffset via {@link offsetAtPoint}
1961
+ *
1962
+ * Both directions are total but not bijective: many offsets at a line
1963
+ * boundary map to the same `x`, and large areas of the document
1964
+ * (padding, gaps) map onto the nearest offset on the nearest line.
1965
+ *
1966
+ * Rendering a caret rect from these primitives is a consumer concern:
1967
+ *
1968
+ * const i = map.lineIndexOfOffset(o);
1969
+ * const caretRect = map.lineRect(i).withZeroWidthAt(map.xAtOffset(o));
1970
+ */
1971
+ export declare class VisualLineMap {
1972
+ readonly lines: readonly VisualLine[];
1973
+ static readonly EMPTY: VisualLineMap;
1974
+ static measure(blockViews: readonly {
1975
+ readonly absoluteStart: number;
1976
+ readonly viewNode: ViewNode;
1977
+ }[]): VisualLineMap;
1978
+ constructor(lines: readonly VisualLine[]);
1979
+ get lineCount(): number;
1980
+ get isEmpty(): boolean;
1981
+ lineRect(lineIndex: number): Rect2D;
1982
+ /**
1983
+ * Line whose runs cover the offset, or the nearest line by source
1984
+ * distance if no run covers it.
1985
+ *
1986
+ * An offset that is only a run's *trailing* boundary (`offset ===
1987
+ * endExclusive`) — most notably the source offset just past a
1988
+ * line-breaking `\n`, which a zero-width run reports as its end on the line
1989
+ * it terminates — belongs to the START of the NEXT line instead. Preferring
1990
+ * the line that actually *starts* the offset makes the caret advance past a
1991
+ * newline to the next line rather than collapsing onto the previous line's
1992
+ * end (which would render two distinct offsets at the same caret position).
1993
+ * The first such trailing-boundary line is remembered as a fallback for the
1994
+ * document's very last offset, where no later line starts it.
1995
+ */
1996
+ lineIndexOfOffset(offset: SourceOffset): number;
1997
+ /**
1998
+ * x of the caret position before `offset`, on the line returned by
1999
+ * {@link lineIndexOfOffset}. Returns `0` when the map is empty.
2000
+ */
2001
+ xAtOffset(offset: SourceOffset): number;
2002
+ /**
2003
+ * Line whose vertical band contains `y`, clamped to the first/last
2004
+ * line when `y` is outside the document.
2005
+ */
2006
+ lineIndexAtY(y: number): number;
2007
+ /**
2008
+ * Snap a 2D point to the nearest source offset. Uses `y` to pick a
2009
+ * line, then `x` to pick an offset within it. Up/down navigation
2010
+ * uses {@link offsetInLineAtX} directly to preserve desired column.
2011
+ */
2012
+ offsetAtPoint(point: Point2D): SourceOffset;
2013
+ /** Snap `x` to the nearest offset on a specific line. */
2014
+ offsetInLineAtX(lineIndex: number, x: number): SourceOffset;
2015
+ }
2016
+
2017
+ /**
2018
+ * One contiguous run of text painted on a single visual line.
2019
+ *
2020
+ * When constructed with a {@link VisualRunSource}, `xAtOffset` returns the
2021
+ * pixel-exact x of the caret before character `offset` by measuring the
2022
+ * prefix `[textNodeStart, textNodeStart + (offset - sourceStart))` with a
2023
+ * DOM `Range`. Without a source it falls back to linear interpolation
2024
+ * across `rect.width`.
2025
+ */
2026
+ export declare class VisualRun {
2027
+ readonly sourceRange: OffsetRange;
2028
+ readonly rect: Rect2D;
2029
+ readonly source?: VisualRunSource | undefined;
2030
+ constructor(sourceRange: OffsetRange, rect: Rect2D, source?: VisualRunSource | undefined);
2031
+ get sourceStart(): SourceOffset;
2032
+ get sourceEndExclusive(): SourceOffset;
2033
+ get sourceLength(): number;
2034
+ containsOffset(offset: SourceOffset): boolean;
2035
+ sourceDistanceTo(offset: SourceOffset): number;
2036
+ xAtOffset(offset: SourceOffset): number;
2037
+ offsetAtX(x: number): SourceOffset;
2038
+ }
2039
+
2040
+ /**
2041
+ * The DOM source of a {@link VisualRun}. When set, `xAtOffset` and
2042
+ * `offsetAtX` measure exact glyph positions via `Range.getBoundingClientRect`
2043
+ * instead of linear interpolation across the run's rect. This matters for
2044
+ * proportional fonts where character widths differ a lot (e.g. `m` vs `i`)
2045
+ * and a caret placed by interpolation lands several pixels inside the
2046
+ * wrong character.
2047
+ *
2048
+ * Hand-built runs (tests) omit this; their `xAtOffset` falls back to
2049
+ * linear interpolation.
2050
+ */
2051
+ declare interface VisualRunSource {
2052
+ readonly textNode: Text;
2053
+ /** Offset within `textNode.data` corresponding to `sourceRange.start`. */
2054
+ readonly textNodeStart: number;
2055
+ }
2056
+
2057
+ export { }