@vscode/markdown-editor 0.0.2-1 → 0.0.2-10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +313 -25
- package/dist/index.js +1674 -1175
- package/dist/index.js.map +1 -1
- package/dist/observables.js +90 -114
- package/dist/observables.js.map +1 -1
- package/dist/{runOnChange-owE1SMC0.js → runOnChange-C00UIwqQ.js} +130 -106
- package/dist/runOnChange-C00UIwqQ.js.map +1 -0
- package/package.json +14 -7
- package/src/view/editor.css +146 -19
- package/src/view/themes/github.css +0 -5
- package/src/view/themes/vscode.css +331 -0
- package/dist/runOnChange-owE1SMC0.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export declare abstract class AstNode {
|
|
|
31
31
|
* instances — keeping this O(children), not O(subtree). Leaves have no
|
|
32
32
|
* children, so {@link _localEquals} is their whole comparison.
|
|
33
33
|
*/
|
|
34
|
-
|
|
34
|
+
equalsShallow(other: AstNode): boolean;
|
|
35
35
|
/** Compares only this node's own scalar fields (kind/length already match). */
|
|
36
36
|
protected _localEquals(_other: this): boolean;
|
|
37
37
|
/**
|
|
@@ -54,8 +54,41 @@ declare interface AstVisualizationNode {
|
|
|
54
54
|
children?: AstVisualizationNode[];
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Strategy for hosts that never deliver native clipboard events to the editor
|
|
59
|
+
* — most importantly VS Code webviews, whose preload calls `preventDefault()`
|
|
60
|
+
* on the Ctrl/Cmd+C/X/V keydowns, so no `copy`/`cut`/`paste` event is ever
|
|
61
|
+
* dispatched. Here the keystrokes are the only signal, so this strategy
|
|
62
|
+
* listens for them directly and drives the async {@link Clipboard} API
|
|
63
|
+
* (`navigator.clipboard`), which webviews are granted.
|
|
64
|
+
*
|
|
65
|
+
* Cut deletes synchronously once the text is captured; the clipboard write is
|
|
66
|
+
* fire-and-forget. Paste must wait for the async read before inserting.
|
|
67
|
+
*/
|
|
68
|
+
export declare class AsyncClipboardStrategy implements IClipboardStrategy {
|
|
69
|
+
private readonly _clipboard;
|
|
70
|
+
constructor(_clipboard?: Clipboard);
|
|
71
|
+
connect(context: IClipboardContext): IDisposable;
|
|
72
|
+
}
|
|
73
|
+
|
|
57
74
|
export declare type BlockAstNode = HeadingAstNode | ParagraphAstNode | CodeBlockAstNode | MathBlockAstNode | ThematicBreakAstNode | BlockQuoteAstNode | ListAstNode | TableAstNode;
|
|
58
75
|
|
|
76
|
+
/**
|
|
77
|
+
* A block-level node. Every block may carry a {@link leadingTrivia} glue — the
|
|
78
|
+
* whitespace that precedes it on its own line (a nested list's indentation, the
|
|
79
|
+
* leading space of a continued paragraph). It is owned by the block it precedes
|
|
80
|
+
* (not the one it trails), so the view reveals it exactly when *this* block is
|
|
81
|
+
* active, and it tiles at the block's front: {@link children} prepends it to the
|
|
82
|
+
* block's own content while `content` stays the block's real payload.
|
|
83
|
+
*/
|
|
84
|
+
declare abstract class BlockAstNodeBase extends AstNode {
|
|
85
|
+
abstract readonly leadingTrivia?: GlueAstNode;
|
|
86
|
+
/** This block with its leading trivia replaced — re-homes a leading glue onto it. */
|
|
87
|
+
abstract withLeadingTrivia(trivia: GlueAstNode | undefined): BlockAstNode;
|
|
88
|
+
/** Prepends {@link leadingTrivia}, if any, ahead of the block's own children. */
|
|
89
|
+
protected _withLeading(own: readonly AstNode[]): readonly AstNode[];
|
|
90
|
+
}
|
|
91
|
+
|
|
59
92
|
/**
|
|
60
93
|
* One block's place in the rendered document.
|
|
61
94
|
*
|
|
@@ -79,13 +112,15 @@ export declare interface BlockMeasurement {
|
|
|
79
112
|
readonly viewNode: ViewNode | undefined;
|
|
80
113
|
}
|
|
81
114
|
|
|
82
|
-
export declare class BlockQuoteAstNode extends
|
|
115
|
+
export declare class BlockQuoteAstNode extends BlockAstNodeBase {
|
|
83
116
|
readonly content: readonly (MarkerAstNode | BlockAstNode | GlueAstNode)[];
|
|
117
|
+
readonly leadingTrivia?: GlueAstNode | undefined;
|
|
84
118
|
readonly kind = "blockQuote";
|
|
85
|
-
constructor(content: readonly (MarkerAstNode | BlockAstNode | GlueAstNode)[]);
|
|
119
|
+
constructor(content: readonly (MarkerAstNode | BlockAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
|
|
86
120
|
get children(): readonly AstNode[];
|
|
87
121
|
get blocks(): readonly BlockAstNode[];
|
|
88
122
|
mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
|
|
123
|
+
withLeadingTrivia(trivia: GlueAstNode | undefined): BlockQuoteAstNode;
|
|
89
124
|
}
|
|
90
125
|
|
|
91
126
|
declare class BlockQuoteViewData {
|
|
@@ -163,13 +198,14 @@ export declare interface BlockViewOptions {
|
|
|
163
198
|
readonly renderMath?: (request: MathRenderRequest) => MathRendering | undefined;
|
|
164
199
|
}
|
|
165
200
|
|
|
166
|
-
export declare class CodeBlockAstNode extends
|
|
201
|
+
export declare class CodeBlockAstNode extends BlockAstNodeBase {
|
|
167
202
|
readonly language: string;
|
|
168
203
|
readonly content: readonly (MarkerAstNode | GlueAstNode)[];
|
|
204
|
+
readonly leadingTrivia?: GlueAstNode | undefined;
|
|
169
205
|
readonly kind = "codeBlock";
|
|
170
206
|
private _previous?;
|
|
171
207
|
private _contentEdit?;
|
|
172
|
-
constructor(language: string, content: readonly (MarkerAstNode | GlueAstNode)[]);
|
|
208
|
+
constructor(language: string, content: readonly (MarkerAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
|
|
173
209
|
get children(): readonly AstNode[];
|
|
174
210
|
get openFence(): MarkerAstNode | undefined;
|
|
175
211
|
get closeFence(): MarkerAstNode | undefined;
|
|
@@ -177,6 +213,7 @@ export declare class CodeBlockAstNode extends AstNode {
|
|
|
177
213
|
/** Relative start offset of the {@link code} marker within this block. */
|
|
178
214
|
get codeOffset(): number;
|
|
179
215
|
mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
|
|
216
|
+
withLeadingTrivia(trivia: GlueAstNode | undefined): CodeBlockAstNode;
|
|
180
217
|
protected _localEquals(o: this): boolean;
|
|
181
218
|
/**
|
|
182
219
|
* A copy of this block carrying an incremental link to `previous`:
|
|
@@ -301,6 +338,13 @@ export declare class CursorView extends Disposable {
|
|
|
301
338
|
export declare interface CursorViewOptions {
|
|
302
339
|
readonly offset: IObservable<SourceOffset | undefined>;
|
|
303
340
|
readonly visualLineMap: IObservable<VisualLineMap>;
|
|
341
|
+
/**
|
|
342
|
+
* When set, the caret is drawn over the transient empty paragraph instead
|
|
343
|
+
* of at {@link offset} — its rect (in client coordinates) comes straight
|
|
344
|
+
* from that synthetic element's geometry, since it has no visual-line-map
|
|
345
|
+
* entry. Takes priority over the normal offset-based placement.
|
|
346
|
+
*/
|
|
347
|
+
readonly pendingCaretRect?: IObservable<Rect2D | undefined>;
|
|
304
348
|
}
|
|
305
349
|
|
|
306
350
|
export declare class CursorViewRendering {
|
|
@@ -346,13 +390,14 @@ declare interface DocumentBlockViewData {
|
|
|
346
390
|
readonly view: BlockViewData;
|
|
347
391
|
}
|
|
348
392
|
|
|
349
|
-
/** A mounted document child: a block
|
|
393
|
+
/** A mounted document child: a block, a run of inter-block glue, or the
|
|
394
|
+
* transient empty paragraph (see {@link PendingParagraphViewData}). */
|
|
350
395
|
declare interface DocumentChildViewData {
|
|
351
396
|
readonly absoluteStart: number;
|
|
352
|
-
/** For a block: selection reaches it. For glue:
|
|
397
|
+
/** For a block: selection reaches it. For glue: always false (unowned, hidden). */
|
|
353
398
|
readonly isActive: boolean;
|
|
354
|
-
readonly view: BlockViewData | GlueViewData;
|
|
355
|
-
readonly kind: 'block' | 'glue';
|
|
399
|
+
readonly view: BlockViewData | GlueViewData | PendingParagraphViewData;
|
|
400
|
+
readonly kind: 'block' | 'glue' | 'pendingParagraph';
|
|
356
401
|
}
|
|
357
402
|
|
|
358
403
|
/**
|
|
@@ -408,6 +453,8 @@ declare class DocumentViewData {
|
|
|
408
453
|
*/
|
|
409
454
|
export declare class DocumentViewNode extends ViewNode {
|
|
410
455
|
readonly blocks: readonly DocumentBlock[];
|
|
456
|
+
/** The transient empty-paragraph element, when one is armed. */
|
|
457
|
+
readonly pendingElement?: HTMLElement | undefined;
|
|
411
458
|
static create(viewData: DocumentViewData, options: BlockViewOptions | undefined, previous: DocumentViewNode | undefined): DocumentViewNode;
|
|
412
459
|
private constructor();
|
|
413
460
|
/** The stable content element this document mounts its children into. */
|
|
@@ -442,7 +489,7 @@ export declare class EditorController extends Disposable {
|
|
|
442
489
|
private readonly _model;
|
|
443
490
|
private readonly _view;
|
|
444
491
|
private _desiredColumn;
|
|
445
|
-
constructor(_model: EditorModel, _view: EditorView);
|
|
492
|
+
constructor(_model: EditorModel, _view: EditorView, options?: EditorControllerOptions);
|
|
446
493
|
private readonly _handleTextUpdate;
|
|
447
494
|
private readonly _handleMouseDown;
|
|
448
495
|
private _makeCursorContext;
|
|
@@ -454,11 +501,25 @@ export declare class EditorController extends Disposable {
|
|
|
454
501
|
cursorDown(extend?: boolean): void;
|
|
455
502
|
/** Move the cursor up one visual line (Arrow Up). */
|
|
456
503
|
cursorUp(extend?: boolean): void;
|
|
457
|
-
private readonly _handleCopy;
|
|
458
|
-
private readonly _handleCut;
|
|
459
|
-
private readonly _handlePaste;
|
|
460
504
|
private _selectedText;
|
|
505
|
+
private readonly _updateModifierState;
|
|
506
|
+
private readonly _clearModifierState;
|
|
461
507
|
private readonly _handleKeyDown;
|
|
508
|
+
/**
|
|
509
|
+
* Context-aware Enter: splits / line-breaks via {@link insertSmartEnter}, or
|
|
510
|
+
* arms a transient empty paragraph when at the end of a paragraph.
|
|
511
|
+
*/
|
|
512
|
+
private _smartEnter;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/** Options for an {@link EditorController}. */
|
|
516
|
+
export declare interface EditorControllerOptions {
|
|
517
|
+
/**
|
|
518
|
+
* How copy/cut/paste is handled. Defaults to {@link NativeClipboardStrategy},
|
|
519
|
+
* which reads the browser's native clipboard events — pass a different
|
|
520
|
+
* strategy (e.g. `AsyncClipboardStrategy`) in hosts that swallow them.
|
|
521
|
+
*/
|
|
522
|
+
readonly clipboardStrategy?: IClipboardStrategy;
|
|
462
523
|
}
|
|
463
524
|
|
|
464
525
|
export declare class EditorModel {
|
|
@@ -476,6 +537,20 @@ export declare class EditorModel {
|
|
|
476
537
|
* (e.g. an inactive/unfocused rendering).
|
|
477
538
|
*/
|
|
478
539
|
readonly selection: ISettableObservable<Selection_2 | undefined, void>;
|
|
540
|
+
/**
|
|
541
|
+
* Whether a Ctrl/Cmd modifier is currently held. Set by the controller from
|
|
542
|
+
* live keyboard state; the view reads it to show the link-open affordance
|
|
543
|
+
* (underline + pointer cursor) only while a Ctrl/Cmd+click would open a link
|
|
544
|
+
* whose block is active.
|
|
545
|
+
*/
|
|
546
|
+
readonly ctrlOrMetaDown: ISettableObservable<boolean, void>;
|
|
547
|
+
/**
|
|
548
|
+
* Gutter markers (source-control style change indicators) painted in the
|
|
549
|
+
* left gutter. Each entry maps a source {@link OffsetRange} to a change kind
|
|
550
|
+
* — see {@link GutterMarker}. Purely decorative: markers never affect the
|
|
551
|
+
* parsed {@link document}, selection, or layout. Empty by default.
|
|
552
|
+
*/
|
|
553
|
+
readonly gutterMarkers: ISettableObservable<readonly GutterMarker[], void>;
|
|
479
554
|
/**
|
|
480
555
|
* Forces the rendered active-block set. `undefined` (the default)
|
|
481
556
|
* derives the set from the current selection range (see
|
|
@@ -484,6 +559,13 @@ export declare class EditorModel {
|
|
|
484
559
|
* collapsed/inactive rendering.
|
|
485
560
|
*/
|
|
486
561
|
readonly activeBlocksOverride: ISettableObservable<readonly BlockAstNode[] | typeof NO_ACTIVE_BLOCKS | undefined, void>;
|
|
562
|
+
/**
|
|
563
|
+
* The transient empty-paragraph editing state, or `undefined` when none is
|
|
564
|
+
* armed. See {@link PendingParagraph}. This is *not* document data — it is
|
|
565
|
+
* cleared by any source edit and lives only between the Enter that armed it
|
|
566
|
+
* and the next keystroke.
|
|
567
|
+
*/
|
|
568
|
+
readonly pendingParagraph: ISettableObservable<PendingParagraph | undefined, void>;
|
|
487
569
|
readonly cursorOffset: IObservableWithChange<number | undefined, void>;
|
|
488
570
|
/**
|
|
489
571
|
* The parsed document. Threads the previous document into the parser so
|
|
@@ -507,6 +589,24 @@ export declare class EditorModel {
|
|
|
507
589
|
* collapsed this is a one-element set holding {@link activeBlock}.
|
|
508
590
|
*/
|
|
509
591
|
readonly activeBlocks: IObservableWithChange<Set<BlockAstNode>, void>;
|
|
592
|
+
/**
|
|
593
|
+
* Arm a {@link PendingParagraph} at the given gap, minting a fresh synthetic
|
|
594
|
+
* AST node for it, and park the caret at the gap start. No source edit is
|
|
595
|
+
* applied — the blank line exists only in the view until it is materialized.
|
|
596
|
+
*/
|
|
597
|
+
armPendingParagraph(req: {
|
|
598
|
+
anchorBlock: BlockAstNode;
|
|
599
|
+
replaceRange: OffsetRange;
|
|
600
|
+
atEof: boolean;
|
|
601
|
+
}): void;
|
|
602
|
+
/** Discard the pending paragraph (if any) without touching the source. */
|
|
603
|
+
cancelPendingParagraph(): void;
|
|
604
|
+
/**
|
|
605
|
+
* Turn the pending paragraph into real source: rewrite its gap so the typed
|
|
606
|
+
* `text` becomes its own paragraph, separated from its neighbours by blank
|
|
607
|
+
* lines, and place the caret after the inserted text.
|
|
608
|
+
*/
|
|
609
|
+
materializePendingParagraph(text: string): void;
|
|
510
610
|
applyEdit(edit: StringEdit): void;
|
|
511
611
|
applyEditForSelection(edit: StringEdit): void;
|
|
512
612
|
}
|
|
@@ -540,8 +640,16 @@ export declare class EditorView extends Disposable {
|
|
|
540
640
|
readonly element: HTMLElement;
|
|
541
641
|
readonly editContext: EditContext;
|
|
542
642
|
readonly measuredLayout: MeasuredLayoutModel;
|
|
643
|
+
/**
|
|
644
|
+
* Inner container that holds the rendered document and the cursor/selection
|
|
645
|
+
* overlays. The outer {@link element} spans the full width; this container
|
|
646
|
+
* is what limited-width mode caps and centers, so the overlays (which anchor
|
|
647
|
+
* to their parent's box) stay aligned with the content.
|
|
648
|
+
*/
|
|
649
|
+
private readonly _contentContainer;
|
|
543
650
|
private readonly _cursorView;
|
|
544
651
|
private readonly _selectionView;
|
|
652
|
+
private readonly _gutterMarkersView;
|
|
545
653
|
/**
|
|
546
654
|
* The mounted block sequence, in source order. Rebuilt (not mutated) each
|
|
547
655
|
* frame by {@link DocumentViewNode.create}; the view just swaps one
|
|
@@ -561,6 +669,13 @@ export declare class EditorView extends Disposable {
|
|
|
561
669
|
/** The current view-data tree (AST overlaid with selection flags), for debugging. */
|
|
562
670
|
private readonly _viewData;
|
|
563
671
|
get viewData(): IObservable<DocumentViewData | undefined>;
|
|
672
|
+
/**
|
|
673
|
+
* Caret rect (client coords) for the transient empty paragraph, or
|
|
674
|
+
* `undefined` when none is armed. Set each frame from the synthetic
|
|
675
|
+
* paragraph element's geometry and fed to the {@link CursorView}, which has
|
|
676
|
+
* no visual-line-map entry to place the caret from otherwise.
|
|
677
|
+
*/
|
|
678
|
+
private readonly _pendingCaretRect;
|
|
564
679
|
/**
|
|
565
680
|
* The block cache projected for views (selection painting) that need to
|
|
566
681
|
* react to mount/unmount. Derived from {@link _document}, so it stays in
|
|
@@ -568,6 +683,13 @@ export declare class EditorView extends Disposable {
|
|
|
568
683
|
*/
|
|
569
684
|
private readonly _selectionBlocksObs;
|
|
570
685
|
constructor(_model: EditorModel, _options?: EditorViewOptions | undefined);
|
|
686
|
+
/**
|
|
687
|
+
* Mirrors the model's live Ctrl/Cmd state onto the editor root as
|
|
688
|
+
* `.md-mod-down` so CSS can show the link-open underline and pointer cursor
|
|
689
|
+
* only while a click would actually open the link: an inactive link opens on
|
|
690
|
+
* a plain click, but an active link only opens with the modifier held.
|
|
691
|
+
*/
|
|
692
|
+
private _setupModifierTracking;
|
|
571
693
|
focus(): void;
|
|
572
694
|
/**
|
|
573
695
|
* Client coordinates → absolute source offset (any block). Used during
|
|
@@ -603,6 +725,16 @@ export declare interface EditorViewOptions extends BlockViewOptions {
|
|
|
603
725
|
* only) unless a theme class is supplied.
|
|
604
726
|
*/
|
|
605
727
|
readonly classNames?: readonly string[];
|
|
728
|
+
/**
|
|
729
|
+
* Controls "limited width mode". The observable yields the maximum content
|
|
730
|
+
* width in pixels, or `undefined` to let the content fill the available
|
|
731
|
+
* width. When the option is omitted, the width is capped at
|
|
732
|
+
* {@link DEFAULT_LIMITED_WIDTH}px (limited mode is on by default).
|
|
733
|
+
*
|
|
734
|
+
* The cap and centering apply to an inner content container; the editor
|
|
735
|
+
* root ({@link element}) always spans the full available width.
|
|
736
|
+
*/
|
|
737
|
+
readonly limitedWidth?: IObservable<number | undefined>;
|
|
606
738
|
}
|
|
607
739
|
|
|
608
740
|
export declare class EmphasisAstNode extends AstNode {
|
|
@@ -670,14 +802,39 @@ declare class GlueViewData {
|
|
|
670
802
|
decorateNewline: boolean);
|
|
671
803
|
}
|
|
672
804
|
|
|
673
|
-
|
|
805
|
+
/**
|
|
806
|
+
* A single gutter marker: a source {@link OffsetRange} tagged with a
|
|
807
|
+
* {@link GutterMarkerType}. The view resolves the range to the visual lines it
|
|
808
|
+
* covers and paints a bar (or, for `deleted`, a wedge at the range position) in
|
|
809
|
+
* the left gutter.
|
|
810
|
+
*
|
|
811
|
+
* A `deleted` marker is normally an empty range (`range.isEmpty`) sitting at the
|
|
812
|
+
* boundary where the removed text used to be — there is nothing left to span,
|
|
813
|
+
* so it is drawn as a caret between lines rather than a bar.
|
|
814
|
+
*/
|
|
815
|
+
export declare interface GutterMarker {
|
|
816
|
+
readonly range: OffsetRange;
|
|
817
|
+
readonly type: GutterMarkerType;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
/**
|
|
821
|
+
* The kind of change a gutter marker represents, mirroring the three states a
|
|
822
|
+
* source-control diff distinguishes (the git change markers in the editor
|
|
823
|
+
* gutter): a freshly inserted region, an edited region, and a point where
|
|
824
|
+
* content was removed.
|
|
825
|
+
*/
|
|
826
|
+
export declare type GutterMarkerType = 'added' | 'modified' | 'deleted';
|
|
827
|
+
|
|
828
|
+
export declare class HeadingAstNode extends BlockAstNodeBase {
|
|
674
829
|
readonly level: 1 | 2 | 3 | 4 | 5 | 6;
|
|
675
830
|
readonly marker: MarkerAstNode;
|
|
676
831
|
readonly content: readonly (InlineAstNode | GlueAstNode)[];
|
|
832
|
+
readonly leadingTrivia?: GlueAstNode | undefined;
|
|
677
833
|
readonly kind = "heading";
|
|
678
|
-
constructor(level: 1 | 2 | 3 | 4 | 5 | 6, marker: MarkerAstNode, content: readonly (InlineAstNode | GlueAstNode)[]);
|
|
834
|
+
constructor(level: 1 | 2 | 3 | 4 | 5 | 6, marker: MarkerAstNode, content: readonly (InlineAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
|
|
679
835
|
get children(): readonly AstNode[];
|
|
680
836
|
mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
|
|
837
|
+
withLeadingTrivia(trivia: GlueAstNode | undefined): HeadingAstNode;
|
|
681
838
|
protected _localEquals(o: this): boolean;
|
|
682
839
|
}
|
|
683
840
|
|
|
@@ -688,6 +845,42 @@ declare class HeadingViewData {
|
|
|
688
845
|
constructor(ast: HeadingAstNode, content: readonly AnyViewData[]);
|
|
689
846
|
}
|
|
690
847
|
|
|
848
|
+
/**
|
|
849
|
+
* The editor operations a clipboard strategy drives. The strategy never
|
|
850
|
+
* touches the model or the DOM directly — it asks through this seam, so the
|
|
851
|
+
* same strategy works regardless of how the editor is wired up.
|
|
852
|
+
*/
|
|
853
|
+
export declare interface IClipboardContext {
|
|
854
|
+
/** The element that owns focus and receives clipboard/keyboard events. */
|
|
855
|
+
readonly element: HTMLElement;
|
|
856
|
+
/** The selected source text, or `undefined` when the selection is empty. */
|
|
857
|
+
getSelectedText(): string | undefined;
|
|
858
|
+
/** Delete the current selection (the cut half of cut). */
|
|
859
|
+
deleteSelection(): void;
|
|
860
|
+
/** Insert text at the caret, replacing any selection (the paste action). */
|
|
861
|
+
insertText(text: string): void;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
/**
|
|
865
|
+
* How copy/cut/paste intent reaches the editor. Host environments deliver it
|
|
866
|
+
* differently, so the controller owns no clipboard logic itself — it
|
|
867
|
+
* {@link connect}s a strategy and lets it install whatever listeners it needs.
|
|
868
|
+
*
|
|
869
|
+
* Two implementations ship:
|
|
870
|
+
* - {@link NativeClipboardStrategy} (default) reads the browser's native
|
|
871
|
+
* `copy`/`cut`/`paste` events and their synchronous `clipboardData`.
|
|
872
|
+
* - {@link AsyncClipboardStrategy} drives the async `navigator.clipboard` API
|
|
873
|
+
* from Ctrl/Cmd+C/X/V keystrokes, for hosts (e.g. VS Code webviews) that
|
|
874
|
+
* swallow the native clipboard events before they reach the editor.
|
|
875
|
+
*/
|
|
876
|
+
export declare interface IClipboardStrategy {
|
|
877
|
+
/**
|
|
878
|
+
* Wire up clipboard handling against `context`. The returned disposable
|
|
879
|
+
* tears down every listener the strategy installed.
|
|
880
|
+
*/
|
|
881
|
+
connect(context: IClipboardContext): IDisposable;
|
|
882
|
+
}
|
|
883
|
+
|
|
691
884
|
/** The Monarch language definitions the default highlighter wires up. */
|
|
692
885
|
export declare interface IDefaultMonarchGrammars {
|
|
693
886
|
typescript: unknown;
|
|
@@ -782,6 +975,21 @@ export declare const insertLineBreak: EditCommand;
|
|
|
782
975
|
|
|
783
976
|
export declare const insertParagraph: EditCommand;
|
|
784
977
|
|
|
978
|
+
/**
|
|
979
|
+
* Context-aware Enter. The behaviour is chosen from the active block:
|
|
980
|
+
* - paragraph / heading / thematic break — the "rich text" thing: at the
|
|
981
|
+
* block's end arm a transient empty paragraph (see {@link SmartEnterResult});
|
|
982
|
+
* elsewhere split into two paragraphs (`\n\n`).
|
|
983
|
+
* - code block — insert a newline that preserves the current line's indentation,
|
|
984
|
+
* staying inside the fence.
|
|
985
|
+
* - block quote — continue the quote (`\n> `); an empty quote line exits it.
|
|
986
|
+
* - list — continue the list with the next marker (incrementing ordered
|
|
987
|
+
* numbers, re-emitting task checkboxes); an empty item exits the list.
|
|
988
|
+
* A non-collapsed selection, or any other block, falls back to a plain soft line
|
|
989
|
+
* break, preserving today's behaviour.
|
|
990
|
+
*/
|
|
991
|
+
export declare const insertSmartEnter: (ctx: CursorCommandContext) => SmartEnterResult;
|
|
992
|
+
|
|
785
993
|
export declare function insertText(text: string): EditCommand;
|
|
786
994
|
|
|
787
995
|
/**
|
|
@@ -886,14 +1094,16 @@ declare class LinkViewData {
|
|
|
886
1094
|
constructor(ast: LinkAstNode, content: readonly AnyViewData[]);
|
|
887
1095
|
}
|
|
888
1096
|
|
|
889
|
-
export declare class ListAstNode extends
|
|
1097
|
+
export declare class ListAstNode extends BlockAstNodeBase {
|
|
890
1098
|
readonly ordered: boolean;
|
|
891
1099
|
readonly content: readonly (ListItemAstNode | GlueAstNode)[];
|
|
1100
|
+
readonly leadingTrivia?: GlueAstNode | undefined;
|
|
892
1101
|
readonly kind = "list";
|
|
893
|
-
constructor(ordered: boolean, content: readonly (ListItemAstNode | GlueAstNode)[]);
|
|
1102
|
+
constructor(ordered: boolean, content: readonly (ListItemAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
|
|
894
1103
|
get children(): readonly AstNode[];
|
|
895
1104
|
get items(): readonly ListItemAstNode[];
|
|
896
1105
|
mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
|
|
1106
|
+
withLeadingTrivia(trivia: GlueAstNode | undefined): ListAstNode;
|
|
897
1107
|
protected _localEquals(o: this): boolean;
|
|
898
1108
|
}
|
|
899
1109
|
|
|
@@ -907,6 +1117,7 @@ export declare class ListItemAstNode extends AstNode {
|
|
|
907
1117
|
get children(): readonly AstNode[];
|
|
908
1118
|
get blocks(): readonly BlockAstNode[];
|
|
909
1119
|
mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
|
|
1120
|
+
withLeadingTrivia(trivia: GlueAstNode | undefined): ListItemAstNode;
|
|
910
1121
|
protected _localEquals(o: this): boolean;
|
|
911
1122
|
}
|
|
912
1123
|
|
|
@@ -960,13 +1171,15 @@ declare class MarkerViewData {
|
|
|
960
1171
|
constructor(ast: MarkerAstNode, visible: boolean);
|
|
961
1172
|
}
|
|
962
1173
|
|
|
963
|
-
export declare class MathBlockAstNode extends
|
|
1174
|
+
export declare class MathBlockAstNode extends BlockAstNodeBase {
|
|
964
1175
|
readonly content: readonly (MarkerAstNode | GlueAstNode)[];
|
|
1176
|
+
readonly leadingTrivia?: GlueAstNode | undefined;
|
|
965
1177
|
readonly kind = "mathBlock";
|
|
966
|
-
constructor(content: readonly (MarkerAstNode | GlueAstNode)[]);
|
|
1178
|
+
constructor(content: readonly (MarkerAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
|
|
967
1179
|
get children(): readonly AstNode[];
|
|
968
1180
|
get code(): MarkerAstNode | undefined;
|
|
969
1181
|
mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
|
|
1182
|
+
withLeadingTrivia(trivia: GlueAstNode | undefined): MathBlockAstNode;
|
|
970
1183
|
}
|
|
971
1184
|
|
|
972
1185
|
declare class MathBlockViewData {
|
|
@@ -1129,6 +1342,17 @@ export declare class MonacoSyntaxHighlighter implements ISyntaxHighlighter {
|
|
|
1129
1342
|
private _tokenizerFor;
|
|
1130
1343
|
}
|
|
1131
1344
|
|
|
1345
|
+
/**
|
|
1346
|
+
* Default strategy: handle the browser's native `copy`/`cut`/`paste` events,
|
|
1347
|
+
* reading and writing the synchronous {@link ClipboardEvent.clipboardData}.
|
|
1348
|
+
* This is the standard rich-editor approach and works wherever the browser
|
|
1349
|
+
* actually dispatches those events to the focused element (e.g. a standalone
|
|
1350
|
+
* web page).
|
|
1351
|
+
*/
|
|
1352
|
+
export declare class NativeClipboardStrategy implements IClipboardStrategy {
|
|
1353
|
+
connect(context: IClipboardContext): IDisposable;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1132
1356
|
/**
|
|
1133
1357
|
* Move the cursor one position left or right, skipping over hidden marker
|
|
1134
1358
|
* ranges in inactive blocks (and inactive items of an active list).
|
|
@@ -1164,12 +1388,14 @@ export declare class OffsetRange {
|
|
|
1164
1388
|
toString(): string;
|
|
1165
1389
|
}
|
|
1166
1390
|
|
|
1167
|
-
export declare class ParagraphAstNode extends
|
|
1391
|
+
export declare class ParagraphAstNode extends BlockAstNodeBase {
|
|
1168
1392
|
readonly content: readonly (InlineAstNode | GlueAstNode)[];
|
|
1393
|
+
readonly leadingTrivia?: GlueAstNode | undefined;
|
|
1169
1394
|
readonly kind = "paragraph";
|
|
1170
|
-
constructor(content: readonly (InlineAstNode | GlueAstNode)[]);
|
|
1395
|
+
constructor(content: readonly (InlineAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
|
|
1171
1396
|
get children(): readonly AstNode[];
|
|
1172
1397
|
mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
|
|
1398
|
+
withLeadingTrivia(trivia: GlueAstNode | undefined): ParagraphAstNode;
|
|
1173
1399
|
}
|
|
1174
1400
|
|
|
1175
1401
|
declare class ParagraphViewData {
|
|
@@ -1179,6 +1405,45 @@ declare class ParagraphViewData {
|
|
|
1179
1405
|
constructor(ast: ParagraphAstNode, content: readonly AnyViewData[]);
|
|
1180
1406
|
}
|
|
1181
1407
|
|
|
1408
|
+
/**
|
|
1409
|
+
* A *transient* editing state: the empty paragraph the user conjured by
|
|
1410
|
+
* pressing Enter at the end of a paragraph. Markdown has no empty-paragraph
|
|
1411
|
+
* node, so this never lives in {@link EditorModel.sourceText} or the parsed
|
|
1412
|
+
* {@link EditorModel.document} — it is pure edit intent that the view renders
|
|
1413
|
+
* as a synthetic blank line and that the controller either *materializes* (the
|
|
1414
|
+
* user types) or *cancels* (the user navigates away / backspaces).
|
|
1415
|
+
*/
|
|
1416
|
+
declare interface PendingParagraph {
|
|
1417
|
+
/** The paragraph the blank line is rendered directly after. */
|
|
1418
|
+
readonly anchorBlock: BlockAstNode;
|
|
1419
|
+
/**
|
|
1420
|
+
* Source region rewritten when the pending paragraph is materialized — the
|
|
1421
|
+
* gap between {@link anchorBlock}'s text and whatever follows it.
|
|
1422
|
+
*/
|
|
1423
|
+
readonly replaceRange: OffsetRange;
|
|
1424
|
+
/** Whether {@link replaceRange} ends at the end of the document. */
|
|
1425
|
+
readonly atEof: boolean;
|
|
1426
|
+
/**
|
|
1427
|
+
* A throwaway AST node that exists only to give the synthetic view child a
|
|
1428
|
+
* stable identity across render frames (the view pairs nodes by `ast.id`).
|
|
1429
|
+
* It is never part of {@link document}.
|
|
1430
|
+
*/
|
|
1431
|
+
readonly syntheticAst: ParagraphAstNode;
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
/**
|
|
1435
|
+
* View-data for the transient empty paragraph (see `PendingParagraph` in the
|
|
1436
|
+
* model). It carries only the throwaway {@link ParagraphAstNode} that gives the
|
|
1437
|
+
* rendered blank line a stable identity across frames; it has no content and is
|
|
1438
|
+
* never measured or part of the selection geometry — the caret is positioned
|
|
1439
|
+
* over it via a dedicated rect, not via the visual-line map.
|
|
1440
|
+
*/
|
|
1441
|
+
declare class PendingParagraphViewData {
|
|
1442
|
+
readonly ast: ParagraphAstNode;
|
|
1443
|
+
readonly kind = "pendingParagraph";
|
|
1444
|
+
constructor(ast: ParagraphAstNode);
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1182
1447
|
/**
|
|
1183
1448
|
* Immutable point in 2D space, in CSS-pixel client coordinates.
|
|
1184
1449
|
*/
|
|
@@ -1296,6 +1561,25 @@ export declare class SelectionViewRendering {
|
|
|
1296
1561
|
|
|
1297
1562
|
export declare const selectWord: SelectionCommand;
|
|
1298
1563
|
|
|
1564
|
+
/**
|
|
1565
|
+
* The outcome of {@link insertSmartEnter}: either a concrete source edit (the
|
|
1566
|
+
* ordinary cases), or a request to arm a transient empty paragraph (Enter at
|
|
1567
|
+
* the very end of a paragraph), which the controller turns into
|
|
1568
|
+
* {@link EditorModel.armPendingParagraph} rather than a source edit. Modelling
|
|
1569
|
+
* the empty paragraph as state instead of source keeps the document valid
|
|
1570
|
+
* Markdown — which has no empty-paragraph node — until the user actually types.
|
|
1571
|
+
*/
|
|
1572
|
+
export declare type SmartEnterResult = {
|
|
1573
|
+
readonly kind: 'edit';
|
|
1574
|
+
readonly edit: StringEdit;
|
|
1575
|
+
readonly selection: Selection_2;
|
|
1576
|
+
} | {
|
|
1577
|
+
readonly kind: 'pending';
|
|
1578
|
+
readonly anchorBlock: BlockAstNode;
|
|
1579
|
+
readonly replaceRange: OffsetRange;
|
|
1580
|
+
readonly atEof: boolean;
|
|
1581
|
+
};
|
|
1582
|
+
|
|
1299
1583
|
/**
|
|
1300
1584
|
* A run of {@link Token}s together with the exact {@link OffsetRange} they
|
|
1301
1585
|
* cover.
|
|
@@ -1381,16 +1665,18 @@ declare class StrongViewData {
|
|
|
1381
1665
|
constructor(ast: StrongAstNode, content: readonly AnyViewData[]);
|
|
1382
1666
|
}
|
|
1383
1667
|
|
|
1384
|
-
export declare class TableAstNode extends
|
|
1668
|
+
export declare class TableAstNode extends BlockAstNodeBase {
|
|
1385
1669
|
readonly content: readonly (TableRowAstNode | GlueAstNode)[];
|
|
1670
|
+
readonly leadingTrivia?: GlueAstNode | undefined;
|
|
1386
1671
|
readonly kind = "table";
|
|
1387
|
-
constructor(content: readonly (TableRowAstNode | GlueAstNode)[]);
|
|
1672
|
+
constructor(content: readonly (TableRowAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
|
|
1388
1673
|
get children(): readonly AstNode[];
|
|
1389
1674
|
private get _rows();
|
|
1390
1675
|
get headerRow(): TableRowAstNode | undefined;
|
|
1391
1676
|
get delimiterRow(): TableRowAstNode | undefined;
|
|
1392
1677
|
get bodyRows(): readonly TableRowAstNode[];
|
|
1393
1678
|
mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
|
|
1679
|
+
withLeadingTrivia(trivia: GlueAstNode | undefined): TableAstNode;
|
|
1394
1680
|
}
|
|
1395
1681
|
|
|
1396
1682
|
export declare class TableCellAstNode extends AstNode {
|
|
@@ -1472,13 +1758,15 @@ declare class TextViewData {
|
|
|
1472
1758
|
constructor(ast: TextAstNode, showWhitespace: boolean, leftWordBoundary?: boolean, rightWordBoundary?: boolean);
|
|
1473
1759
|
}
|
|
1474
1760
|
|
|
1475
|
-
export declare class ThematicBreakAstNode extends
|
|
1761
|
+
export declare class ThematicBreakAstNode extends BlockAstNodeBase {
|
|
1476
1762
|
readonly content: readonly (MarkerAstNode | GlueAstNode)[];
|
|
1763
|
+
readonly leadingTrivia?: GlueAstNode | undefined;
|
|
1477
1764
|
readonly kind = "thematicBreak";
|
|
1478
|
-
constructor(content: readonly (MarkerAstNode | GlueAstNode)[]);
|
|
1765
|
+
constructor(content: readonly (MarkerAstNode | GlueAstNode)[], leadingTrivia?: GlueAstNode | undefined);
|
|
1479
1766
|
get children(): readonly AstNode[];
|
|
1480
1767
|
get marker(): MarkerAstNode | undefined;
|
|
1481
1768
|
mapChildren(m: ReadonlyMap<AstNode, AstNode>): AstNode;
|
|
1769
|
+
withLeadingTrivia(trivia: GlueAstNode | undefined): ThematicBreakAstNode;
|
|
1482
1770
|
}
|
|
1483
1771
|
|
|
1484
1772
|
declare class ThematicBreakViewData {
|