@vscode/markdown-editor 0.0.2-1 → 0.0.2-100

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 (75) hide show
  1. package/README.md +31 -0
  2. package/dist/commands.d.ts +67 -0
  3. package/dist/commands.js +183 -0
  4. package/dist/commands.js.map +1 -0
  5. package/dist/config-BGeaJqWk.js +286 -0
  6. package/dist/config-BGeaJqWk.js.map +1 -0
  7. package/dist/config.d.ts +10 -0
  8. package/dist/config.js +6 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/index.d.ts +1901 -112
  11. package/dist/index.js +7073 -1969
  12. package/dist/index.js.map +1 -1
  13. package/dist/markdown-editor.css +1 -0
  14. package/dist/stringEdit-CVDbCUBY.js +215 -0
  15. package/dist/stringEdit-CVDbCUBY.js.map +1 -0
  16. package/dist/web-editors.d.ts +297 -0
  17. package/dist/web-editors.js +7359 -0
  18. package/dist/web-editors.js.map +1 -0
  19. package/package.json +60 -15
  20. package/src/contrib/comments/commentInput.css +89 -0
  21. package/src/contrib/comments/commentWidget.css +60 -0
  22. package/src/contrib/find/find.css +347 -0
  23. package/src/view/editor.css +1316 -44
  24. package/src/view/themes/default.css +13 -4
  25. package/src/view/themes/github.css +16 -18
  26. package/src/view/themes/vscode-default.css +397 -0
  27. package/src/view/themes/vscode-github.css +393 -0
  28. package/dist/_observables/assert.d.ts +0 -2
  29. package/dist/_observables/deps.d.ts +0 -28
  30. package/dist/_observables/disposables.d.ts +0 -19
  31. package/dist/_observables/equals.d.ts +0 -32
  32. package/dist/_observables/index.d.ts +0 -2
  33. package/dist/_observables/observableInternal/base.d.ts +0 -172
  34. package/dist/_observables/observableInternal/changeTracker.d.ts +0 -44
  35. package/dist/_observables/observableInternal/commonFacade/cancellation.d.ts +0 -24
  36. package/dist/_observables/observableInternal/commonFacade/deps.d.ts +0 -24
  37. package/dist/_observables/observableInternal/debugLocation.d.ts +0 -21
  38. package/dist/_observables/observableInternal/debugName.d.ts +0 -33
  39. package/dist/_observables/observableInternal/experimental/deferUnobserve.d.ts +0 -16
  40. package/dist/_observables/observableInternal/experimental/reducer.d.ts +0 -37
  41. package/dist/_observables/observableInternal/experimental/utils.d.ts +0 -15
  42. package/dist/_observables/observableInternal/index.d.ts +0 -25
  43. package/dist/_observables/observableInternal/logging/consoleObservableLogger.d.ts +0 -40
  44. package/dist/_observables/observableInternal/logging/debugGetDependencyGraph.d.ts +0 -4
  45. package/dist/_observables/observableInternal/logging/debugger/debuggerRpc.d.ts +0 -4
  46. package/dist/_observables/observableInternal/logging/debugger/devToolsLogger.d.ts +0 -43
  47. package/dist/_observables/observableInternal/logging/debugger/rpc.d.ts +0 -41
  48. package/dist/_observables/observableInternal/logging/debugger/utils.d.ts +0 -13
  49. package/dist/_observables/observableInternal/logging/logging.d.ts +0 -30
  50. package/dist/_observables/observableInternal/map.d.ts +0 -18
  51. package/dist/_observables/observableInternal/observables/baseObservable.d.ts +0 -58
  52. package/dist/_observables/observableInternal/observables/constObservable.d.ts +0 -5
  53. package/dist/_observables/observableInternal/observables/derived.d.ts +0 -46
  54. package/dist/_observables/observableInternal/observables/derivedImpl.d.ts +0 -83
  55. package/dist/_observables/observableInternal/observables/lazyObservableValue.d.ts +0 -27
  56. package/dist/_observables/observableInternal/observables/observableFromEvent.d.ts +0 -37
  57. package/dist/_observables/observableInternal/observables/observableSignal.d.ts +0 -11
  58. package/dist/_observables/observableInternal/observables/observableSignalFromEvent.d.ts +0 -5
  59. package/dist/_observables/observableInternal/observables/observableValue.d.ts +0 -37
  60. package/dist/_observables/observableInternal/observables/observableValueOpts.d.ts +0 -8
  61. package/dist/_observables/observableInternal/reactions/autorun.d.ts +0 -56
  62. package/dist/_observables/observableInternal/reactions/autorunImpl.d.ts +0 -53
  63. package/dist/_observables/observableInternal/set.d.ts +0 -17
  64. package/dist/_observables/observableInternal/transaction.d.ts +0 -27
  65. package/dist/_observables/observableInternal/utils/promise.d.ts +0 -75
  66. package/dist/_observables/observableInternal/utils/runOnChange.d.ts +0 -7
  67. package/dist/_observables/observableInternal/utils/utils.d.ts +0 -43
  68. package/dist/_observables/observableInternal/utils/utilsCancellation.d.ts +0 -10
  69. package/dist/_observables/observableInternal/utils/valueWithChangeEvent.d.ts +0 -10
  70. package/dist/_observables/utils.d.ts +0 -15
  71. package/dist/observables.d.ts +0 -4
  72. package/dist/observables.js +0 -463
  73. package/dist/observables.js.map +0 -1
  74. package/dist/runOnChange-owE1SMC0.js +0 -1514
  75. package/dist/runOnChange-owE1SMC0.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -1,15 +1,32 @@
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';
1
+ import { Disposable } from '@vscode/observables';
2
+ import { IDisposable } from '@vscode/observables';
3
+ import { IObservable } from '@vscode/observables';
4
+ import { IObservableWithChange } from '@vscode/observables';
5
+ import { ISettableObservable } from '@vscode/observables';
6
+ import { ITransaction } from '@vscode/observables';
7
7
  import { MonarchTokenizer } from 'monaco-editor/esm/vs/editor/standalone/common/monarch/monarchLexer.js';
8
8
 
9
+ declare interface AddedItem {
10
+ readonly kind: 'added';
11
+ readonly node: AstNode;
12
+ readonly modifiedStart: number;
13
+ readonly insertedLocal: readonly AnnotatedRange[];
14
+ }
15
+
16
+ /**
17
+ * A word/character-level highlight inside a single block, in that block's
18
+ * *local* coordinate space (`0` = block start). `inserted` ranges live on a
19
+ * modified/added block, `deleted` ranges on an original/removed block.
20
+ */
21
+ declare interface AnnotatedRange {
22
+ readonly range: OffsetRange;
23
+ readonly kind: 'inserted' | 'deleted';
24
+ }
25
+
9
26
  /** 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;
27
+ export declare type AnyAstNode = TextAstNode | MarkerAstNode | GlueAstNode | ThematicBreakAstNode | StrongAstNode | EmphasisAstNode | StrikethroughAstNode | InlineCodeAstNode | InlineMathAstNode | LinkAstNode | ImageAstNode | HeadingAstNode | ParagraphAstNode | FrontMatterAstNode | CodeBlockAstNode | MathBlockAstNode | BlockQuoteAstNode | ListAstNode | ListItemAstNode | TableAstNode | TableRowAstNode | TableCellAstNode | DocumentAstNode | UnhandledBlockAstNode;
11
28
 
12
- declare type AnyViewData = DocumentViewData | BlockViewData | InlineViewData | ListItemViewData | TableRowViewData | TableCellViewData | MarkerViewData | GlueViewData;
29
+ declare type AnyViewData = DocumentViewData | BlockViewData | InlineViewData | ListItemViewData | TableRowViewData | TableCellViewData | MarkerViewData | GlueViewData | DiffHunkViewData | DiffDecorationViewData;
13
30
 
14
31
  export declare abstract class AstNode {
15
32
  abstract readonly kind: string;
@@ -31,7 +48,7 @@ export declare abstract class AstNode {
31
48
  * instances — keeping this O(children), not O(subtree). Leaves have no
32
49
  * children, so {@link _localEquals} is their whole comparison.
33
50
  */
34
- structurallyEqual(other: AstNode): boolean;
51
+ equalsShallow(other: AstNode): boolean;
35
52
  /** Compares only this node's own scalar fields (kind/length already match). */
36
53
  protected _localEquals(_other: this): boolean;
37
54
  /**
@@ -54,12 +71,46 @@ declare interface AstVisualizationNode {
54
71
  children?: AstVisualizationNode[];
55
72
  }
56
73
 
57
- export declare type BlockAstNode = HeadingAstNode | ParagraphAstNode | CodeBlockAstNode | MathBlockAstNode | ThematicBreakAstNode | BlockQuoteAstNode | ListAstNode | TableAstNode;
74
+ /**
75
+ * Strategy for hosts that intercept native clipboard shortcuts, notably
76
+ * VS Code webviews. Their preload prevents the default Ctrl/Cmd+C/X/V handling
77
+ * and forwards the keydowns to the host. This strategy handles the keystrokes
78
+ * directly using the async {@link Clipboard} API (`navigator.clipboard`),
79
+ * which webviews are granted.
80
+ *
81
+ * Cut deletes synchronously once the text is captured; the clipboard write is
82
+ * fire-and-forget. Paste must wait for the async read before inserting.
83
+ * Handled keydowns must not reach the host, which may replay native clipboard
84
+ * commands even when the browser's default has been prevented.
85
+ */
86
+ export declare class AsyncClipboardStrategy implements IClipboardStrategy {
87
+ private readonly _clipboard;
88
+ constructor(_clipboard?: Clipboard);
89
+ connect(context: IClipboardContext): IDisposable;
90
+ }
91
+
92
+ export declare type BlockAstNode = HeadingAstNode | ParagraphAstNode | FrontMatterAstNode | CodeBlockAstNode | MathBlockAstNode | ThematicBreakAstNode | BlockQuoteAstNode | ListAstNode | TableAstNode | UnhandledBlockAstNode;
93
+
94
+ /**
95
+ * A block-level node. Every block may carry a {@link leadingTrivia} glue — the
96
+ * whitespace that precedes it on its own line (a nested list's indentation, the
97
+ * leading space of a continued paragraph). It is owned by the block it precedes
98
+ * (not the one it trails), so the view reveals it exactly when *this* block is
99
+ * active, and it tiles at the block's front: {@link children} prepends it to the
100
+ * block's own content while `content` stays the block's real payload.
101
+ */
102
+ declare abstract class BlockAstNodeBase extends AstNode {
103
+ abstract readonly leadingTrivia?: GlueAstNode;
104
+ /** This block with its leading trivia replaced — re-homes a leading glue onto it. */
105
+ abstract withLeadingTrivia(trivia: GlueAstNode | undefined): BlockAstNode;
106
+ /** Prepends {@link leadingTrivia}, if any, ahead of the block's own children. */
107
+ protected _withLeading(own: readonly AstNode[]): readonly AstNode[];
108
+ }
58
109
 
59
110
  /**
60
111
  * One block's place in the rendered document.
61
112
  *
62
- * `height` is in CSS pixels. It is either a real DOM measurement
113
+ * Geometry is in editor-local CSS pixels. `height` is either a real DOM measurement
63
114
  * (`isMeasured: true`) or an estimate produced when the block is not
64
115
  * currently mounted (`isMeasured: false`). Estimates exist so virtual
65
116
  * rendering can size the scroll container without mounting every block.
@@ -74,28 +125,48 @@ export declare interface BlockMeasurement {
74
125
  readonly block: BlockAstNode;
75
126
  readonly absoluteStart: number;
76
127
  readonly height: number;
128
+ /** Local border box when mounted and measured. */
129
+ readonly rect: Rect2D | undefined;
130
+ /** Local horizontal padding-box clip when this block scrolls horizontally. */
131
+ readonly viewportClip: {
132
+ readonly left: number;
133
+ readonly right: number;
134
+ } | undefined;
77
135
  readonly isMeasured: boolean;
78
136
  readonly visualLineMap: VisualLineMap | undefined;
79
137
  readonly viewNode: ViewNode | undefined;
80
138
  }
81
139
 
82
- export declare class BlockQuoteAstNode extends AstNode {
140
+ export declare class BlockQuoteAstNode extends BlockAstNodeBase {
83
141
  readonly content: readonly (MarkerAstNode | BlockAstNode | GlueAstNode)[];
142
+ readonly leadingTrivia?: GlueAstNode | undefined;
84
143
  readonly kind = "blockQuote";
85
- constructor(content: readonly (MarkerAstNode | BlockAstNode | GlueAstNode)[]);
144
+ constructor(content: readonly (MarkerAstNode | BlockAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
86
145
  get children(): readonly AstNode[];
87
146
  get blocks(): readonly BlockAstNode[];
88
147
  mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
148
+ withLeadingTrivia(trivia: GlueAstNode | undefined): BlockQuoteAstNode;
89
149
  }
90
150
 
91
151
  declare class BlockQuoteViewData {
92
152
  readonly ast: BlockQuoteAstNode;
93
153
  readonly content: readonly AnyViewData[];
154
+ /** False while a pending paragraph replaces the final marker-only line. */
155
+ readonly showFinalMarkerOnlyLine: boolean;
94
156
  readonly kind = "blockQuote";
95
- constructor(ast: BlockQuoteAstNode, content: readonly AnyViewData[]);
157
+ constructor(ast: BlockQuoteAstNode, content: readonly AnyViewData[],
158
+ /** False while a pending paragraph replaces the final marker-only line. */
159
+ showFinalMarkerOnlyLine: boolean);
96
160
  }
97
161
 
98
- declare type BlockViewData = HeadingViewData | ParagraphViewData | CodeBlockViewData | MathBlockViewData | ThematicBreakViewData | BlockQuoteViewData | ListViewData | TableViewData;
162
+ /**
163
+ * All blocks whose source range intersects `[start, endExclusive]`. A
164
+ * collapsed range (start === endExclusive) matches the block containing
165
+ * that offset (with the same boundary rule as {@link findBlockAtOffset}).
166
+ */
167
+ export declare function blocksIntersecting(doc: DocumentAstNode, start: SourceOffset, endExclusive: SourceOffset): BlockAstNode[];
168
+
169
+ declare type BlockViewData = HeadingViewData | ParagraphViewData | FrontMatterViewData | CodeBlockViewData | MathBlockViewData | ThematicBreakViewData | BlockQuoteViewData | ListViewData | TableViewData | UnhandledBlockViewData;
99
170
 
100
171
  /**
101
172
  * Base view node for everything the editor renders, generic over the
@@ -116,6 +187,17 @@ export declare class BlockViewNode<T extends AnyViewData = AnyViewData> extends
116
187
  constructor(data: T, dom: globalThis.Node, children: readonly ViewNode[]);
117
188
  get block(): BlockAstNode;
118
189
  get element(): HTMLElement;
190
+ /**
191
+ * The horizontal scroll viewport for selection/caret clipping
192
+ * ({@link blockViewportClip}). For most blocks the scroller *is*
193
+ * {@link element} — a code / math / unhandled block's `element` is the very
194
+ * `overflow-x: auto` box that scrolls. A table is the exception: its
195
+ * `element` stays the inner `<table>` (so the active/markers classes and
196
+ * `.md-table` theme styling are unaffected), but the box that actually
197
+ * scrolls is the wrapping `.md-table-wrapper`, so {@link TableViewNode}
198
+ * overrides this to return that wrapper.
199
+ */
200
+ get scrollElement(): HTMLElement;
119
201
  /**
120
202
  * Whether this already-built node can stand in for `data` unchanged. The
121
203
  * builder preserves view-data identity for any subtree whose ast and
@@ -123,7 +205,7 @@ export declare class BlockViewNode<T extends AnyViewData = AnyViewData> extends
123
205
  * single identity check captures "nothing in my subtree changed" — and its
124
206
  * whole subtree, and any session it owns, are kept as-is.
125
207
  */
126
- canReuse(data: AnyViewData): boolean;
208
+ canReuse(data: AnyViewData, _options: BlockViewOptions | undefined): boolean;
127
209
  /**
128
210
  * Called by the view after this block is mounted and measured, with the
129
211
  * block's rendered height in px. The default is a no-op; subclasses whose
@@ -136,12 +218,18 @@ export declare class BlockViewNode<T extends AnyViewData = AnyViewData> extends
136
218
  export declare interface BlockViewOptions {
137
219
  readonly renderCustomCodeBlock?: (language: string, content: string) => HTMLElement | undefined;
138
220
  readonly onToggleCheckbox?: (item: ListItemAstNode, newChecked: boolean) => void;
221
+ /**
222
+ * Supplies live, declarative metadata for recognized links. The editor owns
223
+ * the markup and styling; providers own lookup, caching, and updates.
224
+ */
225
+ readonly linkPresentationProvider?: ILinkPresentationProvider;
139
226
  /**
140
227
  * Opens a link's URL. Called when the user activates a link: a plain click
141
228
  * while the link's block is inactive (rendered), or a Ctrl/Cmd+click while it
142
- * is active (source shown). Defaults to `window.open(url, '_blank')`.
229
+ * is active (source shown). Return `false` to use the anchor's native
230
+ * navigation behavior.
143
231
  */
144
- readonly onOpenLink?: (url: string, event: MouseEvent) => void;
232
+ readonly onOpenLink?: (url: string, event: MouseEvent) => false | void;
145
233
  /**
146
234
  * Colours fenced code blocks. When set, a code block's content is rendered
147
235
  * as a sequence of token spans instead of one plain text node. This is the
@@ -161,15 +249,43 @@ export declare interface BlockViewOptions {
161
249
  * `katexEditableIdentifiers.ts`).
162
250
  */
163
251
  readonly renderMath?: (request: MathRenderRequest) => MathRendering | undefined;
252
+ /**
253
+ * Pluggable factory for an in-place, interactive editor that replaces the
254
+ * *rendered* (inactive) form of a fenced code block — see
255
+ * {@link IEmbeddedCodeEditor}. When it returns an editor for the block's
256
+ * language, that editor's element is mounted instead of the highlighted
257
+ * code, and content flows both ways as string edits. Returning `undefined`
258
+ * falls back to the default rendering. EXPERIMENTAL.
259
+ */
260
+ readonly embeddedCodeEditorFactory?: IEmbeddedCodeEditorFactory;
261
+ /** Current read-only state forwarded to embedded code editors. */
262
+ readonly embeddedCodeEditorReadOnly?: boolean;
263
+ /** Identity used to invalidate previously created embedded editors. */
264
+ readonly embeddedCodeEditorFactoryVersion?: unknown;
265
+ /**
266
+ * Called when an {@link IEmbeddedCodeEditor} edits its content. `contentEdit`
267
+ * is in the block's *content* coordinates; the host translates it to a
268
+ * document edit (via {@link CodeBlockAstNode.codeOffset} and the block's
269
+ * offset) and applies it to the model.
270
+ */
271
+ readonly onEmbeddedCodeEditorEdit?: (block: CodeBlockAstNode, contentEdit: StringEdit) => void;
164
272
  }
165
273
 
166
- export declare class CodeBlockAstNode extends AstNode {
274
+ export declare class CodeBlockAstNode extends BlockAstNodeBase {
275
+ /** First token of the fenced code block info string, used for syntax highlighting. */
167
276
  readonly language: string;
277
+ /** Complete fenced code block info string, including metadata after the language token. */
278
+ readonly infoString: string;
168
279
  readonly content: readonly (MarkerAstNode | GlueAstNode)[];
280
+ readonly leadingTrivia?: GlueAstNode | undefined;
169
281
  readonly kind = "codeBlock";
170
282
  private _previous?;
171
283
  private _contentEdit?;
172
- constructor(language: string, content: readonly (MarkerAstNode | GlueAstNode)[]);
284
+ constructor(
285
+ /** First token of the fenced code block info string, used for syntax highlighting. */
286
+ language: string,
287
+ /** Complete fenced code block info string, including metadata after the language token. */
288
+ infoString: string, content: readonly (MarkerAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
173
289
  get children(): readonly AstNode[];
174
290
  get openFence(): MarkerAstNode | undefined;
175
291
  get closeFence(): MarkerAstNode | undefined;
@@ -177,6 +293,7 @@ export declare class CodeBlockAstNode extends AstNode {
177
293
  /** Relative start offset of the {@link code} marker within this block. */
178
294
  get codeOffset(): number;
179
295
  mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
296
+ withLeadingTrivia(trivia: GlueAstNode | undefined): CodeBlockAstNode;
180
297
  protected _localEquals(o: this): boolean;
181
298
  /**
182
299
  * A copy of this block carrying an incremental link to `previous`:
@@ -234,10 +351,226 @@ export declare class CodeBlockViewNode extends BlockViewNode<CodeBlockViewData>
234
351
  * its predecessor's subscription explicitly.
235
352
  */
236
353
  private _snapshotSub;
354
+ /**
355
+ * An in-place interactive editor (e.g. an iframe) mounted instead of the
356
+ * rendered code. Like {@link _session} it is adopted from `previous` across
357
+ * rebuilds so the underlying editor keeps its state, and must be disposed
358
+ * manually (a node reused as `previous` is never {@link dispose}d).
359
+ */
360
+ private _embeddedEditor;
361
+ private readonly _embeddedEditorFactoryVersion;
362
+ private readonly _embeddedEditorReadOnly;
363
+ canReuse(data: AnyViewData, options: BlockViewOptions | undefined): boolean;
237
364
  constructor(data: CodeBlockViewData, options: BlockViewOptions | undefined, previous: ViewNode | undefined);
238
365
  dispose(): void;
239
366
  }
240
367
 
368
+ /**
369
+ * Canonical editor command catalog. Standalone keyboard handling and host
370
+ * integrations derive their command registration and default keybindings from
371
+ * this list.
372
+ */
373
+ export declare const commands: readonly EditorCommandDefinition[];
374
+
375
+ /** A persistent comment anchored to a source range. */
376
+ declare interface Comment_2 {
377
+ readonly id: string;
378
+ /** Source range the comment refers to (its highlighted region). */
379
+ readonly range: OffsetRange;
380
+ /** The comment text. */
381
+ readonly body: string;
382
+ /** Display name of the author, if any. */
383
+ readonly author?: string;
384
+ /** Creation time (epoch ms), used to render a relative timestamp. */
385
+ readonly createdAt?: number;
386
+ }
387
+ export { Comment_2 as Comment }
388
+
389
+ /**
390
+ * The compact editing state for a markdown comment.
391
+ *
392
+ * The widget owns its DOM and draft state but not its position. The comment-mode
393
+ * controller mounts it next to the active selection.
394
+ */
395
+ export declare class CommentInputWidget extends Disposable {
396
+ private readonly _options?;
397
+ readonly element: HTMLElement;
398
+ private readonly _textarea;
399
+ private readonly _measure;
400
+ private readonly _submitButton;
401
+ private readonly _value;
402
+ /** Live, untrimmed textarea content. */
403
+ get value(): IObservable<string>;
404
+ /** The raw textarea, exposed so a host can move focus into it. */
405
+ get inputElement(): HTMLTextAreaElement;
406
+ constructor(_options?: CommentInputWidgetOptions | undefined);
407
+ focus(): void;
408
+ setText(text: string): void;
409
+ clear(): void;
410
+ private _submit;
411
+ private _autoSize;
412
+ }
413
+
414
+ export declare interface CommentInputWidgetOptions {
415
+ /** Placeholder shown while the textarea is empty. Defaults to "Add comment". */
416
+ readonly placeholder?: string;
417
+ /** Called after the textarea changes size. */
418
+ readonly onDidChangeSize?: () => void;
419
+ /**
420
+ * Called when the user submits a non-empty comment (Enter or the add button).
421
+ * The text is trimmed; never called with an empty string.
422
+ */
423
+ readonly onSubmit?: (text: string) => void;
424
+ /** Called when the user dismisses the input (Escape). */
425
+ readonly onCancel?: () => void;
426
+ }
427
+
428
+ /**
429
+ * Comment mode — a compact "add a comment" affordance layered on top of
430
+ * the editor *without modifying it*. It reads the editor's public observables
431
+ * ({@link EditorModel.readonlyMode}, {@link EditorModel.selection}) and the
432
+ * exposed {@link EditorView.caretRect} geometry, and mounts a
433
+ * {@link CommentInputWidget} into {@link EditorView.overlayContainer}.
434
+ *
435
+ * Behaviour:
436
+ * - Only active in read-only mode (the "review" view).
437
+ * - When a user-created selection is non-empty, the input box appears next to
438
+ * the caret (the selection's active end) but does NOT take focus, so keyboard
439
+ * selection keeps working. Programmatic selections such as find matches do
440
+ * not summon it. Press Tab to move focus into the box, then type.
441
+ * - The box appears on mouse-up, not mid-drag, so it doesn't flicker/jump
442
+ * while a selection is being dragged out (keyboard selection shows at once).
443
+ * - While the box has focus or holds a draft it is frozen in place (selection
444
+ * changes, drags and clicks no longer move it). It is dismissed by Escape,
445
+ * by submitting, or by blurring an empty box.
446
+ * - The editor's logical caret geometry remains available for anchoring in
447
+ * read-only mode even though the painted caret is hidden. While the box has
448
+ * focus, `.md-comment-active` also suppresses the painted caret in any mode.
449
+ */
450
+ export declare class CommentModeController extends Disposable {
451
+ private readonly _model;
452
+ private readonly _view;
453
+ private readonly _options?;
454
+ private static _isCommentableSelectionSource;
455
+ private readonly _widget;
456
+ private readonly _gap;
457
+ private _visible;
458
+ private _anchorX;
459
+ private _pinnedRange;
460
+ /**
461
+ * The range a comment was just submitted for. The box stays hidden for it
462
+ * until the selection changes, so submitting doesn't immediately re-summon an
463
+ * empty box on the still-selected text.
464
+ */
465
+ private _submittedRange;
466
+ constructor(_model: EditorModel, _view: EditorView, _options?: CommentModeControllerOptions | undefined);
467
+ private _update;
468
+ private _show;
469
+ private _layoutHorizontally;
470
+ /** Force-hide and clear the box (used by Escape and submit). */
471
+ private _hide;
472
+ /**
473
+ * Hide unless the user is engaged with the box: it has focus or holds a
474
+ * non-empty draft. This preserves in-progress text and keeps a focused box
475
+ * open (it is dismissed explicitly via Escape/submit, or by blurring it).
476
+ */
477
+ private _autoHide;
478
+ private _widgetHasFocus;
479
+ /**
480
+ * The visible viewport (client coords) used for the flip-above decision: the
481
+ * nearest scrollable ancestor of the editor. `.md-editor` itself spans the
482
+ * full document height and never clips, so measuring against it would always
483
+ * report room below. Falls back to the window when nothing scrolls.
484
+ */
485
+ private _getViewportRect;
486
+ private _hideAndRefocus;
487
+ private _submit;
488
+ }
489
+
490
+ export declare interface CommentModeControllerOptions {
491
+ /** Called when the user submits a comment for the current selection. */
492
+ readonly onSubmit?: (submission: CommentSubmission) => void;
493
+ /** Gap (px) between the bottom of the selection and the top of the input box. */
494
+ readonly gap?: number;
495
+ }
496
+
497
+ /**
498
+ * Seedable store of {@link Comment}s for the comment-mode contribution. It has
499
+ * no opinion on rendering or persistence — a host seeds it via
500
+ * {@link set}/{@link add} and observes {@link comments}.
501
+ */
502
+ export declare class CommentsModel {
503
+ private readonly _comments;
504
+ /** Monotonic counter for ids of comments created via {@link create}. */
505
+ private _sequence;
506
+ /** The current comments, in insertion order. */
507
+ get comments(): IObservable<readonly Comment_2[]>;
508
+ /** Replace the whole comment set. */
509
+ set(comments: readonly Comment_2[]): void;
510
+ /**
511
+ * Create a comment from a user submission and append it, generating its `id`
512
+ * and `createdAt` here so id/time allocation stays the store's concern (the
513
+ * UI only supplies the range and text). Returns the created comment.
514
+ */
515
+ create(input: {
516
+ range: OffsetRange;
517
+ body: string;
518
+ author?: string;
519
+ }): Comment_2;
520
+ /** Append a comment. */
521
+ add(comment: Comment_2): void;
522
+ /** Remove a comment by id. */
523
+ remove(id: string): void;
524
+ }
525
+
526
+ /** A comment the user submitted, with the source range it was anchored to. */
527
+ export declare interface CommentSubmission {
528
+ readonly text: string;
529
+ readonly range: OffsetRange;
530
+ }
531
+
532
+ /** Displays posted comments beside their source ranges. */
533
+ export declare class CommentsView extends Disposable {
534
+ private readonly _model;
535
+ private readonly _view;
536
+ private readonly _layer;
537
+ private readonly _entries;
538
+ private _order;
539
+ private _pendingRevealCommentId;
540
+ constructor(_model: CommentsModel, _view: EditorView);
541
+ revealComment(id: string): void;
542
+ private _reconcile;
543
+ private _relayout;
544
+ private _revealPendingComment;
545
+ }
546
+
547
+ /** Compact posted state for a markdown comment. */
548
+ export declare class CommentWidget {
549
+ private readonly _domNode;
550
+ private readonly _disposables;
551
+ get element(): HTMLElement;
552
+ constructor(options: CommentWidgetOptions);
553
+ dispose(): void;
554
+ }
555
+
556
+ export declare interface CommentWidgetOptions {
557
+ /** The posted comment body. */
558
+ readonly body: string;
559
+ /** If provided, shows a delete action and invokes it when activated. */
560
+ readonly onDelete?: () => void;
561
+ }
562
+
563
+ /** The lossless source slices of a complete block HTML comment. */
564
+ declare interface CompleteHtmlCommentSource extends HtmlCommentSourceBase {
565
+ readonly kind: 'complete';
566
+ readonly closing: '-->';
567
+ readonly trailingWhitespace: string;
568
+ }
569
+
570
+ export declare const copyLinesDown: EditCommand;
571
+
572
+ export declare const copyLinesUp: EditCommand;
573
+
241
574
  /**
242
575
  * A {@link MonacoSyntaxHighlighter} preloaded with a handful of common Monarch
243
576
  * grammars (plus the usual short aliases). Unknown languages fall back to an
@@ -248,13 +581,16 @@ export declare class CodeBlockViewNode extends BlockViewNode<CodeBlockViewData>
248
581
  */
249
582
  export declare function createDefaultMonacoSyntaxHighlighter(monaco: IMonarchApi, grammars: IDefaultMonarchGrammars): MonacoSyntaxHighlighter;
250
583
 
251
- export declare type CursorCommand = (ctx: CursorCommandContext) => SourceOffset;
584
+ export declare type CursorCommand = (ctx: CursorCommandContext) => CursorPosition;
252
585
 
253
586
  export declare interface CursorCommandContext {
254
587
  readonly text: string;
255
588
  readonly selection: Selection_2;
256
589
  readonly document: DocumentAstNode;
257
590
  readonly activeBlock: BlockAstNode | undefined;
591
+ readonly markerVisibleBlocks: ReadonlySet<BlockAstNode>;
592
+ readonly wordNavigationConfig: WordNavigationConfig;
593
+ readonly cursorPosition: CursorPosition;
258
594
  }
259
595
 
260
596
  export declare const cursorDocumentEnd: CursorCommand;
@@ -263,6 +599,8 @@ export declare const cursorDocumentStart: CursorCommand;
263
599
 
264
600
  export declare const cursorDown: VisualCursorCommand;
265
601
 
602
+ export declare type CursorKeyboardAction = 'left' | 'right' | 'up' | 'down' | 'wordLeft' | 'wordRight' | 'visualLineStart' | 'visualLineEnd' | 'logicalLineStart' | 'logicalLineEnd' | 'documentStart' | 'documentEnd';
603
+
266
604
  export declare const cursorLeft: CursorCommand;
267
605
 
268
606
  export declare const cursorLineEnd: CursorCommand;
@@ -272,12 +610,26 @@ export declare const cursorLineStart: CursorCommand;
272
610
  export declare const cursorMoveLeft: CursorCommand;
273
611
 
274
612
  export declare interface CursorMoveResult {
275
- readonly offset: SourceOffset;
613
+ readonly position: CursorPosition;
276
614
  readonly desiredColumn: number | undefined;
277
615
  }
278
616
 
279
617
  export declare const cursorMoveRight: CursorCommand;
280
618
 
619
+ /** The cursor's position in either source text or a source-less visual line. */
620
+ export declare type CursorPosition = {
621
+ readonly kind: 'source';
622
+ readonly offset: SourceOffset;
623
+ } | {
624
+ readonly kind: 'virtual';
625
+ readonly line: VirtualCursorLine;
626
+ };
627
+
628
+ export declare namespace CursorPosition {
629
+ export function source(offset: SourceOffset): CursorPosition;
630
+ export function virtual(line: VirtualCursorLine): CursorPosition;
631
+ }
632
+
281
633
  export declare const cursorRight: CursorCommand;
282
634
 
283
635
  export declare const cursorUp: VisualCursorCommand;
@@ -286,42 +638,131 @@ export declare const cursorUp: VisualCursorCommand;
286
638
  * Owns the blinking cursor DOM element.
287
639
  *
288
640
  * The rendering pipeline is a single `derived` whose compute callback
289
- * asks the {@link VisualLineMap} for the caret rect at the current
290
- * offset, writes it to {@link element}, and returns a
641
+ * asks the {@link VisualLineMap} for the caret rect at the current source or
642
+ * virtual position, writes it to {@link element}, and returns a
291
643
  * {@link CursorViewRendering} value as proof. An autorun keeps the
292
644
  * derived subscribed.
293
645
  */
294
646
  export declare class CursorView extends Disposable {
295
- private readonly _parent;
296
647
  readonly element: HTMLElement;
297
648
  readonly rendering: IObservable<CursorViewRendering>;
298
- constructor(_parent: HTMLElement, options: CursorViewOptions);
649
+ constructor(options: CursorViewOptions);
299
650
  }
300
651
 
301
652
  export declare interface CursorViewOptions {
302
- readonly offset: IObservable<SourceOffset | undefined>;
653
+ readonly position: IObservable<CursorPosition | undefined>;
303
654
  readonly visualLineMap: IObservable<VisualLineMap>;
655
+ /**
656
+ * The mounted blocks, used to hide the caret when it sits at an offset that
657
+ * has been scrolled out of its (horizontally scrolling) block's viewport —
658
+ * matching how the selection is clipped there.
659
+ */
660
+ readonly blocks?: IObservable<readonly SelectionBlock[]>;
304
661
  }
305
662
 
306
663
  export declare class CursorViewRendering {
307
- readonly offset: SourceOffset;
664
+ readonly position: CursorPosition;
308
665
  readonly visible: boolean;
309
666
  readonly rect: Rect2D;
310
- constructor(offset: SourceOffset, visible: boolean, rect: Rect2D);
667
+ constructor(position: CursorPosition, visible: boolean, rect: Rect2D);
311
668
  }
312
669
 
670
+ export declare const cursorVisualLineEnd: VisualCursorCommand;
671
+
672
+ export declare const cursorVisualLineStart: VisualCursorCommand;
673
+
313
674
  export declare const cursorWordLeft: CursorCommand;
314
675
 
315
676
  export declare const cursorWordRight: CursorCommand;
316
677
 
678
+ export declare const DEFAULT_INDENTATION_CONFIG: IndentationConfig;
679
+
680
+ export declare const DEFAULT_WORD_NAVIGATION_CONFIG: WordNavigationConfig;
681
+
682
+ export declare const DEFAULT_WORD_SEPARATORS = "`~!@#$%^&*()-=+[{]}\\|;:'\",.<>/?";
683
+
317
684
  export declare const deleteLeft: EditCommand;
318
685
 
686
+ export declare const deleteLineLeft: EditCommand;
687
+
688
+ export declare const deleteLineRight: EditCommand;
689
+
690
+ export declare const deleteLines: EditCommand;
691
+
319
692
  export declare const deleteRight: EditCommand;
320
693
 
321
694
  export declare const deleteWordLeft: EditCommand;
322
695
 
323
696
  export declare const deleteWordRight: EditCommand;
324
697
 
698
+ /**
699
+ * A read-only "removed" decoration: an original block rendered (red) above its
700
+ * place in the modified document, occupying vertical space like a view-zone but
701
+ * contributing **zero** source length, so the editor's source mapping stays the
702
+ * modified document and editing is unaffected. Used for `removed` and the
703
+ * original side of a `replaced` block in editor diff mode.
704
+ */
705
+ declare class DiffDecorationViewData {
706
+ readonly ast: AstNode;
707
+ readonly side: BlockViewData;
708
+ readonly deletedRanges: readonly DiffHighlightRange[];
709
+ /** True when the whole block was removed: solid red band, no word rects. */
710
+ readonly whole: boolean;
711
+ /** Absolute offset of this block in the *original* document. */
712
+ readonly originalStart: number;
713
+ readonly kind = "diffDecoration";
714
+ constructor(ast: AstNode, side: BlockViewData, deletedRanges: readonly DiffHighlightRange[],
715
+ /** True when the whole block was removed: solid red band, no word rects. */
716
+ whole: boolean,
717
+ /** Absolute offset of this block in the *original* document. */
718
+ originalStart: number);
719
+ }
720
+
721
+ /** A word/character highlight inside one diff side, in block-local coords. */
722
+ declare interface DiffHighlightRange {
723
+ readonly range: OffsetRange;
724
+ readonly kind: 'inserted' | 'deleted';
725
+ }
726
+
727
+ /**
728
+ * A changed block rendered as its original form stacked over its modified form
729
+ * (either side may be absent for a pure deletion/insertion). It is itself a
730
+ * document child the renderer mounts like a block; its {@link ast} is the
731
+ * surviving side's ast, used only for view-node identity/reuse.
732
+ */
733
+ declare class DiffHunkViewData {
734
+ readonly ast: AstNode;
735
+ readonly original: DiffSideViewData | undefined;
736
+ readonly modified: DiffSideViewData | undefined;
737
+ readonly kind = "diffHunk";
738
+ constructor(ast: AstNode, original: DiffSideViewData | undefined, modified: DiffSideViewData | undefined);
739
+ }
740
+
741
+ /**
742
+ * The recursive classification of a diff. Each item describes one aligned
743
+ * position in the merged document:
744
+ *
745
+ * - `unchanged` — render the (modified) node once, neutral.
746
+ * - `added` — exists only in the modified document (green).
747
+ * - `removed` — exists only in the original document (red).
748
+ * - `replaced` — a *leaf* block changed in place → render original over
749
+ * modified, with word-level {@link AnnotatedRange}s on each.
750
+ * - `nested` — a *container* changed → render it once and diff its
751
+ * {@link NestedItem.children} recursively.
752
+ *
753
+ * Offsets ({@link UnchangedItem.modifiedStart} etc.) are absolute in their
754
+ * respective documents, so a renderer/visualizer can slice the source text.
755
+ */
756
+ declare type DiffItem = UnchangedItem | AddedItem | RemovedItem | ReplacedItem | NestedItem;
757
+
758
+ /** One side (original or modified) of a {@link DiffHunkViewData}. */
759
+ declare interface DiffSideViewData {
760
+ readonly view: BlockViewData;
761
+ /** Render in active form (markers/whitespace visible). */
762
+ readonly active: boolean;
763
+ readonly ranges: readonly DiffHighlightRange[];
764
+ }
765
+
325
766
  export declare class DocumentAstNode extends AstNode {
326
767
  readonly content: readonly (BlockAstNode | GlueAstNode)[];
327
768
  readonly kind = "document";
@@ -346,13 +787,21 @@ declare interface DocumentBlockViewData {
346
787
  readonly view: BlockViewData;
347
788
  }
348
789
 
349
- /** A mounted document child: a block or a run of inter-block glue. */
790
+ /** A mounted document child: a block, a run of inter-block glue, the
791
+ * transient empty paragraph (see {@link PendingParagraphViewData}), or a
792
+ * {@link DiffHunkViewData diff hunk} (stacked original/modified blocks). */
350
793
  declare interface DocumentChildViewData {
351
794
  readonly absoluteStart: number;
352
- /** For a block: selection reaches it. For glue: a neighbouring block is active. */
795
+ /** For a block: selection reaches it. For glue: always false (unowned, hidden). */
353
796
  readonly isActive: boolean;
354
- readonly view: BlockViewData | GlueViewData;
355
- readonly kind: 'block' | 'glue';
797
+ readonly view: BlockViewData | GlueViewData | PendingParagraphViewData | DiffHunkViewData | DiffDecorationViewData;
798
+ readonly kind: 'block' | 'glue' | 'pendingParagraph' | 'diffHunk' | 'diffDecoration';
799
+ /**
800
+ * Diff mode: how this (modified) block changed. `added` = a whole new block
801
+ * (strong green band, no inline rects); `modified` = a partial change (light
802
+ * band + inline rects on the changed words).
803
+ */
804
+ readonly diffKind?: 'added' | 'modified';
356
805
  }
357
806
 
358
807
  /**
@@ -408,6 +857,8 @@ declare class DocumentViewData {
408
857
  */
409
858
  export declare class DocumentViewNode extends ViewNode {
410
859
  readonly blocks: readonly DocumentBlock[];
860
+ /** The transient empty-paragraph element, when one is armed. */
861
+ readonly pendingParagraph?: PendingParagraphViewNode | undefined;
411
862
  static create(viewData: DocumentViewData, options: BlockViewOptions | undefined, previous: DocumentViewNode | undefined): DocumentViewNode;
412
863
  private constructor();
413
864
  /** The stable content element this document mounts its children into. */
@@ -429,6 +880,26 @@ export declare type EditCommand = (ctx: CursorCommandContext) => {
429
880
  readonly selection: Selection_2;
430
881
  } | undefined;
431
882
 
883
+ export declare type EditKeyboardAction = 'deleteLeft' | 'deleteRight' | 'deleteWordLeft' | 'deleteWordRight' | 'deleteLineLeft' | 'deleteLineRight' | 'copyLinesUp' | 'copyLinesDown' | 'moveLinesUp' | 'moveLinesDown' | 'deleteLines' | 'joinLines';
884
+
885
+ export declare interface EditorCommandDefinition {
886
+ readonly id: `markdown.editor.${string}`;
887
+ readonly title: string;
888
+ readonly action: EditorKeyboardAction;
889
+ readonly keybindings: readonly EditorCommandKeybinding[];
890
+ /**
891
+ * Local commands must execute synchronously in the webview instead of being
892
+ * forwarded through the VS Code keybinding service.
893
+ */
894
+ readonly routing?: 'host' | 'local';
895
+ }
896
+
897
+ export declare interface EditorCommandKeybinding {
898
+ readonly key: string;
899
+ readonly modifiers?: KeyboardModifiers;
900
+ readonly platforms?: readonly KeyboardPlatform[];
901
+ }
902
+
432
903
  /**
433
904
  * Translates raw browser input (mouse, keyboard, EditContext) into model
434
905
  * mutations. Knows about DOM event types but never reads/writes the DOM
@@ -437,32 +908,165 @@ export declare type EditCommand = (ctx: CursorCommandContext) => {
437
908
  *
438
909
  * Owns the only non-derivable controller state:
439
910
  * - `_desiredColumn` — sticky column for up/down navigation
911
+ * - `_clickCount` / `_lastPointerDown` — multi-click detection for pointer
912
+ * input, since `pointerdown` events (unlike `mousedown`) don't populate
913
+ * `detail` with a click count.
440
914
  */
441
915
  export declare class EditorController extends Disposable {
442
916
  private readonly _model;
443
917
  private readonly _view;
918
+ readonly findController: FindController | undefined;
444
919
  private _desiredColumn;
445
- constructor(_model: EditorModel, _view: EditorView);
920
+ private readonly _keyboardPlatform;
921
+ private readonly _keyboardProfile;
922
+ private readonly _forwardedKeyboardProfile;
923
+ private readonly _historyStrategy;
924
+ private readonly _indentation;
925
+ private readonly _tabFocusStatus;
926
+ private _tabMovesFocus;
927
+ /** Indentation copied by the most recent fenced-code Enter, while still untouched. */
928
+ private _generatedIndentation;
929
+ /** Running click count for the current multi-click sequence (1, 2, 3, …). */
930
+ private _clickCount;
931
+ /** Timestamp and position of the previous pointer-down, for multi-click detection. */
932
+ private _lastPointerDown;
933
+ constructor(_model: EditorModel, _view: EditorView, options?: EditorControllerOptions);
446
934
  private readonly _handleTextUpdate;
447
- private readonly _handleMouseDown;
935
+ private _insertText;
936
+ private _remainingGeneratedIndentation;
937
+ /** Handle typed, pasted, or command-generated text while a paragraph is pending. */
938
+ private _handlePendingInput;
939
+ private _deletePendingText;
940
+ private readonly _handlePointerDown;
448
941
  private _makeCursorContext;
449
942
  private _makeVisualCursorContext;
450
943
  private _executeCursorCommand;
451
944
  private _executeEditCommand;
945
+ private _runUndoableEdit;
452
946
  private _executeVisualCursorCommand;
947
+ private _cursorDown;
948
+ private _setUserSelection;
949
+ private _applyCursorPosition;
453
950
  /** Move the cursor down one visual line (Arrow Down). */
454
951
  cursorDown(extend?: boolean): void;
455
952
  /** Move the cursor up one visual line (Arrow Up). */
456
953
  cursorUp(extend?: boolean): void;
457
- private readonly _handleCopy;
458
- private readonly _handleCut;
459
- private readonly _handlePaste;
460
954
  private _selectedText;
955
+ private readonly _updateModifierState;
956
+ private readonly _clearModifierState;
957
+ /**
958
+ * Drop any native DOM selection over the rendered text.
959
+ *
960
+ * The editor paints selection from `model.selection`, so a browser
961
+ * selection there is always spurious: nothing reads it (copy/cut read the
962
+ * model, hit-testing uses the measured layout) and nothing clears it, so it
963
+ * lingers as a second highlight even after the caret moves away.
964
+ * {@link isCaretMotionKey} stops the common source synchronously; this is
965
+ * the backstop for the rest of the browser's editing commands, which are
966
+ * platform- and version-specific and cannot be enumerated (Shift+PageDown
967
+ * and macOS Shift+Ctrl+B both reach one today).
968
+ *
969
+ * Scoped twice so it only ever discards selections the editor owns: the
970
+ * range must touch the rendered text (overlays such as comment widgets sit
971
+ * beside it and stay selectable), and input focus must still be inside this
972
+ * editor (so a host find-in-page, which selects while its own input is
973
+ * focused, is left alone).
974
+ */
975
+ private readonly _discardNativeSelection;
461
976
  private readonly _handleKeyDown;
977
+ executeCommand(command: EditorCommandDefinition): void;
978
+ private _executeKeyboardAction;
979
+ /**
980
+ * Context-aware Enter: splits / line-breaks via {@link insertSmartEnter}, or
981
+ * arms a transient empty paragraph when at the end of a paragraph.
982
+ */
983
+ private _smartEnter;
984
+ private _registerTabFocusAccessibility;
985
+ }
986
+
987
+ /** Options for an {@link EditorController}. */
988
+ export declare interface EditorControllerOptions {
989
+ /**
990
+ * How copy/cut/paste is handled. Defaults to {@link NativeClipboardStrategy},
991
+ * which reads the browser's native clipboard events — pass a different
992
+ * strategy (e.g. `AsyncClipboardStrategy`) in hosts that swallow them.
993
+ */
994
+ readonly clipboardStrategy?: IClipboardStrategy;
995
+ /**
996
+ * Where undo and redo are executed: `LocalHistoryStrategy` for a
997
+ * self-contained editor, or a strategy that forwards to the host's own
998
+ * document history. Left unset, the chords are passed on to the host.
999
+ */
1000
+ readonly historyStrategy?: IHistoryStrategy;
1001
+ readonly keyboardPlatform?: KeyboardPlatform;
1002
+ readonly keyboardProfile?: KeyboardProfile;
1003
+ /**
1004
+ * Bindings owned by the host. Matching events have their browser default
1005
+ * suppressed but continue propagating so the host keybinding service sees them.
1006
+ */
1007
+ readonly forwardedKeyboardProfile?: KeyboardProfile;
1008
+ /** Tab-stop settings used outside semantic list indentation. */
1009
+ readonly indentation?: IndentationConfig;
1010
+ readonly find?: false;
462
1011
  }
463
1012
 
1013
+ /**
1014
+ * The editor overlay's local CSS-pixel coordinate space.
1015
+ *
1016
+ * Browser geometry and pointer APIs expose viewport client coordinates. This
1017
+ * boundary converts them immediately into the coordinate system shared by the
1018
+ * editor content and its overlays. Range rectangles are axis-aligned, so the
1019
+ * current implementation deliberately supports positive axis-aligned scale and
1020
+ * translation only.
1021
+ */
1022
+ export declare class EditorCoordinateSpace {
1023
+ private readonly _getLocalToClientMatrix;
1024
+ static forSvgOverlay(overlay: SVGSVGElement): EditorCoordinateSpace;
1025
+ private constructor();
1026
+ capture(): EditorCoordinateTransform;
1027
+ }
1028
+
1029
+ /** A stable coordinate conversion captured for one measurement operation. */
1030
+ export declare class EditorCoordinateTransform {
1031
+ private readonly _localToClient;
1032
+ private readonly _clientToLocal;
1033
+ constructor(_localToClient: DOMMatrix);
1034
+ toLocalPoint(point: Pick<Point2D, 'x' | 'y'>): Point2D;
1035
+ toClientPoint(point: Pick<Point2D, 'x' | 'y'>): Point2D;
1036
+ toLocalRect(rect: Pick<DOMRectReadOnly, 'left' | 'top' | 'width' | 'height'>): Rect2D;
1037
+ toClientRect(rect: Pick<Rect2D, 'left' | 'top' | 'width' | 'height'>): Rect2D;
1038
+ private _convertRect;
1039
+ }
1040
+
1041
+ export declare type EditorKeyboardAction = {
1042
+ readonly kind: 'cursor';
1043
+ readonly command: CursorKeyboardAction;
1044
+ readonly extend: boolean;
1045
+ } | {
1046
+ readonly kind: 'edit';
1047
+ readonly command: EditKeyboardAction;
1048
+ } | {
1049
+ readonly kind: 'history';
1050
+ readonly command: HistoryKeyboardAction;
1051
+ } | {
1052
+ readonly kind: 'tab';
1053
+ readonly command: TabKeyboardAction;
1054
+ } | {
1055
+ readonly kind: 'toggleTabFocus';
1056
+ } | {
1057
+ readonly kind: 'toggleReadonly';
1058
+ } | {
1059
+ readonly kind: 'selectAll';
1060
+ } | {
1061
+ readonly kind: 'enter';
1062
+ readonly command: 'smartEnter' | 'insertParagraph' | 'insertHardLineBreak';
1063
+ };
1064
+
464
1065
  export declare class EditorModel {
465
1066
  private readonly _parser;
1067
+ private readonly _sourceEditListeners;
1068
+ private readonly _sourceTextIds;
1069
+ private _lastSourceTextId;
466
1070
  /**
467
1071
  * The most recent edit applied to {@link sourceText}, used by
468
1072
  * {@link document} to let the parser link incrementally edited code
@@ -471,11 +1075,46 @@ export declare class EditorModel {
471
1075
  */
472
1076
  private _pendingEdit;
473
1077
  readonly sourceText: ISettableObservable<StringValue, void>;
1078
+ readonly wordNavigationConfig: ISettableObservable<WordNavigationConfig, void>;
1079
+ /**
1080
+ * Read-only mode. When `true`, the editor never reveals a block's source
1081
+ * markers (markdown special characters like `**`, `#`, list bullets, code
1082
+ * fences, `$…$`) — every block stays in its clean rendered form regardless of
1083
+ * where the caret/selection is — and text-editing commands are ignored.
1084
+ * Explicit interactions with rendered controls, such as task checkboxes,
1085
+ * remain available. Plain text selection still works everywhere (so the user
1086
+ * can copy). The default (`false`) is the normal editing mode where the active
1087
+ * block reveals its markers.
1088
+ */
1089
+ readonly readonlyMode: ISettableObservable<boolean, void>;
474
1090
  /**
475
1091
  * The current selection, or `undefined` when the editor has no caret
476
1092
  * (e.g. an inactive/unfocused rendering).
477
1093
  */
478
1094
  readonly selection: ISettableObservable<Selection_2 | undefined, void>;
1095
+ readonly selectionSource: ISettableObservable<SelectionSource, void>;
1096
+ /**
1097
+ * Whether a Ctrl/Cmd modifier is currently held. Set by the controller from
1098
+ * live keyboard state; the view reads it to show the link-open affordance
1099
+ * (underline + pointer cursor) only while a Ctrl/Cmd+click would open a link
1100
+ * whose block is active.
1101
+ */
1102
+ readonly ctrlOrMetaDown: ISettableObservable<boolean, void>;
1103
+ /**
1104
+ * Whether a pointer-driven selection drag is currently in progress. Set by
1105
+ * the controller between the pointer-down that starts the drag and the
1106
+ * pointer-up/cancel that ends it. Contributions read it to defer UI that
1107
+ * would otherwise flicker mid-drag (e.g. the comment input box appears only
1108
+ * once the drag ends).
1109
+ */
1110
+ readonly isSelecting: ISettableObservable<boolean, void>;
1111
+ /**
1112
+ * Gutter markers (source-control style change indicators) painted in the
1113
+ * left gutter. Each entry maps a source {@link OffsetRange} to a change kind
1114
+ * — see {@link GutterMarker}. Purely decorative: markers never affect the
1115
+ * parsed {@link document}, selection, or layout. Empty by default.
1116
+ */
1117
+ readonly gutterMarkers: ISettableObservable<readonly GutterMarker[], void>;
479
1118
  /**
480
1119
  * Forces the rendered active-block set. `undefined` (the default)
481
1120
  * derives the set from the current selection range (see
@@ -484,13 +1123,23 @@ export declare class EditorModel {
484
1123
  * collapsed/inactive rendering.
485
1124
  */
486
1125
  readonly activeBlocksOverride: ISettableObservable<readonly BlockAstNode[] | typeof NO_ACTIVE_BLOCKS | undefined, void>;
1126
+ /**
1127
+ * The transient empty-paragraph editing state, or `undefined` when none is
1128
+ * armed. See {@link PendingParagraph}. This is *not* document data — it is
1129
+ * cleared by any source edit and lives only between the Enter that armed it
1130
+ * and the next content-producing edit.
1131
+ */
1132
+ readonly pendingParagraph: ISettableObservable<PendingParagraph | undefined, void>;
1133
+ /** Switches between editing and locked mode and clears transient edit intent. */
1134
+ toggleReadonlyMode(): void;
487
1135
  readonly cursorOffset: IObservableWithChange<number | undefined, void>;
1136
+ readonly cursorPosition: IObservableWithChange<CursorPosition | undefined, void>;
488
1137
  /**
489
1138
  * The parsed document. Threads the previous document into the parser so
490
1139
  * unchanged blocks keep their object identity across reparses (see
491
1140
  * {@link MarkdownParser.parse}). Writing `previous` inside the compute is
492
- * a safe optimization: `derived` only recomputes when `sourceText`
493
- * changes, and the result is structurally identical to a full reparse.
1141
+ * safe: unchanged source reuses it directly, while changed source produces
1142
+ * a result structurally identical to a full reparse.
494
1143
  */
495
1144
  readonly document: IObservableWithChange<DocumentAstNode, void>;
496
1145
  /**
@@ -507,10 +1156,62 @@ export declare class EditorModel {
507
1156
  * collapsed this is a one-element set holding {@link activeBlock}.
508
1157
  */
509
1158
  readonly activeBlocks: IObservableWithChange<Set<BlockAstNode>, void>;
510
- applyEdit(edit: StringEdit): void;
1159
+ /**
1160
+ * The baseline document to diff against. When set, the editor renders in
1161
+ * diff mode: the modified document ({@link document}) stays editable, while
1162
+ * the baseline's removed/changed blocks are shown as read-only decorations.
1163
+ * `undefined` (the default) renders normally.
1164
+ */
1165
+ readonly baseline: ISettableObservable<StringValue | undefined, void>;
1166
+ private readonly _baselineDocument;
1167
+ /**
1168
+ * The diff of {@link baseline} → {@link document}, or `undefined` when no
1169
+ * baseline is set. The view renders the {@link DiffItem}s as stacked
1170
+ * decorations; `insertedRanges` (modified-side change spans) drive the green
1171
+ * word-level highlight.
1172
+ */
1173
+ readonly diff: IObservableWithChange< {
1174
+ items: DiffItem[];
1175
+ insertedRanges: OffsetRange[];
1176
+ changedBlocks: Set<BlockAstNode>;
1177
+ } | undefined, void>;
1178
+ readonly markerVisibleBlocks: IObservableWithChange<Set<BlockAstNode>, void>;
1179
+ onWillApplySourceEdit(listener: (event: SourceEditEvent) => void): IDisposable;
1180
+ /** Returns a stable per-object identity without retaining the source text. */
1181
+ getSourceTextId(sourceText: StringValue): number;
1182
+ /**
1183
+ * Arm a {@link PendingParagraph} at the given gap, minting a fresh synthetic
1184
+ * AST node for it, and park the caret at the gap start. No source edit is
1185
+ * applied — the blank line exists only in the view until it is materialized.
1186
+ */
1187
+ armPendingParagraph(req: Omit<PendingParagraph, 'syntheticAst' | 'cursorLine' | 'text'>): void;
1188
+ /** Discard the pending paragraph (if any) without touching the source. */
1189
+ cancelPendingParagraph(): void;
1190
+ /**
1191
+ * Replace the source with an authoritative value from the host, mapping the
1192
+ * selection through the changed span and atomically discarding transient
1193
+ * state anchored to the previous parse.
1194
+ */
1195
+ replaceSourceText(text: StringValue): void;
1196
+ /** Replace the transient horizontal whitespace on the pending line. */
1197
+ setPendingParagraphText(text: string): void;
1198
+ /**
1199
+ * Turn the pending paragraph into real source: rewrite its gap so the typed
1200
+ * text, including any transient indentation, is separated from its neighbours
1201
+ * by blank lines, and place the caret after it.
1202
+ */
1203
+ materializePendingParagraph(text: string): void;
1204
+ /** Sets a rendered task checkbox state in either editing or read-only mode. */
1205
+ setTaskCheckboxChecked(item: ListItemAstNode, checked: boolean): void;
1206
+ applyEdit(edit: StringEdit, selection?: Selection_2): void;
511
1207
  applyEditForSelection(edit: StringEdit): void;
1208
+ private _applySourceEdit;
1209
+ private _identifySourceEdit;
1210
+ private _emitWillApplySourceEdit;
512
1211
  }
513
1212
 
1213
+ export declare type EditorOverlayPosition = 'top-chrome' | 'below-selection' | 'above-decorations';
1214
+
514
1215
  /**
515
1216
  * Pure-render view of an {@link EditorModel}.
516
1217
  *
@@ -540,8 +1241,27 @@ export declare class EditorView extends Disposable {
540
1241
  readonly element: HTMLElement;
541
1242
  readonly editContext: EditContext;
542
1243
  readonly measuredLayout: MeasuredLayoutModel;
1244
+ readonly coordinateSpace: EditorCoordinateSpace;
1245
+ readonly forcedMarkerVisibleBlocks: ISettableObservable<ReadonlySet<BlockAstNode>, void>;
1246
+ /**
1247
+ * Inner container that holds the rendered document and the cursor/selection
1248
+ * overlays. The outer {@link element} spans the full width; this container
1249
+ * is what limited-width mode caps and centers, so the overlays (which anchor
1250
+ * to their parent's box) stay aligned with the content.
1251
+ */
1252
+ private readonly _contentContainer;
1253
+ private readonly _resizeObserver;
543
1254
  private readonly _cursorView;
544
1255
  private readonly _selectionView;
1256
+ private readonly _gutterMarkersView;
1257
+ private readonly _diffHighlightsView;
1258
+ private _readonlyToggleButton;
1259
+ private readonly _editContextSuspensions;
1260
+ private readonly _revealOcclusions;
1261
+ private _pendingTopReveal;
1262
+ private _caretRevealRaf;
1263
+ private _followedCaretBlock;
1264
+ private _followCaretAfterEdit;
545
1265
  /**
546
1266
  * The mounted block sequence, in source order. Rebuilt (not mutated) each
547
1267
  * frame by {@link DocumentViewNode.create}; the view just swaps one
@@ -549,8 +1269,11 @@ export declare class EditorView extends Disposable {
549
1269
  * (those go through the measured-layout model).
550
1270
  */
551
1271
  private readonly _document;
1272
+ private readonly _embeddedCodeEditorFactoryVersion;
552
1273
  /** The current view-node tree (AST overlaid with rendered DOM), for debugging. */
553
1274
  get documentViewNode(): IObservable<DocumentViewNode | undefined>;
1275
+ /** Re-resolves embedded code editors while preserving the surrounding editor view. */
1276
+ refreshEmbeddedCodeEditors(): void;
554
1277
  /**
555
1278
  * Last frame's view-data overlay, threaded back into
556
1279
  * {@link buildDocumentViewData} so any subtree whose ast and selection flags
@@ -561,20 +1284,169 @@ export declare class EditorView extends Disposable {
561
1284
  /** The current view-data tree (AST overlaid with selection flags), for debugging. */
562
1285
  private readonly _viewData;
563
1286
  get viewData(): IObservable<DocumentViewData | undefined>;
1287
+ /**
1288
+ * Whether the editor is genuinely focused: focus rests somewhere inside the
1289
+ * editor subtree *and* its window is focused. Mirrored onto the root as
1290
+ * `.md-focused`, which gates the painted caret — the blinking cursor is only
1291
+ * shown while this is `true`, so it never blinks in an unfocused editor or
1292
+ * after the window loses focus. Only the caret's visibility is affected; the
1293
+ * logical selection and caret geometry ({@link caretRect}) are unchanged.
1294
+ */
1295
+ private readonly _focused;
1296
+ get focused(): IObservable<boolean>;
564
1297
  /**
565
1298
  * The block cache projected for views (selection painting) that need to
566
1299
  * react to mount/unmount. Derived from {@link _document}, so it stays in
567
1300
  * lock-step without any manual bookkeeping.
568
1301
  */
569
1302
  private readonly _selectionBlocksObs;
1303
+ /**
1304
+ * The caret rect (zero width) at the selection's active end, in
1305
+ * {@link overlayContainer}-local coordinates, or `undefined` when there is no
1306
+ * caret. This is the same geometry the editor paints its cursor from, so
1307
+ * contributions (e.g. comment mode) can anchor an overlay to the active end of
1308
+ * the selection — where the user's cursor is — without re-deriving geometry.
1309
+ */
1310
+ private readonly _caretRect;
1311
+ get caretRect(): IObservable<Rect2D | undefined>;
1312
+ /**
1313
+ * The container that establishes the positioning context for the editor's
1314
+ * overlays (cursor, selection, gutter). Contributions mount their own
1315
+ * absolutely-positioned overlays here so they share the coordinate space of
1316
+ * {@link caretRect}.
1317
+ */
1318
+ get overlayContainer(): HTMLElement;
1319
+ /**
1320
+ * Selection-style rectangles covering `range`, in {@link overlayContainer}-
1321
+ * local coordinates — the same geometry the live selection paints. Exposed so
1322
+ * contributions (e.g. persistent comments) can highlight arbitrary ranges and
1323
+ * anchor overlays to them. Recomputes when the measured layout changes.
1324
+ */
1325
+ rangeRects(range: OffsetRange): IObservable<readonly SelectionRect[]>;
570
1326
  constructor(_model: EditorModel, _options?: EditorViewOptions | undefined);
1327
+ /**
1328
+ * Mirrors the model's live Ctrl/Cmd state onto the editor root as
1329
+ * `.md-mod-down` so CSS can show the link-open underline and pointer cursor
1330
+ * only while a click would actually open the link: an inactive link opens on
1331
+ * a plain click, but an active link only opens with the modifier held.
1332
+ */
1333
+ private _setupModifierTracking;
1334
+ /**
1335
+ * Tracks whether the editor is genuinely focused and mirrors it onto the
1336
+ * root as `.md-focused` so CSS can gate the painted caret. "Focused" means
1337
+ * focus rests somewhere inside the editor subtree *and* the window itself is
1338
+ * focused; either condition failing (focus moving elsewhere, or the window
1339
+ * losing focus) hides the blinking caret while leaving the logical selection
1340
+ * and caret geometry intact.
1341
+ */
1342
+ private _setupFocusTracking;
1343
+ private _setupCaretScrollPadding;
1344
+ /**
1345
+ * Renders the edit/read-only mode toggle. It flips the model's
1346
+ * {@link EditorModel.readonlyMode}: when locked (read-only) every block stays
1347
+ * in its clean rendered form (no markdown markers revealed) and edits are
1348
+ * ignored, while text selection still works. The control lives in a
1349
+ * zero-height *sticky* host inside the centered content container, so the
1350
+ * lock follows the content's right edge and remains pinned as the document
1351
+ * scrolls. The current mode is also mirrored onto the root as `.md-readonly`
1352
+ * for any CSS hooks.
1353
+ */
1354
+ private _setupReadonlyToggle;
1355
+ /** Draws attention to the mode toggle after text input is attempted while locked. */
1356
+ showReadonlyEditingAttempt(): void;
571
1357
  focus(): void;
1358
+ mountOverlay(element: HTMLElement | SVGSVGElement, position: EditorOverlayPosition): IDisposable;
1359
+ /** Registers floating editor chrome that should count as covering a range during reveal. */
1360
+ registerRevealOcclusion(element: Element): IDisposable;
1361
+ /**
1362
+ * Temporarily detaches the root {@link EditContext} while focus is inside
1363
+ * nested editor chrome. Chromium otherwise reclaims focus from non-text
1364
+ * controls inside the EditContext host, breaking keyboard access to controls
1365
+ * such as the find actions and read-only toggle.
1366
+ */
1367
+ suspendEditContextWhileFocused(element: HTMLElement): IDisposable;
1368
+ revealRangeInCenterIfOutsideViewport(range: OffsetRange, behavior?: ScrollBehavior): IDisposable;
1369
+ /**
1370
+ * Aligns an explicitly navigated range with the top of its nearest vertical
1371
+ * scroll viewport, even when the range is already partially or fully visible.
1372
+ * The alignment leaves {@link TOP_REVEAL_CONTEXT_INSET}px of navigation
1373
+ * context above the range, grown so the range also clears any chrome
1374
+ * registered through {@link registerRevealOcclusion} that covers the top of
1375
+ * that viewport. Outer vertical scrollers and the window keep nearest-edge
1376
+ * behavior so they do not jump, and horizontal scrolling stays nearest-edge.
1377
+ *
1378
+ * Explicit navigation also stops edit-driven caret following, so a later
1379
+ * block resize does not scroll back to where the caret was left behind.
1380
+ * Sticky chrome is remeasured once scrolling completes. User input, a newer
1381
+ * reveal, or disposal cancels that deferred correction.
1382
+ */
1383
+ revealRangeAtTop(range: OffsetRange, behavior?: ScrollBehavior): IDisposable;
1384
+ private _scheduleRangeReveal;
1385
+ private _scheduleTopRangeReveal;
1386
+ /**
1387
+ * Keeps the caret visible after an editor-driven text edit. The reveal is
1388
+ * deferred until the rebuilt document has been laid out and uses nearest-edge
1389
+ * scrolling so ordinary typing only moves the containing viewport as far as
1390
+ * needed. While this mode is active, a later resize of the same active block
1391
+ * also re-reveals the caret (for asynchronous code, math, or diagram layout).
1392
+ */
1393
+ revealCaretAfterEdit(): void;
1394
+ /** Keeps a keyboard-moved caret visible without enabling edit-resize following. */
1395
+ revealCaretAfterKeyboardNavigation(): void;
1396
+ /** Stops edit-driven caret following before pointer-based selection begins. */
1397
+ stopFollowingCaret(): void;
1398
+ /**
1399
+ * Samples the ambient focus state that decides whether taking focus on open
1400
+ * would steal it from an explicit user target: whether the window is focused
1401
+ * and whether focus is still unclaimed (no active element, or the `<body>`
1402
+ * fallback).
1403
+ */
1404
+ private _sampleAutoFocusEnvironment;
1405
+ /**
1406
+ * One-shot guarded focus attempt: focuses the editor only if doing so will
1407
+ * not steal focus from an explicit user target — the window must already be
1408
+ * focused and no other element may have claimed focus yet. Returns whether
1409
+ * focus was taken. A no-op for a background window or when the user has
1410
+ * already focused something else. {@link autoFocusOnOpen} builds the
1411
+ * open-time behavior on top of this primitive.
1412
+ */
1413
+ tryAutoFocus(): boolean;
1414
+ /**
1415
+ * Focuses the editor when it opens without ever stealing focus from an
1416
+ * explicit user target. Tries once immediately; if the window is not focused
1417
+ * yet — a common open-time race where the editor is mounted before the host
1418
+ * routes focus to its window — the guarded attempt is deferred to the next
1419
+ * time the window gains focus and re-evaluated then. The deferral is
1420
+ * one-shot, so a later, unrelated window refocus never grabs focus, and the
1421
+ * re-check still respects any target the user has claimed in the meantime.
1422
+ */
1423
+ autoFocusOnOpen(): void;
1424
+ /**
1425
+ * Own point→offset resolution. When `true` (the default),
1426
+ * {@link resolveOffsetFromPoint} ignores the platform DOM hit-test
1427
+ * (`caretPositionFromPoint`) and snaps the point to the nearest offset purely
1428
+ * from the rendered {@link VisualLineMap} geometry — picking the nearest
1429
+ * visual line by `y`, then the nearest offset on it by `x`. Because a table
1430
+ * row's cells share one horizontal line band, this makes the whole width of a
1431
+ * row resolve into that row (rather than only the cell boxes), with no visible
1432
+ * layout change. It also lets a drag keep extending toward off-viewport points
1433
+ * (e.g. the pointer leaving the window), which the platform hit-test cannot
1434
+ * resolve. Set to `false` to fall back to the platform DOM hit-test.
1435
+ */
1436
+ readonly geometricHitTest: ISettableObservable<boolean, void>;
572
1437
  /**
573
1438
  * Client coordinates → absolute source offset (any block). Used during
574
1439
  * drag to keep extending the selection even when the pointer leaves the
575
- * original block.
1440
+ * original block. Honours {@link geometricHitTest}.
576
1441
  */
577
1442
  resolveOffsetFromPoint(point: Point2D): SourceOffset | undefined;
1443
+ /**
1444
+ * Resolve table-cell hits that have no measurable text run. Empty cells map
1445
+ * from their own box instead of snapping to a neighboring cell; element-only
1446
+ * content (for example an inactive image) maps through the hit element's view
1447
+ * node. Text-bearing cells keep the normal pixel-precise line-map/DOM path.
1448
+ */
1449
+ private _resolveTableCellOffset;
578
1450
  /**
579
1451
  * Whether a client point falls on the rendered document content, as
580
1452
  * opposed to the surrounding editor padding (the green area). Uses DOM
@@ -584,6 +1456,14 @@ export declare class EditorView extends Disposable {
584
1456
  * have `pointer-events: none`, so the hit-test sees through them.
585
1457
  */
586
1458
  isPointInContent(point: Point2D): boolean;
1459
+ /**
1460
+ * Whether `range` intersects the rendered source text — the region whose
1461
+ * selection this editor paints itself from `model.selection`. This also
1462
+ * catches select-all ranges whose endpoints surround the rendered content.
1463
+ * Overlays anchored beside the text (comment widgets and the like) are *not*
1464
+ * part of it and keep their own native selection behaviour.
1465
+ */
1466
+ intersectsRenderedContent(range: Range): boolean;
587
1467
  private readonly _renderAutorun;
588
1468
  /** Current mounted blocks, or empty before the first render. */
589
1469
  private get _blocks();
@@ -593,6 +1473,50 @@ export declare class EditorView extends Disposable {
593
1473
  * is not read here, so there is no feedback loop into the render autorun.
594
1474
  */
595
1475
  private _publishMeasurements;
1476
+ /**
1477
+ * Paint the diff highlights via the CSS Custom Highlight API: green over the
1478
+ * inserted/changed modified ranges (mapped on the document's own DOM), and
1479
+ * red over each {@link DiffDecorationViewNode}'s deleted ranges (mapped on
1480
+ * the decoration's own subtree). No DOM is mutated, so reconciliation and
1481
+ * editing are unaffected.
1482
+ */
1483
+ private _paintDiff;
1484
+ private _clearDiff;
1485
+ private _syncEditContextAttachment;
1486
+ private _revealRange;
1487
+ private _revealTarget;
1488
+ private _scheduleCaretReveal;
1489
+ private _revealCaretNearest;
1490
+ private _revealCaretAfterActiveBlockResize;
1491
+ private _caretBlockAt;
1492
+ private _measurementAt;
1493
+ private _stopFollowingCaret;
1494
+ private _isRevealOccluded;
1495
+ /** Client rects of registered occlusions that are currently rendered and visible. */
1496
+ private _activeRevealOcclusions;
1497
+ /**
1498
+ * How far registered chrome covers the top of `viewport`, measured down from
1499
+ * `viewport.top`, across the columns `target` occupies. Clearing one occluder
1500
+ * can slide the target behind the next one, so the tested band is re-evaluated
1501
+ * until it settles; stacked chrome therefore reports the lowest connected
1502
+ * bottom edge. Returns 0 when nothing covers the top.
1503
+ */
1504
+ private _occludedTopHeight;
1505
+ /**
1506
+ * Vertical inset used to top-align `target` inside `viewport`. Defaults to
1507
+ * {@link TOP_REVEAL_CONTEXT_INSET}, and grows past registered chrome covering
1508
+ * the viewport top so the same breathing room is kept below that chrome.
1509
+ */
1510
+ private _topRevealInset;
1511
+ /**
1512
+ * `viewport` reduced to the area an explicitly navigated target may occupy:
1513
+ * registered top chrome is excluded, along with the breathing room below it.
1514
+ * Nearest-edge movement parks the target just inside the rect it is given, so
1515
+ * the inset has to be part of that rect; otherwise an outer scroller, or the
1516
+ * window, would leave the target grazing the chrome's bottom edge after the
1517
+ * nearest vertical viewport had already aligned it.
1518
+ */
1519
+ private _unoccludedViewport;
596
1520
  }
597
1521
 
598
1522
  export declare interface EditorViewOptions extends BlockViewOptions {
@@ -603,14 +1527,38 @@ export declare interface EditorViewOptions extends BlockViewOptions {
603
1527
  * only) unless a theme class is supplied.
604
1528
  */
605
1529
  readonly classNames?: readonly string[];
1530
+ /**
1531
+ * Whether to render the sticky edit/read-only toggle at the top-right edge
1532
+ * of the content. Defaults to `true`; set to `false` to omit it (e.g. in
1533
+ * fixtures that focus on selection rendering).
1534
+ */
1535
+ readonly showReadonlyToggle?: boolean;
1536
+ /**
1537
+ * Controls "limited width mode". The observable yields the maximum content
1538
+ * width in pixels, or `undefined` to let the content fill the available
1539
+ * width. When the option is omitted, the width is capped at
1540
+ * {@link DEFAULT_LIMITED_WIDTH}px (limited mode is on by default).
1541
+ *
1542
+ * The cap and centering apply to an inner content container; the editor
1543
+ * root ({@link element}) always spans the full available width.
1544
+ */
1545
+ readonly limitedWidth?: IObservable<number | undefined>;
1546
+ /**
1547
+ * Diff mode only: render every read-only original decoration in active
1548
+ * (source) form, so even whole-block removals expose their markdown markers
1549
+ * as real text. Used by the diff-coverage fixture to verify that every
1550
+ * changed original character is rendered somewhere; off in normal use, where
1551
+ * whole removals show a clean solid band.
1552
+ */
1553
+ readonly diffDecorationsActive?: boolean;
606
1554
  }
607
1555
 
608
1556
  export declare class EmphasisAstNode extends AstNode {
609
1557
  readonly openMarker: MarkerAstNode;
610
- readonly content: readonly (InlineAstNode | GlueAstNode)[];
1558
+ readonly content: readonly InlineContentAstNode[];
611
1559
  readonly closeMarker: MarkerAstNode;
612
1560
  readonly kind = "emphasis";
613
- constructor(openMarker: MarkerAstNode, content: readonly (InlineAstNode | GlueAstNode)[], closeMarker: MarkerAstNode);
1561
+ constructor(openMarker: MarkerAstNode, content: readonly InlineContentAstNode[], closeMarker: MarkerAstNode);
614
1562
  get children(): readonly AstNode[];
615
1563
  mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
616
1564
  }
@@ -622,6 +1570,111 @@ declare class EmphasisViewData {
622
1570
  constructor(ast: EmphasisAstNode, content: readonly AnyViewData[]);
623
1571
  }
624
1572
 
1573
+ export declare function escapeFindRegex(value: string): string;
1574
+
1575
+ export declare const FIND_MATCH_LIMIT = 19999;
1576
+
1577
+ export declare function findBlockAtOffset(doc: DocumentAstNode, offset: SourceOffset): BlockAstNode | undefined;
1578
+
1579
+ export declare class FindController extends Disposable {
1580
+ private readonly _editorModel;
1581
+ private readonly _view;
1582
+ private readonly _options;
1583
+ readonly model: FindModel;
1584
+ readonly widget: FindWidget;
1585
+ private readonly _selectionForScope;
1586
+ private _forcedMatch;
1587
+ private _selectedMatch;
1588
+ private _observedSourceTextId;
1589
+ private readonly _sourceEditTracker;
1590
+ private _revealRequest;
1591
+ constructor(_editorModel: EditorModel, _view: EditorView, _options: FindControllerOptions);
1592
+ private _setForcedMarkerVisibleBlocks;
1593
+ openAndFocus(): void;
1594
+ close(): void;
1595
+ private _handleKeyDown;
1596
+ private _cancelRevealRequest;
1597
+ private _findByKeyboard;
1598
+ private _querySeed;
1599
+ private _prepareSeed;
1600
+ private _selectedSingleLineText;
1601
+ private _toggleFindInSelection;
1602
+ }
1603
+
1604
+ export declare interface FindControllerOptions {
1605
+ readonly keyboardPlatform: KeyboardPlatform;
1606
+ }
1607
+
1608
+ export declare type FindDirection = 'next' | 'previous';
1609
+
1610
+ export declare class FindHighlightsView extends Disposable {
1611
+ private readonly _view;
1612
+ private readonly _matchesLayer;
1613
+ private readonly _currentLayer;
1614
+ private readonly _highlightRegistration;
1615
+ private readonly _resizeObserver;
1616
+ private readonly _resizeObservedElements;
1617
+ private _snapshot;
1618
+ private _paintRaf;
1619
+ constructor(_view: EditorView, findModel: FindModel);
1620
+ private _schedulePaint;
1621
+ private _paint;
1622
+ private _observeResizeAncestors;
1623
+ private _paintRanges;
1624
+ }
1625
+
1626
+ export declare interface FindMatchesResult {
1627
+ readonly matches: readonly OffsetRange[];
1628
+ readonly isCapped: boolean;
1629
+ }
1630
+
1631
+ export declare class FindModel extends Disposable {
1632
+ private readonly _editorModel;
1633
+ readonly isRevealed: ISettableObservable<boolean, void>;
1634
+ readonly searchString: ISettableObservable<string, void>;
1635
+ readonly isRegex: ISettableObservable<boolean, void>;
1636
+ readonly matchCase: ISettableObservable<boolean, void>;
1637
+ readonly wholeWord: ISettableObservable<boolean, void>;
1638
+ readonly searchScope: ISettableObservable<OffsetRange | undefined, void>;
1639
+ readonly currentMatch: ISettableObservable<OffsetRange | undefined, void>;
1640
+ readonly loop: ISettableObservable<boolean, void>;
1641
+ readonly searchResult: IObservableWithChange< {
1642
+ kind: "invalid";
1643
+ error: Error;
1644
+ pattern?: undefined;
1645
+ matches?: undefined;
1646
+ isCapped?: undefined;
1647
+ } | {
1648
+ kind: "valid";
1649
+ pattern: FindPattern;
1650
+ matches: readonly OffsetRange[];
1651
+ isCapped: boolean;
1652
+ error?: undefined;
1653
+ }, void>;
1654
+ readonly matchesCount: IObservableWithChange<number, void>;
1655
+ readonly isCapped: IObservableWithChange<boolean, void>;
1656
+ readonly currentMatchPosition: IObservableWithChange<number, void>;
1657
+ private _searchOrigin;
1658
+ private readonly _sourceEditTracker;
1659
+ private _pendingInitialDirection;
1660
+ constructor(_editorModel: EditorModel);
1661
+ reveal(options: {
1662
+ readonly origin: number;
1663
+ readonly searchString?: string;
1664
+ readonly direction?: FindDirection;
1665
+ }): void;
1666
+ hide(): void;
1667
+ setSearchOrigin(offset: number): void;
1668
+ setSearchScope(scope: OffsetRange | undefined): void;
1669
+ moveToNextMatch(): OffsetRange | undefined;
1670
+ moveToPreviousMatch(): OffsetRange | undefined;
1671
+ private _move;
1672
+ private _selectFromOrigin;
1673
+ private _mapStateThroughEdit;
1674
+ private _inputSnapshot;
1675
+ private _readInputSnapshot;
1676
+ }
1677
+
625
1678
  /**
626
1679
  * Source offset (relative to `root`) of the node with `target`'s id, or
627
1680
  * `undefined` when it is not in the tree. Ids are stable across edits, so this
@@ -629,14 +1682,117 @@ declare class EmphasisViewData {
629
1682
  */
630
1683
  export declare function findNodeOffsetById(root: AstNode, target: AstNode): number | undefined;
631
1684
 
632
- export declare function findWordAt(text: string, offset: number): {
1685
+ export declare class FindPattern {
1686
+ private readonly _source;
1687
+ private readonly _flags;
1688
+ private readonly _wholeWord;
1689
+ private readonly _wordSeparators;
1690
+ readonly isEmpty: boolean;
1691
+ private constructor();
1692
+ static create(query: FindQuery): FindQueryResult;
1693
+ findMatches(text: string, scope?: OffsetRange, limit?: number): FindMatchesResult;
1694
+ findNextMatch(text: string, after: number, scope?: OffsetRange, loop?: boolean, skip?: OffsetRange): OffsetRange | undefined;
1695
+ findPreviousMatch(text: string, before: number, scope?: OffsetRange, loop?: boolean, skip?: OffsetRange): OffsetRange | undefined;
1696
+ private _forEachMatch;
1697
+ }
1698
+
1699
+ export declare interface FindQuery {
1700
+ readonly searchString: string;
1701
+ readonly isRegex: boolean;
1702
+ readonly matchCase: boolean;
1703
+ readonly wholeWord: boolean;
1704
+ readonly wordSeparators: string;
1705
+ }
1706
+
1707
+ export declare type FindQueryResult = {
1708
+ readonly kind: 'valid';
1709
+ readonly pattern: FindPattern;
1710
+ } | {
1711
+ readonly kind: 'invalid';
1712
+ readonly error: Error;
1713
+ };
1714
+
1715
+ export declare type FindSearchResult = {
1716
+ readonly kind: 'valid';
1717
+ readonly pattern: FindPattern;
1718
+ readonly matches: readonly OffsetRange[];
1719
+ readonly isCapped: boolean;
1720
+ } | {
1721
+ readonly kind: 'invalid';
1722
+ readonly error: Error;
1723
+ };
1724
+
1725
+ export declare class FindWidget extends Disposable {
1726
+ private readonly _view;
1727
+ private readonly _options;
1728
+ readonly element: HTMLElement;
1729
+ readonly panelElement: HTMLElement;
1730
+ readonly focused: ISettableObservable<boolean, void>;
1731
+ private readonly _inputShell;
1732
+ private readonly _input;
1733
+ private readonly _matchesCount;
1734
+ private readonly _previousButton;
1735
+ private readonly _nextButton;
1736
+ private readonly _selectionButton;
1737
+ private readonly _caseButton;
1738
+ private readonly _wholeWordButton;
1739
+ private readonly _regexButton;
1740
+ private readonly _error;
1741
+ constructor(_view: EditorView, _options: FindWidgetOptions);
1742
+ focusAndSelect(): void;
1743
+ private _registerButton;
1744
+ private _render;
1745
+ }
1746
+
1747
+ export declare interface FindWidgetOptions {
1748
+ readonly findModel: FindModel;
1749
+ readonly canFindInSelection: IObservable<boolean>;
1750
+ readonly onNext: () => void;
1751
+ readonly onPrevious: () => void;
1752
+ readonly onToggleFindInSelection: () => void;
1753
+ readonly onClose: () => void;
1754
+ }
1755
+
1756
+ export declare function findWordAt(text: string, offset: number, config?: WordNavigationConfig): {
633
1757
  start: number;
634
1758
  end: number;
635
1759
  };
636
1760
 
637
- export declare function findWordBoundaryLeft(text: string, offset: number): number;
1761
+ export declare function findWordBoundaryLeft(text: string, offset: number, config?: WordNavigationConfig): number;
1762
+
1763
+ export declare function findWordBoundaryRight(text: string, offset: number, config?: WordNavigationConfig): number;
638
1764
 
639
- export declare function findWordBoundaryRight(text: string, offset: number): number;
1765
+ export declare function findWordDeleteBoundaryLeft(text: string, offset: number, config?: WordNavigationConfig): number;
1766
+
1767
+ export declare function findWordDeleteBoundaryRight(text: string, offset: number, config?: WordNavigationConfig): number;
1768
+
1769
+ /**
1770
+ * A leading YAML front matter block. The YAML value is intentionally opaque:
1771
+ * only the two fences and the exact source between them are modeled.
1772
+ */
1773
+ export declare class FrontMatterAstNode extends BlockAstNodeBase {
1774
+ readonly content: readonly (MarkerAstNode | GlueAstNode)[];
1775
+ readonly leadingTrivia?: GlueAstNode | undefined;
1776
+ readonly kind = "frontMatter";
1777
+ constructor(content: readonly (MarkerAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
1778
+ get children(): readonly AstNode[];
1779
+ get openFence(): MarkerAstNode | undefined;
1780
+ get closeFence(): MarkerAstNode | undefined;
1781
+ get value(): MarkerAstNode | undefined;
1782
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
1783
+ withLeadingTrivia(trivia: GlueAstNode | undefined): FrontMatterAstNode;
1784
+ }
1785
+
1786
+ declare class FrontMatterViewData {
1787
+ readonly ast: FrontMatterAstNode;
1788
+ /** Active: render both fences; inactive: render only the opaque YAML value. */
1789
+ readonly showMarkup: boolean;
1790
+ readonly content: readonly AnyViewData[];
1791
+ readonly kind = "frontMatter";
1792
+ constructor(ast: FrontMatterAstNode,
1793
+ /** Active: render both fences; inactive: render only the opaque YAML value. */
1794
+ showMarkup: boolean, content: readonly AnyViewData[]);
1795
+ }
640
1796
 
641
1797
  export declare function getAnnotatedSource(node: AstNode, source: string, offset?: number): string;
642
1798
 
@@ -670,14 +1826,39 @@ declare class GlueViewData {
670
1826
  decorateNewline: boolean);
671
1827
  }
672
1828
 
673
- export declare class HeadingAstNode extends AstNode {
1829
+ /**
1830
+ * A single gutter marker: a source {@link OffsetRange} tagged with a
1831
+ * {@link GutterMarkerType}. The view resolves the range to the visual lines it
1832
+ * covers and paints a bar (or, for `deleted`, a wedge at the range position) in
1833
+ * the left gutter.
1834
+ *
1835
+ * A `deleted` marker is normally an empty range (`range.isEmpty`) sitting at the
1836
+ * boundary where the removed text used to be — there is nothing left to span,
1837
+ * so it is drawn as a caret between lines rather than a bar.
1838
+ */
1839
+ export declare interface GutterMarker {
1840
+ readonly range: OffsetRange;
1841
+ readonly type: GutterMarkerType;
1842
+ }
1843
+
1844
+ /**
1845
+ * The kind of change a gutter marker represents, mirroring the three states a
1846
+ * source-control diff distinguishes (the git change markers in the editor
1847
+ * gutter): a freshly inserted region, an edited region, and a point where
1848
+ * content was removed.
1849
+ */
1850
+ export declare type GutterMarkerType = 'added' | 'modified' | 'deleted';
1851
+
1852
+ export declare class HeadingAstNode extends BlockAstNodeBase {
674
1853
  readonly level: 1 | 2 | 3 | 4 | 5 | 6;
675
1854
  readonly marker: MarkerAstNode;
676
- readonly content: readonly (InlineAstNode | GlueAstNode)[];
1855
+ readonly content: readonly InlineContentAstNode[];
1856
+ readonly leadingTrivia?: GlueAstNode | undefined;
677
1857
  readonly kind = "heading";
678
- constructor(level: 1 | 2 | 3 | 4 | 5 | 6, marker: MarkerAstNode, content: readonly (InlineAstNode | GlueAstNode)[]);
1858
+ constructor(level: 1 | 2 | 3 | 4 | 5 | 6, marker: MarkerAstNode, content: readonly InlineContentAstNode[], leadingTrivia?: GlueAstNode | undefined);
679
1859
  get children(): readonly AstNode[];
680
1860
  mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
1861
+ withLeadingTrivia(trivia: GlueAstNode | undefined): HeadingAstNode;
681
1862
  protected _localEquals(o: this): boolean;
682
1863
  }
683
1864
 
@@ -688,6 +1869,55 @@ declare class HeadingViewData {
688
1869
  constructor(ast: HeadingAstNode, content: readonly AnyViewData[]);
689
1870
  }
690
1871
 
1872
+ export declare function hiddenCursorRanges(doc: DocumentAstNode, markerVisibleBlocks: ReadonlySet<BlockAstNode>, selectionRange: OffsetRange): readonly OffsetRange[];
1873
+
1874
+ export declare type HistoryKeyboardAction = 'undo' | 'redo';
1875
+
1876
+ /** A block HTML comment, discriminated by whether its closing delimiter is present. */
1877
+ declare type HtmlCommentSource = OpenHtmlCommentSource | CompleteHtmlCommentSource;
1878
+
1879
+ declare interface HtmlCommentSourceBase {
1880
+ readonly leadingWhitespace: string;
1881
+ readonly opening: '<!--';
1882
+ readonly body: string;
1883
+ }
1884
+
1885
+ /**
1886
+ * The editor operations a clipboard strategy drives. The strategy never
1887
+ * touches the model or the DOM directly — it asks through this seam, so the
1888
+ * same strategy works regardless of how the editor is wired up.
1889
+ */
1890
+ export declare interface IClipboardContext {
1891
+ /** The element that owns focus and receives clipboard/keyboard events. */
1892
+ readonly element: HTMLElement;
1893
+ /** The selected source text, or `undefined` when the selection is empty. */
1894
+ getSelectedText(): string | undefined;
1895
+ /** Delete the current selection (the cut half of cut). */
1896
+ deleteSelection(): void;
1897
+ /** Insert text at the caret, replacing any selection (the paste action). */
1898
+ insertText(text: string): void;
1899
+ }
1900
+
1901
+ /**
1902
+ * How copy/cut/paste intent reaches the editor. Host environments deliver it
1903
+ * differently, so the controller owns no clipboard logic itself — it
1904
+ * {@link connect}s a strategy and lets it install whatever listeners it needs.
1905
+ *
1906
+ * Two implementations ship:
1907
+ * - {@link NativeClipboardStrategy} (default) reads the browser's native
1908
+ * `copy`/`cut`/`paste` events and their synchronous `clipboardData`.
1909
+ * - {@link AsyncClipboardStrategy} drives the async `navigator.clipboard` API
1910
+ * from Ctrl/Cmd+C/X/V keystrokes, for hosts (e.g. VS Code webviews) that
1911
+ * swallow the native clipboard events before they reach the editor.
1912
+ */
1913
+ export declare interface IClipboardStrategy {
1914
+ /**
1915
+ * Wire up clipboard handling against `context`. The returned disposable
1916
+ * tears down every listener the strategy installed.
1917
+ */
1918
+ connect(context: IClipboardContext): IDisposable;
1919
+ }
1920
+
691
1921
  /** The Monarch language definitions the default highlighter wires up. */
692
1922
  export declare interface IDefaultMonarchGrammars {
693
1923
  typescript: unknown;
@@ -697,6 +1927,87 @@ export declare interface IDefaultMonarchGrammars {
697
1927
  python: unknown;
698
1928
  rust: unknown;
699
1929
  shell: unknown;
1930
+ yaml: unknown;
1931
+ }
1932
+
1933
+ /**
1934
+ * A live editor embedded in place of a fenced code block's *rendered* form.
1935
+ *
1936
+ * This is the internal seam between the block view and a concrete embedded
1937
+ * editor (e.g. an `<iframe>` speaking the web-editor protocol). The block view
1938
+ * only speaks string edits: it pushes the block's content down via
1939
+ * {@link setContent} and receives the editor's own changes back through
1940
+ * {@link onEdit} (set by the block view on each (re)construction, so it always
1941
+ * routes to the current AST node). The concrete implementation owns its DOM,
1942
+ * transport, and lifecycle.
1943
+ *
1944
+ * A single instance is adopted across re-renders (like the highlighter session)
1945
+ * so the underlying editor keeps its state across edits — see
1946
+ * {@link CodeBlockViewNode}.
1947
+ */
1948
+ declare interface IEmbeddedCodeEditor {
1949
+ /** The element mounted as the block's rendered form. */
1950
+ readonly element: HTMLElement;
1951
+ /**
1952
+ * Document → editor. The block's content changed (from any source). Must be
1953
+ * idempotent: pushing the content the editor already holds is a no-op, which
1954
+ * is how edits the editor itself originated are prevented from echoing back.
1955
+ */
1956
+ setContent(content: string): void;
1957
+ /** Update whether the embedded editor may change its content. */
1958
+ setReadOnly?(readOnly: boolean): void;
1959
+ /**
1960
+ * Optional synchronous height (px) to reserve for `content` *before* the
1961
+ * editor has laid out. Return `undefined` to let the editor size itself
1962
+ * (the implementation may report its real height later). Lets a registration
1963
+ * avoid a layout jump when it can cheaply estimate the size from content.
1964
+ */
1965
+ estimateHeight?(content: string): number | undefined;
1966
+ /**
1967
+ * Editor → document. Set by the block view on every (re)construction to
1968
+ * route the editor's own edits, expressed in the block's *content*
1969
+ * coordinates, to the current AST node.
1970
+ */
1971
+ onEdit?: (edit: StringEdit) => void;
1972
+ dispose(): void;
1973
+ }
1974
+
1975
+ /** Creates an {@link IEmbeddedCodeEditor} for a fenced block, or opts out. */
1976
+ declare interface IEmbeddedCodeEditorFactory {
1977
+ /**
1978
+ * Return an editor for a fenced block, or `undefined` to fall
1979
+ * back to the default (highlighting / {@link BlockViewOptions.renderCustomCodeBlock}).
1980
+ */
1981
+ create(language: string, infoString: string, initialContent: string): IEmbeddedCodeEditor | undefined;
1982
+ }
1983
+
1984
+ /**
1985
+ * Routes undo and redo to whatever owns the document's history: the editor
1986
+ * itself on a standalone page, or the enclosing document in a host like
1987
+ * VS Code.
1988
+ */
1989
+ export declare interface IHistoryStrategy {
1990
+ undo(): void;
1991
+ redo(): void;
1992
+ /**
1993
+ * Invoked around each source mutation so the strategy can record it.
1994
+ * Implemented only by strategies that build their own history; a host that
1995
+ * forwards edits to a VS Code `TextDocument` lets it record them instead.
1996
+ */
1997
+ record?(operation: () => void, edit?: StringEdit): void;
1998
+ }
1999
+
2000
+ export declare interface ILinkPresentation extends IDisposable {
2001
+ /** Current presentation, updated without rebuilding the editor. */
2002
+ readonly presentation: IObservable<LinkPresentation | undefined>;
2003
+ }
2004
+
2005
+ export declare interface ILinkPresentationProvider {
2006
+ /**
2007
+ * Returns `undefined` for unsupported links. The caller disposes the returned
2008
+ * reference when the rendered link disappears.
2009
+ */
2010
+ createLinkPresentation(url: string): ILinkPresentation | undefined;
700
2011
  }
701
2012
 
702
2013
  export declare class ImageAstNode extends AstNode {
@@ -733,6 +2044,14 @@ export declare interface IMonarchApi {
733
2044
  MonarchTokenizer: new (languageService: unknown, standaloneThemeService: unknown, languageId: string, lexer: unknown, configurationService: unknown) => MonarchTokenizer;
734
2045
  }
735
2046
 
2047
+ /** Controls tab-stop insertion and non-list line indentation. */
2048
+ export declare interface IndentationConfig {
2049
+ /** Number of visual columns between tab stops. */
2050
+ readonly tabSize: number;
2051
+ /** Whether indentation uses spaces instead of tab characters. */
2052
+ readonly insertSpaces: boolean;
2053
+ }
2054
+
736
2055
  export declare type InlineAstNode = TextAstNode | StrongAstNode | EmphasisAstNode | StrikethroughAstNode | InlineCodeAstNode | InlineMathAstNode | LinkAstNode | ImageAstNode;
737
2056
 
738
2057
  export declare class InlineCodeAstNode extends AstNode {
@@ -750,6 +2069,8 @@ declare class InlineCodeViewData {
750
2069
  constructor(ast: InlineCodeAstNode, content: readonly AnyViewData[]);
751
2070
  }
752
2071
 
2072
+ declare type InlineContentAstNode = InlineAstNode | MarkerAstNode | GlueAstNode;
2073
+
753
2074
  export declare class InlineMathAstNode extends AstNode {
754
2075
  readonly content: readonly (MarkerAstNode | GlueAstNode)[];
755
2076
  readonly kind = "inlineMath";
@@ -782,7 +2103,32 @@ export declare const insertLineBreak: EditCommand;
782
2103
 
783
2104
  export declare const insertParagraph: EditCommand;
784
2105
 
785
- export declare function insertText(text: string): EditCommand;
2106
+ /**
2107
+ * Context-aware Enter. The behaviour is chosen from the active block:
2108
+ * - paragraph / heading / thematic break — the "rich text" thing: at the
2109
+ * block's end arm a transient empty paragraph (see {@link SmartEnterResult});
2110
+ * elsewhere split into two paragraphs (`\n\n`).
2111
+ * - fenced code / front matter — insert a newline that preserves the current
2112
+ * line's indentation, staying inside the fences.
2113
+ * - block quote — continue the quote (`\n> `); an empty quote line exits it.
2114
+ * - list — continue the list with the next marker (incrementing ordered
2115
+ * numbers, re-emitting task checkboxes); an empty item outdents one level
2116
+ * before exiting the list.
2117
+ * - complete HTML comment — at the comment's end, leave it by arming a
2118
+ * transient paragraph; inside it (or while the comment is open), insert a
2119
+ * normal source line break.
2120
+ * A non-collapsed selection, or any other block, falls back to a plain soft line
2121
+ * break, preserving today's behaviour.
2122
+ */
2123
+ export declare const insertSmartEnter: (ctx: CursorCommandContext) => SmartEnterResult;
2124
+
2125
+ /**
2126
+ * VS Code-style Tab: insert to the next tab stop for a caret or partial
2127
+ * single-line selection, and indent every selected line for a line selection.
2128
+ */
2129
+ export declare function insertTab(config?: IndentationConfig): EditCommand;
2130
+
2131
+ export declare function insertText(text: string, generatedIndentation?: OffsetRange): EditCommand;
786
2132
 
787
2133
  /**
788
2134
  * An immutable view of one document's tokens at a point in time. It may be a
@@ -823,6 +2169,31 @@ export declare interface ISyntaxHighlighterDocument extends IDisposable {
823
2169
  readonly snapshot: IObservableWithChange<ISyntaxHighlightedSnapshot, LengthEdit>;
824
2170
  }
825
2171
 
2172
+ export declare const joinLines: EditCommand;
2173
+
2174
+ export declare interface KeyboardBinding {
2175
+ readonly key: string;
2176
+ readonly modifiers?: KeyboardModifiers;
2177
+ readonly platforms?: readonly KeyboardPlatform[];
2178
+ readonly action: EditorKeyboardAction;
2179
+ }
2180
+
2181
+ export declare interface KeyboardModifiers {
2182
+ readonly shift?: boolean;
2183
+ readonly alt?: boolean;
2184
+ readonly ctrl?: boolean;
2185
+ readonly meta?: boolean;
2186
+ }
2187
+
2188
+ export declare type KeyboardPlatform = 'macos' | 'windows' | 'linux';
2189
+
2190
+ export declare interface KeyboardProfile {
2191
+ /**
2192
+ * Bindings in priority order. The first exact key/modifier/platform match wins.
2193
+ */
2194
+ readonly bindings: readonly KeyboardBinding[];
2195
+ }
2196
+
826
2197
  declare abstract class LeafAstNode extends AstNode {
827
2198
  abstract readonly content: string;
828
2199
  get children(): readonly AstNode[];
@@ -871,29 +2242,67 @@ export declare class LengthReplacement {
871
2242
 
872
2243
  export declare class LinkAstNode extends AstNode {
873
2244
  readonly url: string;
874
- readonly content: readonly (MarkerAstNode | InlineAstNode | GlueAstNode)[];
2245
+ readonly content: readonly InlineContentAstNode[];
875
2246
  readonly kind = "link";
876
- constructor(url: string, content: readonly (MarkerAstNode | InlineAstNode | GlueAstNode)[]);
2247
+ constructor(url: string, content: readonly InlineContentAstNode[]);
877
2248
  get children(): readonly AstNode[];
878
2249
  mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
879
2250
  protected _localEquals(o: this): boolean;
880
2251
  }
881
2252
 
2253
+ /**
2254
+ * Declarative rendering data for one link. `kind` selects the package-owned
2255
+ * visual treatment; providers never supply DOM or CSS.
2256
+ */
2257
+ export declare interface LinkPresentation {
2258
+ readonly kind: LinkPresentationKind;
2259
+ readonly title?: string;
2260
+ readonly detail?: string;
2261
+ readonly reference?: string;
2262
+ /** Primary resource state, such as pull-request lifecycle or session state. */
2263
+ readonly status?: LinkPresentationStatus;
2264
+ /** Secondary state, such as pull-request CI status. */
2265
+ readonly secondaryStatus?: LinkPresentationStatus;
2266
+ readonly changes?: LinkPresentationChanges;
2267
+ readonly tooltip?: string;
2268
+ readonly ariaLabel?: string;
2269
+ }
2270
+
2271
+ declare interface LinkPresentationChanges {
2272
+ readonly insertions: number;
2273
+ readonly deletions: number;
2274
+ }
2275
+
2276
+ export declare type LinkPresentationKind = 'resource' | 'issue' | 'pullRequest' | 'commit' | 'file' | 'folder' | 'session' | 'repository' | 'branch';
2277
+
2278
+ export declare interface LinkPresentationStatus {
2279
+ readonly kind: LinkPresentationStatusKind;
2280
+ readonly label: string;
2281
+ }
2282
+
2283
+ export declare type LinkPresentationStatusKind = 'neutral' | 'pending' | 'success' | 'warning' | 'error' | 'open' | 'closed' | 'merged' | 'draft' | 'notPlanned';
2284
+
882
2285
  declare class LinkViewData {
883
2286
  readonly ast: LinkAstNode;
2287
+ /** Active: render the Markdown source; inactive: allow a rich presentation. */
2288
+ readonly showMarkup: boolean;
884
2289
  readonly content: readonly AnyViewData[];
885
2290
  readonly kind = "link";
886
- constructor(ast: LinkAstNode, content: readonly AnyViewData[]);
2291
+ constructor(ast: LinkAstNode,
2292
+ /** Active: render the Markdown source; inactive: allow a rich presentation. */
2293
+ showMarkup: boolean, content: readonly AnyViewData[]);
887
2294
  }
888
2295
 
889
- export declare class ListAstNode extends AstNode {
2296
+ export declare class ListAstNode extends BlockAstNodeBase {
890
2297
  readonly ordered: boolean;
891
2298
  readonly content: readonly (ListItemAstNode | GlueAstNode)[];
2299
+ readonly leadingTrivia?: GlueAstNode | undefined;
892
2300
  readonly kind = "list";
893
- constructor(ordered: boolean, content: readonly (ListItemAstNode | GlueAstNode)[]);
2301
+ constructor(ordered: boolean, content: readonly (ListItemAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
894
2302
  get children(): readonly AstNode[];
895
2303
  get items(): readonly ListItemAstNode[];
896
2304
  mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
2305
+ withLeadingTrivia(trivia: GlueAstNode | undefined): ListAstNode;
897
2306
  protected _localEquals(o: this): boolean;
898
2307
  }
899
2308
 
@@ -907,6 +2316,7 @@ export declare class ListItemAstNode extends AstNode {
907
2316
  get children(): readonly AstNode[];
908
2317
  get blocks(): readonly BlockAstNode[];
909
2318
  mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
2319
+ withLeadingTrivia(trivia: GlueAstNode | undefined): ListItemAstNode;
910
2320
  protected _localEquals(o: this): boolean;
911
2321
  }
912
2322
 
@@ -917,12 +2327,26 @@ declare class ListItemViewData {
917
2327
  readonly content: readonly AnyViewData[];
918
2328
  /** 1-based list nesting depth, used to size the indentation gutter. */
919
2329
  readonly level: number;
2330
+ /**
2331
+ * Whether this is an inactive task item whose first paragraph begins
2332
+ * with the `:running:` marker (see {@link TextViewData.hiddenPrefixLength}).
2333
+ * Always `false` while the item is active — an active/editing task
2334
+ * reveals the literal marker instead of the progress affordance.
2335
+ */
2336
+ readonly isRunning: boolean;
920
2337
  readonly kind = "listItem";
921
2338
  constructor(ast: ListItemAstNode,
922
2339
  /** Whether the selection reaches this item (reveals its markers). */
923
2340
  isActive: boolean, content: readonly AnyViewData[],
924
2341
  /** 1-based list nesting depth, used to size the indentation gutter. */
925
- level: number);
2342
+ level: number,
2343
+ /**
2344
+ * Whether this is an inactive task item whose first paragraph begins
2345
+ * with the `:running:` marker (see {@link TextViewData.hiddenPrefixLength}).
2346
+ * Always `false` while the item is active — an active/editing task
2347
+ * reveals the literal marker instead of the progress affordance.
2348
+ */
2349
+ isRunning?: boolean);
926
2350
  }
927
2351
 
928
2352
  declare class ListViewData {
@@ -932,6 +2356,32 @@ declare class ListViewData {
932
2356
  constructor(ast: ListAstNode, content: readonly AnyViewData[]);
933
2357
  }
934
2358
 
2359
+ /**
2360
+ * Compact in-memory history for editors that hold the only copy of the
2361
+ * document, such as a standalone browser page. Where the surrounding host
2362
+ * already records history — a VS Code `TextDocument` — forward to that
2363
+ * instead.
2364
+ */
2365
+ export declare class LocalHistoryStrategy implements IHistoryStrategy {
2366
+ private readonly _model;
2367
+ private readonly _past;
2368
+ private readonly _future;
2369
+ /**
2370
+ * The source text as of the last change this strategy recorded or applied.
2371
+ * Any other value means the document was replaced behind its back, so the
2372
+ * stored edits no longer line up and must be discarded rather than applied.
2373
+ */
2374
+ private _lastKnownText;
2375
+ constructor(_model: EditorModel);
2376
+ record(operation: () => void, edit?: StringEdit): void;
2377
+ undo(): void;
2378
+ redo(): void;
2379
+ /** The entry on top of `stack`, or `undefined` when it cannot be applied. */
2380
+ private _peekApplicable;
2381
+ private _apply;
2382
+ private _clear;
2383
+ }
2384
+
935
2385
  /**
936
2386
  * Parses markdown into a {@link DocumentAstNode}.
937
2387
  *
@@ -960,13 +2410,15 @@ declare class MarkerViewData {
960
2410
  constructor(ast: MarkerAstNode, visible: boolean);
961
2411
  }
962
2412
 
963
- export declare class MathBlockAstNode extends AstNode {
2413
+ export declare class MathBlockAstNode extends BlockAstNodeBase {
964
2414
  readonly content: readonly (MarkerAstNode | GlueAstNode)[];
2415
+ readonly leadingTrivia?: GlueAstNode | undefined;
965
2416
  readonly kind = "mathBlock";
966
- constructor(content: readonly (MarkerAstNode | GlueAstNode)[]);
2417
+ constructor(content: readonly (MarkerAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
967
2418
  get children(): readonly AstNode[];
968
2419
  get code(): MarkerAstNode | undefined;
969
2420
  mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
2421
+ withLeadingTrivia(trivia: GlueAstNode | undefined): MathBlockAstNode;
970
2422
  }
971
2423
 
972
2424
  declare class MathBlockViewData {
@@ -1036,8 +2488,8 @@ export declare class MeasuredLayoutDebugRendering {
1036
2488
  * Exposes two DOM nodes the caller can place independently:
1037
2489
  *
1038
2490
  * - {@link overlayElement} — absolutely positioned; the caller mounts it
1039
- * inside the editor element so dashed line-bands and run-boxes line up
1040
- * with the editor's client coordinates.
2491
+ * inside the editor overlay container so dashed line-bands and run-boxes
2492
+ * share the measured editor-local coordinates.
1041
2493
  * - {@link infoElement} — block-flow; the caller mounts it as a sibling
1042
2494
  * *below* the editor. Contains the per-block summary table that used
1043
2495
  * to live on the overlay.
@@ -1048,7 +2500,6 @@ export declare class MeasuredLayoutDebugRendering {
1048
2500
  * the derived subscribed.
1049
2501
  */
1050
2502
  export declare class MeasuredLayoutDebugView extends Disposable {
1051
- private readonly _overlayParent;
1052
2503
  readonly overlayElement: HTMLElement;
1053
2504
  readonly infoElement: HTMLElement;
1054
2505
  readonly rendering: IObservable<MeasuredLayoutDebugRendering>;
@@ -1061,6 +2512,7 @@ export declare class MeasuredLayoutDebugView extends Disposable {
1061
2512
 
1062
2513
  export declare interface MeasuredLayoutDebugViewOptions {
1063
2514
  readonly model: MeasuredLayoutModel;
2515
+ readonly coordinateSpace: EditorCoordinateSpace;
1064
2516
  /**
1065
2517
  * DEBUG ONLY. Maps an absolute source offset to a fill color for that
1066
2518
  * character's glyph rect. The fixture passes the same function to the
@@ -1093,14 +2545,16 @@ export declare interface MeasuredLayoutDebugViewOptions {
1093
2545
  * through this model and never touches view fields directly.
1094
2546
  */
1095
2547
  export declare class MeasuredLayoutModel {
1096
- readonly measurements: ISettableObservable<readonly BlockMeasurement[], void>;
2548
+ private readonly _measurements;
2549
+ readonly measurements: IObservable<readonly BlockMeasurement[]>;
2550
+ private readonly _virtualLines;
1097
2551
  /**
1098
- * Concatenated visual line map across all mounted blocks. Lines are
1099
- * left in DOM (client-coordinate) y order — each per-block map already
1100
- * uses absolute client coordinates from `getClientRects()`, so the
1101
- * concatenation is well-formed without re-sorting.
2552
+ * Concatenated visual line map across all mounted blocks. Every per-block
2553
+ * map uses the same editor-local coordinate space, so concatenation is
2554
+ * well-formed without translation or re-sorting.
1102
2555
  */
1103
2556
  readonly visualLineMap: IObservableWithChange<VisualLineMap, void>;
2557
+ setMeasurements(measurements: readonly BlockMeasurement[], virtualLines: readonly VirtualLineMeasurement[]): void;
1104
2558
  }
1105
2559
 
1106
2560
  /**
@@ -1129,14 +2583,40 @@ export declare class MonacoSyntaxHighlighter implements ISyntaxHighlighter {
1129
2583
  private _tokenizerFor;
1130
2584
  }
1131
2585
 
2586
+ export declare const moveLinesDown: EditCommand;
2587
+
2588
+ export declare const moveLinesUp: EditCommand;
2589
+
1132
2590
  /**
1133
- * Move the cursor one position left or right, skipping over hidden marker
2591
+ * Default strategy: handle the browser's native `copy`/`cut`/`paste` events,
2592
+ * reading and writing the synchronous {@link ClipboardEvent.clipboardData}.
2593
+ * This is the standard rich-editor approach and works wherever the browser
2594
+ * actually dispatches those events to the focused element (e.g. a standalone
2595
+ * web page).
2596
+ */
2597
+ export declare class NativeClipboardStrategy implements IClipboardStrategy {
2598
+ connect(context: IClipboardContext): IDisposable;
2599
+ }
2600
+
2601
+ declare interface NestedItem {
2602
+ readonly kind: 'nested';
2603
+ readonly original: AstNode;
2604
+ readonly originalStart: number;
2605
+ readonly modified: AstNode;
2606
+ readonly modifiedStart: number;
2607
+ readonly children: readonly DiffItem[];
2608
+ }
2609
+
2610
+ /**
2611
+ * Move the cursor one position left or right, skipping over hidden source
1134
2612
  * ranges in inactive blocks (and inactive items of an active list).
1135
2613
  */
1136
- export declare function nextCursorPosition(doc: DocumentAstNode, activeBlock: BlockAstNode | undefined, cursor: number, direction: 'left' | 'right'): number;
2614
+ export declare function nextCursorPosition(doc: DocumentAstNode, markerVisibleBlocks: ReadonlySet<BlockAstNode>, cursor: number, direction: 'left' | 'right', selectionRange?: OffsetRange): number;
1137
2615
 
1138
2616
  declare const NO_ACTIVE_BLOCKS: unique symbol;
1139
2617
 
2618
+ export declare function normalizeCursorPosition(doc: DocumentAstNode, markerVisibleBlocks: ReadonlySet<BlockAstNode>, cursor: number, target: number, direction: 'left' | 'right', includeHiddenRangeBoundary?: boolean, selectionRange?: OffsetRange): number;
2619
+
1140
2620
  export declare class OffsetRange {
1141
2621
  readonly start: number;
1142
2622
  readonly endExclusive: number;
@@ -1164,12 +2644,22 @@ export declare class OffsetRange {
1164
2644
  toString(): string;
1165
2645
  }
1166
2646
 
1167
- export declare class ParagraphAstNode extends AstNode {
1168
- readonly content: readonly (InlineAstNode | GlueAstNode)[];
2647
+ /** The lossless source slices of a block HTML comment whose closer has not been typed. */
2648
+ declare interface OpenHtmlCommentSource extends HtmlCommentSourceBase {
2649
+ readonly kind: 'open';
2650
+ }
2651
+
2652
+ /** Outdent the current line, or every line touched by the selection. */
2653
+ export declare function outdent(config?: IndentationConfig): EditCommand;
2654
+
2655
+ export declare class ParagraphAstNode extends BlockAstNodeBase {
2656
+ readonly content: readonly InlineContentAstNode[];
2657
+ readonly leadingTrivia?: GlueAstNode | undefined;
1169
2658
  readonly kind = "paragraph";
1170
- constructor(content: readonly (InlineAstNode | GlueAstNode)[]);
2659
+ constructor(content: readonly InlineContentAstNode[], leadingTrivia?: GlueAstNode | undefined);
1171
2660
  get children(): readonly AstNode[];
1172
2661
  mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
2662
+ withLeadingTrivia(trivia: GlueAstNode | undefined): ParagraphAstNode;
1173
2663
  }
1174
2664
 
1175
2665
  declare class ParagraphViewData {
@@ -1180,7 +2670,85 @@ declare class ParagraphViewData {
1180
2670
  }
1181
2671
 
1182
2672
  /**
1183
- * Immutable point in 2D space, in CSS-pixel client coordinates.
2673
+ * A *transient* editing state: an empty paragraph adjacent to a real block.
2674
+ * Markdown has no empty-paragraph node, so this never lives in
2675
+ * {@link EditorModel['sourceText']} or the parsed {@link EditorModel.document}
2676
+ * — it is pure edit intent that the view renders as a synthetic blank line and
2677
+ * that the controller either *materializes* (the user types) or *cancels* (the
2678
+ * user navigates away / backspaces).
2679
+ */
2680
+ declare interface PendingParagraph {
2681
+ /** The block the blank line is rendered directly after. */
2682
+ readonly anchorBlock: BlockAstNode;
2683
+ /**
2684
+ * Source region rewritten when the pending paragraph is materialized — the
2685
+ * gap between {@link anchorBlock}'s text and whatever follows it.
2686
+ */
2687
+ readonly replaceRange: OffsetRange;
2688
+ /** Whether materialized text needs a blank-line separator before it. */
2689
+ readonly separateFromPreviousBlock: boolean;
2690
+ /** Whether {@link replaceRange} ends at the end of the document. */
2691
+ readonly atEof: boolean;
2692
+ /**
2693
+ * Horizontal whitespace typed on the source-less line. It remains transient
2694
+ * until other input materializes the paragraph. Contains only spaces and tabs.
2695
+ */
2696
+ readonly text: string;
2697
+ /** The source-less visual line occupied by the pending caret. */
2698
+ readonly cursorLine: VirtualCursorLine;
2699
+ /**
2700
+ * A throwaway AST node that exists only to give the synthetic view child a
2701
+ * stable identity across render frames (the view pairs nodes by `ast.id`).
2702
+ * It is never part of {@link document}.
2703
+ */
2704
+ readonly syntheticAst: ParagraphAstNode;
2705
+ }
2706
+
2707
+ declare interface PendingParagraphResult {
2708
+ readonly kind: 'pending';
2709
+ readonly anchorBlock: BlockAstNode;
2710
+ readonly replaceRange: OffsetRange;
2711
+ /** Whether materialized text needs a blank-line separator before it. */
2712
+ readonly separateFromPreviousBlock: boolean;
2713
+ readonly atEof: boolean;
2714
+ }
2715
+
2716
+ /**
2717
+ * View-data for the transient empty paragraph (see `PendingParagraph` in the
2718
+ * model). It carries the throwaway {@link ParagraphAstNode} that gives the
2719
+ * rendered line a stable identity across frames, its anchor block, source-less
2720
+ * cursor line, and transient horizontal whitespace. It has no source content or
2721
+ * selection range.
2722
+ */
2723
+ declare class PendingParagraphViewData {
2724
+ readonly ast: ParagraphAstNode;
2725
+ readonly anchorBlock: BlockAstNode;
2726
+ readonly cursorLine: VirtualCursorLine;
2727
+ readonly text: string;
2728
+ readonly kind = "pendingParagraph";
2729
+ constructor(ast: ParagraphAstNode, anchorBlock: BlockAstNode, cursorLine: VirtualCursorLine, text: string);
2730
+ }
2731
+
2732
+ /**
2733
+ * The mounted transient empty paragraph: a `<p class="md-pending-paragraph">`
2734
+ * holding either a `<br>` or decorated transient horizontal whitespace. It is a
2735
+ * leaf view node with no inline source content; the document view publishes its
2736
+ * element geometry as a virtual visual line.
2737
+ */
2738
+ declare class PendingParagraphViewNode extends ViewNode {
2739
+ readonly element: HTMLElement;
2740
+ readonly anchorBlock: BlockAstNode;
2741
+ readonly cursorLine: VirtualCursorLine;
2742
+ private _text;
2743
+ constructor(view: PendingParagraphViewData);
2744
+ update(text: string): void;
2745
+ getCaretClientRect(): DOMRect;
2746
+ }
2747
+
2748
+ /**
2749
+ * Immutable point in a caller-defined 2D CSS-pixel coordinate space.
2750
+ * Coordinate-owning APIs must document whether values are viewport-client or
2751
+ * editor-local; values from different spaces must not be mixed.
1184
2752
  */
1185
2753
  export declare class Point2D {
1186
2754
  readonly x: number;
@@ -1191,8 +2759,8 @@ export declare class Point2D {
1191
2759
  }
1192
2760
 
1193
2761
  /**
1194
- * Immutable axis-aligned rectangle in 2D space, in CSS-pixel client
1195
- * coordinates. `x`/`y` is the top-left corner, growing right/down.
2762
+ * Immutable axis-aligned rectangle in a caller-defined 2D CSS-pixel coordinate
2763
+ * space. `x`/`y` is the top-left corner, growing right/down.
1196
2764
  *
1197
2765
  * Half-open in both dimensions: `right` and `bottom` are excluded.
1198
2766
  */
@@ -1218,6 +2786,48 @@ export declare class Rect2D {
1218
2786
  translate(dx: number, dy: number): Rect2D;
1219
2787
  }
1220
2788
 
2789
+ declare interface RemovedItem {
2790
+ readonly kind: 'removed';
2791
+ readonly node: AstNode;
2792
+ readonly originalStart: number;
2793
+ readonly deletedLocal: readonly AnnotatedRange[];
2794
+ }
2795
+
2796
+ declare interface ReplacedItem {
2797
+ readonly kind: 'replaced';
2798
+ readonly original: AstNode;
2799
+ readonly originalStart: number;
2800
+ readonly modified: AstNode;
2801
+ readonly modifiedStart: number;
2802
+ readonly insertedLocal: readonly AnnotatedRange[];
2803
+ readonly deletedLocal: readonly AnnotatedRange[];
2804
+ }
2805
+
2806
+ export declare class RichLink {
2807
+ static create(options: RichLinkOptions): RichLink;
2808
+ static mount(element: HTMLElement, authoredLabel: HTMLSpanElement): RichLink;
2809
+ static clear(element: HTMLElement): void;
2810
+ readonly element: HTMLElement;
2811
+ readonly authoredLabel: HTMLSpanElement;
2812
+ private readonly _icon;
2813
+ private readonly _title;
2814
+ private readonly _detail;
2815
+ private readonly _reference;
2816
+ private readonly _changes;
2817
+ private readonly _status;
2818
+ private readonly _secondaryStatus;
2819
+ private constructor();
2820
+ update(presentation: LinkPresentation | undefined): void;
2821
+ private _renderUnavailable;
2822
+ private _setDefaultOrder;
2823
+ }
2824
+
2825
+ export declare interface RichLinkOptions {
2826
+ readonly href: string;
2827
+ readonly authoredLabel: string;
2828
+ readonly presentation?: LinkPresentation;
2829
+ }
2830
+
1221
2831
  export declare const selectAll: SelectionCommand;
1222
2832
 
1223
2833
  export declare function selectBlock(ctx: CursorCommandContext, blockRange: OffsetRange): Selection_2;
@@ -1243,8 +2853,13 @@ export { Selection_2 as Selection }
1243
2853
  export declare interface SelectionBlock {
1244
2854
  readonly block: BlockAstNode;
1245
2855
  readonly absoluteStart: number;
1246
- readonly viewNode: ViewNode;
1247
- readonly element: HTMLElement;
2856
+ /** Block border box in editor-local coordinates. */
2857
+ readonly rect: Rect2D;
2858
+ /** Visible horizontal padding-box bounds for a scrolling block. */
2859
+ readonly viewportClip: {
2860
+ readonly left: number;
2861
+ readonly right: number;
2862
+ } | undefined;
1248
2863
  }
1249
2864
 
1250
2865
  export declare type SelectionCommand = (ctx: CursorCommandContext, offset: SourceOffset) => Selection_2;
@@ -1256,6 +2871,9 @@ export declare interface SelectionRect {
1256
2871
  readonly height: number;
1257
2872
  }
1258
2873
 
2874
+ /** The interaction that produced the current editor selection. */
2875
+ export declare type SelectionSource = 'user' | 'find';
2876
+
1259
2877
  /**
1260
2878
  * Owns the SVG overlay that paints the selection.
1261
2879
  *
@@ -1276,11 +2894,10 @@ export declare interface SelectionRect {
1276
2894
  * envelope shape used by IDE selection rendering.
1277
2895
  */
1278
2896
  export declare class SelectionView extends Disposable {
1279
- private readonly _parent;
1280
2897
  readonly element: SVGSVGElement;
1281
2898
  readonly rendering: IObservable<SelectionViewRendering>;
1282
2899
  private readonly _path;
1283
- constructor(_parent: HTMLElement, options: SelectionViewOptions);
2900
+ constructor(options: SelectionViewOptions);
1284
2901
  }
1285
2902
 
1286
2903
  export declare interface SelectionViewOptions {
@@ -1296,6 +2913,22 @@ export declare class SelectionViewRendering {
1296
2913
 
1297
2914
  export declare const selectWord: SelectionCommand;
1298
2915
 
2916
+ /**
2917
+ * The outcome of {@link insertSmartEnter}: either a concrete source edit (the
2918
+ * ordinary cases), or a request to arm a transient empty paragraph (Enter at
2919
+ * the very end of a paragraph), which the controller turns into
2920
+ * {@link EditorModel.armPendingParagraph} rather than a source edit. Modelling
2921
+ * the empty paragraph as state instead of source keeps the document valid
2922
+ * Markdown — which has no empty-paragraph node — until the user actually types.
2923
+ */
2924
+ export declare type SmartEnterResult = {
2925
+ readonly kind: 'edit';
2926
+ readonly edit: StringEdit;
2927
+ readonly selection: Selection_2;
2928
+ /** Post-edit range of indentation copied onto a new fenced-code line. */
2929
+ readonly generatedIndentation?: OffsetRange;
2930
+ } | PendingParagraphResult;
2931
+
1299
2932
  /**
1300
2933
  * A run of {@link Token}s together with the exact {@link OffsetRange} they
1301
2934
  * cover.
@@ -1309,14 +2942,22 @@ export declare interface SnapshotTokens {
1309
2942
  readonly tokens: readonly Token[];
1310
2943
  }
1311
2944
 
2945
+ /** Metadata delivered synchronously immediately before a model-owned source edit is applied. */
2946
+ export declare interface SourceEditEvent {
2947
+ readonly baseSourceTextId: number;
2948
+ readonly resultSourceTextId: number;
2949
+ readonly edit: StringEdit;
2950
+ readonly transaction: ITransaction;
2951
+ }
2952
+
1312
2953
  export declare type SourceOffset = number;
1313
2954
 
1314
2955
  export declare class StrikethroughAstNode extends AstNode {
1315
2956
  readonly openMarker: MarkerAstNode;
1316
- readonly content: readonly (InlineAstNode | GlueAstNode)[];
2957
+ readonly content: readonly InlineContentAstNode[];
1317
2958
  readonly closeMarker: MarkerAstNode;
1318
2959
  readonly kind = "strikethrough";
1319
- constructor(openMarker: MarkerAstNode, content: readonly (InlineAstNode | GlueAstNode)[], closeMarker: MarkerAstNode);
2960
+ constructor(openMarker: MarkerAstNode, content: readonly InlineContentAstNode[], closeMarker: MarkerAstNode);
1320
2961
  get children(): readonly AstNode[];
1321
2962
  mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
1322
2963
  }
@@ -1353,6 +2994,11 @@ export declare class StringReplacement {
1353
2994
  constructor(replaceRange: OffsetRange, newText: string);
1354
2995
  get isEmpty(): boolean;
1355
2996
  equals(other: StringReplacement): boolean;
2997
+ /**
2998
+ * Narrows this replacement to the span that actually changes, by trimming
2999
+ * the prefix and suffix it shares with the text it replaces in `source`.
3000
+ */
3001
+ removeCommonSuffixPrefix(source: string): StringReplacement;
1356
3002
  toString(): string;
1357
3003
  }
1358
3004
 
@@ -1366,10 +3012,10 @@ export declare class StringValue {
1366
3012
 
1367
3013
  export declare class StrongAstNode extends AstNode {
1368
3014
  readonly openMarker: MarkerAstNode;
1369
- readonly content: readonly (InlineAstNode | GlueAstNode)[];
3015
+ readonly content: readonly InlineContentAstNode[];
1370
3016
  readonly closeMarker: MarkerAstNode;
1371
3017
  readonly kind = "strong";
1372
- constructor(openMarker: MarkerAstNode, content: readonly (InlineAstNode | GlueAstNode)[], closeMarker: MarkerAstNode);
3018
+ constructor(openMarker: MarkerAstNode, content: readonly InlineContentAstNode[], closeMarker: MarkerAstNode);
1373
3019
  get children(): readonly AstNode[];
1374
3020
  mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
1375
3021
  }
@@ -1381,16 +3027,20 @@ declare class StrongViewData {
1381
3027
  constructor(ast: StrongAstNode, content: readonly AnyViewData[]);
1382
3028
  }
1383
3029
 
1384
- export declare class TableAstNode extends AstNode {
3030
+ export declare type TabKeyboardAction = 'insert' | 'outdent';
3031
+
3032
+ export declare class TableAstNode extends BlockAstNodeBase {
1385
3033
  readonly content: readonly (TableRowAstNode | GlueAstNode)[];
3034
+ readonly leadingTrivia?: GlueAstNode | undefined;
1386
3035
  readonly kind = "table";
1387
- constructor(content: readonly (TableRowAstNode | GlueAstNode)[]);
3036
+ constructor(content: readonly (TableRowAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
1388
3037
  get children(): readonly AstNode[];
1389
3038
  private get _rows();
1390
3039
  get headerRow(): TableRowAstNode | undefined;
1391
3040
  get delimiterRow(): TableRowAstNode | undefined;
1392
3041
  get bodyRows(): readonly TableRowAstNode[];
1393
3042
  mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
3043
+ withLeadingTrivia(trivia: GlueAstNode | undefined): TableAstNode;
1394
3044
  }
1395
3045
 
1396
3046
  export declare class TableCellAstNode extends AstNode {
@@ -1461,6 +3111,13 @@ declare class TextViewData {
1461
3111
  readonly showWhitespace: boolean;
1462
3112
  readonly leftWordBoundary: boolean;
1463
3113
  readonly rightWordBoundary: boolean;
3114
+ /**
3115
+ * Number of leading source characters to keep out of the rendered
3116
+ * text (but not out of the source): the `:running:` marker plus its
3117
+ * mandatory leading separator, once
3118
+ * {@link isRunnerMarkerText} has matched this node. Zero otherwise.
3119
+ */
3120
+ readonly hiddenPrefixLength: number;
1464
3121
  readonly kind = "text";
1465
3122
  /**
1466
3123
  * Whether non-obvious whitespace in this text is revealed (block is active).
@@ -1469,16 +3126,25 @@ declare class TextViewData {
1469
3126
  * emphasis); a single space touching such a sibling is obvious and stays
1470
3127
  * undecorated, just like a space between two words within this leaf.
1471
3128
  */
1472
- constructor(ast: TextAstNode, showWhitespace: boolean, leftWordBoundary?: boolean, rightWordBoundary?: boolean);
3129
+ constructor(ast: TextAstNode, showWhitespace: boolean, leftWordBoundary?: boolean, rightWordBoundary?: boolean,
3130
+ /**
3131
+ * Number of leading source characters to keep out of the rendered
3132
+ * text (but not out of the source): the `:running:` marker plus its
3133
+ * mandatory leading separator, once
3134
+ * {@link isRunnerMarkerText} has matched this node. Zero otherwise.
3135
+ */
3136
+ hiddenPrefixLength?: number);
1473
3137
  }
1474
3138
 
1475
- export declare class ThematicBreakAstNode extends AstNode {
3139
+ export declare class ThematicBreakAstNode extends BlockAstNodeBase {
1476
3140
  readonly content: readonly (MarkerAstNode | GlueAstNode)[];
3141
+ readonly leadingTrivia?: GlueAstNode | undefined;
1477
3142
  readonly kind = "thematicBreak";
1478
- constructor(content: readonly (MarkerAstNode | GlueAstNode)[]);
3143
+ constructor(content: readonly (MarkerAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
1479
3144
  get children(): readonly AstNode[];
1480
3145
  get marker(): MarkerAstNode | undefined;
1481
3146
  mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
3147
+ withLeadingTrivia(trivia: GlueAstNode | undefined): ThematicBreakAstNode;
1482
3148
  }
1483
3149
 
1484
3150
  declare class ThematicBreakViewData {
@@ -1511,6 +3177,55 @@ export declare class Token {
1511
3177
  className: string | undefined);
1512
3178
  }
1513
3179
 
3180
+ declare interface UnchangedItem {
3181
+ readonly kind: 'unchanged';
3182
+ /** The modified-side node (identical in content to the original). */
3183
+ readonly node: AstNode;
3184
+ readonly modifiedStart: number;
3185
+ }
3186
+
3187
+ /**
3188
+ * A block whose token type the parser does not understand (a setext heading or
3189
+ * any future/extension construct). Rather than dropping the
3190
+ * span — which would demote its text to invisible glue — the parser captures the
3191
+ * whole source range verbatim as a single {@link MarkerAstNode} of kind
3192
+ * `content` and records the originating micromark {@link tokenType}, so the view
3193
+ * can render it as raw, editable text with an "unhandled" affordance. Offsets
3194
+ * stay sound: `content` tiles the block's full source span exactly.
3195
+ */
3196
+ declare class UnhandledBlockAstNode extends BlockAstNodeBase {
3197
+ readonly tokenType: string;
3198
+ readonly content: readonly (MarkerAstNode | GlueAstNode)[];
3199
+ readonly leadingTrivia?: GlueAstNode | undefined;
3200
+ readonly kind = "unhandledBlock";
3201
+ constructor(tokenType: string, content: readonly (MarkerAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
3202
+ get children(): readonly AstNode[];
3203
+ get code(): MarkerAstNode | undefined;
3204
+ /**
3205
+ * Lossless slices when this raw HTML block starts one comment after optional
3206
+ * whitespace. An open comment consumes the remaining source as its body. A
3207
+ * complete comment permits only trailing whitespace after its closer.
3208
+ */
3209
+ get htmlComment(): HtmlCommentSource | undefined;
3210
+ mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
3211
+ withLeadingTrivia(trivia: GlueAstNode | undefined): UnhandledBlockAstNode;
3212
+ protected _localEquals(o: this): boolean;
3213
+ }
3214
+
3215
+ /**
3216
+ * View-data for an {@link UnhandledBlockAstNode}. The source remains verbatim
3217
+ * in both states. Complete HTML comments use {@link showMarkup} to switch
3218
+ * between their quiet reading treatment and editable source presentation;
3219
+ * other unhandled blocks ignore the flag and keep their warning treatment.
3220
+ */
3221
+ declare class UnhandledBlockViewData {
3222
+ readonly ast: UnhandledBlockAstNode;
3223
+ readonly showMarkup: boolean;
3224
+ readonly content: readonly AnyViewData[];
3225
+ readonly kind = "unhandledBlock";
3226
+ constructor(ast: UnhandledBlockAstNode, showMarkup: boolean, content: readonly AnyViewData[]);
3227
+ }
3228
+
1514
3229
  /**
1515
3230
  * Immutable view of an AST node. Pairs `ast` with its rendered `dom` and a
1516
3231
  * mirror of `ast.children` as ViewNode children. Source offsets are NEVER
@@ -1575,10 +3290,12 @@ export declare class ViewNode extends Disposable {
1575
3290
  /**
1576
3291
  * Map a DOM hit that lands on THIS node's own representation into a source
1577
3292
  * range in this node's local space `[0, ast.length)`. Polymorphic: a text
1578
- * leaf maps the caret offset 1:1; an element-only node (KaTeX math, `<hr>`,
1579
- * an image, a hidden marker) has no internal text mapping and snaps to its
1580
- * start by default — subclasses may override (e.g. to snap to the nearer
1581
- * edge by x).
3293
+ * leaf maps the caret offset 1:1. For an element hit — an element-only node
3294
+ * (KaTeX math, `<hr>`, an image, a hidden marker) or a wrapper/container
3295
+ * element — the platform reports a child-index offset, not a text caret, so
3296
+ * there is no internal mapping to honour: it snaps to the node's nearer
3297
+ * edge, `offset 0` (the "before" side) → start, any `offset >= 1` (the
3298
+ * "after" side) → end. Subclasses may override for finer control.
1582
3299
  */
1583
3300
  getLocalSourceRange(pos: DomPosition): OffsetRange;
1584
3301
  /**
@@ -1600,6 +3317,24 @@ export declare class ViewNode extends Disposable {
1600
3317
  forEachTextLeaf(nodeOffset: number, visitor: (leaf: ViewNode, leafOffset: number) => void): void;
1601
3318
  }
1602
3319
 
3320
+ /**
3321
+ * A visual cursor line that has no representation in the source text.
3322
+ *
3323
+ * The two source offsets are the positions immediately before and after the
3324
+ * virtual line. The object itself is the stable identity of the line.
3325
+ */
3326
+ export declare class VirtualCursorLine {
3327
+ readonly sourceOffsetBefore: SourceOffset;
3328
+ readonly sourceOffsetAfter: SourceOffset;
3329
+ constructor(sourceOffsetBefore: SourceOffset, sourceOffsetAfter: SourceOffset);
3330
+ }
3331
+
3332
+ /** A measured source-less line inserted directly after a source block. */
3333
+ declare interface VirtualLineMeasurement {
3334
+ readonly afterBlock: BlockAstNode;
3335
+ readonly line: VisualLine;
3336
+ }
3337
+
1603
3338
  export declare type VisualCursorCommand = (ctx: VisualCursorCommandContext) => CursorMoveResult;
1604
3339
 
1605
3340
  export declare interface VisualCursorCommandContext extends CursorCommandContext {
@@ -1617,12 +3352,15 @@ export declare function visualizeAst(root: AstNode, source: string): AstVisualiz
1617
3352
  export declare class VisualLine {
1618
3353
  readonly rect: Rect2D;
1619
3354
  readonly runs: readonly VisualRun[];
1620
- constructor(rect: Rect2D, runs: readonly VisualRun[]);
3355
+ readonly virtualCursorLine?: VirtualCursorLine | undefined;
3356
+ static virtual(cursorLine: VirtualCursorLine, rect: Rect2D): VisualLine;
3357
+ constructor(rect: Rect2D, runs: readonly VisualRun[], virtualCursorLine?: VirtualCursorLine | undefined);
1621
3358
  containsOffset(offset: SourceOffset): boolean;
1622
3359
  /**
1623
3360
  * How `offset` relates to this line's runs:
1624
3361
  * - `'covers'`: a run starts at or strictly contains the offset
1625
- * (`start <= offset < endExclusive`) — the caret belongs on this line.
3362
+ * (`start <= offset < endExclusive`), or a zero-length visual-line
3363
+ * anchor sits at the offset — the caret belongs on this line.
1626
3364
  * - `'end'`: the offset is only some run's trailing boundary
1627
3365
  * (`offset === endExclusive`) with no run covering it — a line-break
1628
3366
  * boundary the caret should leave for the next line.
@@ -1635,23 +3373,42 @@ export declare class VisualLine {
1635
3373
  */
1636
3374
  sourceDistanceTo(offset: SourceOffset): number;
1637
3375
  /**
1638
- * x of the caret position before `offset` on this line. When `offset`
1639
- * is past all runs (trailing whitespace / blank line), returns the
1640
- * right edge of the last run; when before all runs, returns the left
1641
- * edge of the first run.
3376
+ * x of the caret position before `offset` on this line.
3377
+ *
3378
+ * The runs tile the source but are stored in paint order, not sorted by
3379
+ * source offset (hidden-marker runs are appended last). So this scans all
3380
+ * runs rather than assuming any ordering:
3381
+ *
3382
+ * - A zero-source visual anchor owns its exact offset, so a marker-only line
3383
+ * wins over the preceding line's inclusive end boundary.
3384
+ * - Otherwise a run starting at `offset` owns that seam. This keeps an
3385
+ * out-of-flow prefix from placing the caret at its trailing edge when the
3386
+ * following body starts at a visually separate x.
3387
+ * - Otherwise, if some run *covers* `offset`, its own geometry places the
3388
+ * caret (exact glyph boundary for text runs). In the active,
3389
+ * markers-visible form every interior offset is covered, so this branch
3390
+ * keeps distinct offsets distinct.
3391
+ * - Otherwise `offset` sits in a gap — a hidden inline marker such as the
3392
+ * `**` of `**bold**`, or before/after the painted text. It snaps to the
3393
+ * seam between the source-nearest runs on either side: the right edge of
3394
+ * the closest run ending at/before `offset`, else the left edge of the
3395
+ * closest run starting at/after it. A hidden marker collapses to zero
3396
+ * width, so both edges coincide at the seam.
1642
3397
  */
1643
3398
  xAtOffset(offset: SourceOffset): number;
1644
3399
  /**
1645
3400
  * Snap `x` to the nearest offset on this line. If `x` falls inside a
1646
- * run, the offset is interpolated by character fraction; otherwise it
1647
- * snaps to the closer edge of the nearest run.
3401
+ * run, the run resolves the offset (exact glyph boundary for text runs,
3402
+ * nearer edge for source-less runs); otherwise it snaps to the closer
3403
+ * edge of the nearest run.
1648
3404
  */
1649
3405
  offsetAtX(x: number): SourceOffset;
1650
3406
  }
1651
3407
 
1652
3408
  /**
1653
3409
  * Geometry of the rendered document, as a map from source offsets to 2D
1654
- * positions and back.
3410
+ * positions and back. All geometry is expressed in the editor overlay's local
3411
+ * CSS-pixel coordinate space.
1655
3412
  *
1656
3413
  * Structure (top to bottom):
1657
3414
  *
@@ -1686,7 +3443,9 @@ export declare class VisualLineMap {
1686
3443
  static measure(blockViews: readonly {
1687
3444
  readonly absoluteStart: number;
1688
3445
  readonly viewNode: ViewNode;
1689
- }[]): VisualLineMap;
3446
+ }[], coordinateSpace: EditorCoordinateSpace, transform?: EditorCoordinateTransform): VisualLineMap;
3447
+ /** Lines backed by source ranges, excluding source-less cursor lines. */
3448
+ readonly sourceLines: readonly VisualLine[];
1690
3449
  constructor(lines: readonly VisualLine[]);
1691
3450
  get lineCount(): number;
1692
3451
  get isEmpty(): boolean;
@@ -1711,6 +3470,12 @@ export declare class VisualLineMap {
1711
3470
  * {@link lineIndexOfOffset}. Returns `0` when the map is empty.
1712
3471
  */
1713
3472
  xAtOffset(offset: SourceOffset): number;
3473
+ /**
3474
+ * Line occupied by a source or virtual cursor position. A virtual position
3475
+ * returns `undefined` until its corresponding DOM line has been measured.
3476
+ */
3477
+ lineIndexOfPosition(position: CursorPosition): number | undefined;
3478
+ xAtPosition(position: CursorPosition): number;
1714
3479
  /**
1715
3480
  * Line whose vertical band contains `y`, clamped to the first/last
1716
3481
  * line when `y` is outside the document.
@@ -1724,6 +3489,9 @@ export declare class VisualLineMap {
1724
3489
  offsetAtPoint(point: Point2D): SourceOffset;
1725
3490
  /** Snap `x` to the nearest offset on a specific line. */
1726
3491
  offsetInLineAtX(lineIndex: number, x: number): SourceOffset;
3492
+ positionInLineAtX(lineIndex: number, x: number): CursorPosition;
3493
+ lineStartOffset(lineIndex: number): SourceOffset | undefined;
3494
+ lineEndOffset(lineIndex: number): SourceOffset | undefined;
1727
3495
  }
1728
3496
 
1729
3497
  /**
@@ -1732,14 +3500,22 @@ export declare class VisualLineMap {
1732
3500
  * When constructed with a {@link VisualRunSource}, `xAtOffset` returns the
1733
3501
  * pixel-exact x of the caret before character `offset` by measuring the
1734
3502
  * prefix `[textNodeStart, textNodeStart + (offset - sourceStart))` with a
1735
- * DOM `Range`. Without a source it falls back to linear interpolation
1736
- * across `rect.width`.
3503
+ * DOM `Range`.
3504
+ *
3505
+ * A source-less run has no per-offset geometry: it either represents an
3506
+ * element-only block (KaTeX math, a mermaid/custom diagram, an image, an
3507
+ * inactive `<hr>`) whose box does not correspond to source offsets, or a
3508
+ * hand-built run in a test. Either way it maps between offsets and x by
3509
+ * snapping to the nearer edge of {@link rect} rather than fabricating
3510
+ * interior positions.
1737
3511
  */
1738
3512
  export declare class VisualRun {
1739
3513
  readonly sourceRange: OffsetRange;
1740
3514
  readonly rect: Rect2D;
1741
3515
  readonly source?: VisualRunSource | undefined;
1742
- constructor(sourceRange: OffsetRange, rect: Rect2D, source?: VisualRunSource | undefined);
3516
+ readonly isVisualLineAnchor: boolean;
3517
+ static visualLineAnchor(sourceOffset: SourceOffset, rect: Rect2D): VisualRun;
3518
+ constructor(sourceRange: OffsetRange, rect: Rect2D, source?: VisualRunSource | undefined, isVisualLineAnchor?: boolean);
1743
3519
  get sourceStart(): SourceOffset;
1744
3520
  get sourceEndExclusive(): SourceOffset;
1745
3521
  get sourceLength(): number;
@@ -1751,19 +3527,32 @@ export declare class VisualRun {
1751
3527
 
1752
3528
  /**
1753
3529
  * The DOM source of a {@link VisualRun}. When set, `xAtOffset` and
1754
- * `offsetAtX` measure exact glyph positions via `Range.getBoundingClientRect`
1755
- * instead of linear interpolation across the run's rect. This matters for
1756
- * proportional fonts where character widths differ a lot (e.g. `m` vs `i`)
1757
- * and a caret placed by interpolation lands several pixels inside the
1758
- * wrong character.
3530
+ * `offsetAtX` measure exact glyph positions via `Range.getBoundingClientRect`.
3531
+ * This matters for proportional fonts where character widths differ a lot
3532
+ * (e.g. `m` vs `i`): a caret placed by anything coarser than real glyph
3533
+ * measurement lands several pixels inside the wrong character.
1759
3534
  *
1760
- * Hand-built runs (tests) omit this; their `xAtOffset` falls back to
1761
- * linear interpolation.
3535
+ * A run without a source has no per-offset geometry, so it maps between
3536
+ * offsets and x by snapping to the nearer run edge. Real text runs always
3537
+ * carry a source; source-less runs are element-only blocks (see
3538
+ * {@link _appendElementBlockRun}) and hand-built runs in tests.
1762
3539
  */
1763
3540
  declare interface VisualRunSource {
1764
3541
  readonly textNode: Text;
1765
3542
  /** Offset within `textNode.data` corresponding to `sourceRange.start`. */
1766
3543
  readonly textNodeStart: number;
3544
+ readonly coordinateSpace: EditorCoordinateSpace;
3545
+ }
3546
+
3547
+ export declare const vscodeHostKeyboardProfile: KeyboardProfile;
3548
+
3549
+ export declare const vscodeKeyboardProfile: KeyboardProfile;
3550
+
3551
+ export declare const vscodeLocalKeyboardProfile: KeyboardProfile;
3552
+
3553
+ export declare interface WordNavigationConfig {
3554
+ readonly wordSeparators: string;
3555
+ readonly wordSegmenterLocales: readonly string[];
1767
3556
  }
1768
3557
 
1769
3558
  export { }