@adecore/editor 0.41.1 → 0.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import type { Keymap } from './keymap-table.ts';
2
- import type { EditorClickHandler, EditorInlayClickHandler, EditorContextMenu, EditorKeyHandler, EditorRunCommand, EditorSelectionRanges, KeyChord } from './types.ts';
2
+ import type { EditorClickHandler, EditorInlayClickHandler, EditorContextMenu, EditorCopy, EditorKeyHandler, EditorPasteOptions, EditorRunCommand, EditorSelectionRanges, KeyChord } from './types.ts';
3
3
  import type { EditorView } from './view.ts';
4
4
  export interface ControllerOptions {
5
5
  keymap?: Keymap;
@@ -7,13 +7,19 @@ export interface ControllerOptions {
7
7
  apple: boolean;
8
8
  save(): void;
9
9
  blur(): void;
10
+ zoom(step: -1 | 0 | 1): void;
11
+ wheelZooms(): boolean;
10
12
  }
13
+ export declare function rememberCopy(text: string, wholeLines: boolean): void;
11
14
  export declare class InputController {
12
15
  private readonly native;
13
16
  private readonly pointer;
14
17
  private readonly touch;
15
18
  private readonly cleanup;
16
19
  private readonly keyHandlers;
20
+ private readonly navigateListeners;
21
+ private readonly copyListeners;
22
+ private wordSources;
17
23
  private readonly gesture;
18
24
  private readonly clickHandlers;
19
25
  private readonly inlayHandlers;
@@ -25,6 +31,7 @@ export declare class InputController {
25
31
  private selectionRanges;
26
32
  private expansions;
27
33
  private lastInputAt;
34
+ private readonly wheelZoom;
28
35
  private desiredXs;
29
36
  private keepDesiredXs;
30
37
  private readonly view;
@@ -38,13 +45,17 @@ export declare class InputController {
38
45
  private applyEdits;
39
46
  private replaceSelections;
40
47
  private unfoldCarets;
41
- private paste;
48
+ pasteText(text: string, options?: EditorPasteOptions): boolean;
49
+ onCopy(listener: (copy: EditorCopy) => void): () => void;
42
50
  private commandOptions;
51
+ setWordSources(source: (() => readonly string[]) | null): void;
43
52
  private viewCommand;
53
+ private wheel;
44
54
  command(name: EditorRunCommand): boolean;
45
55
  setSelectionRanges(provider: EditorSelectionRanges | null): void;
46
56
  private expandThrough;
47
57
  private modelCommand;
58
+ onNavigate(listener: (from: number) => void): () => void;
48
59
  private typeText;
49
60
  private movePages;
50
61
  private toggleColumnMode;
@@ -6,6 +6,7 @@ import { NativeInput } from './native-input.js';
6
6
  import { columnSelections, sameCell } from './column-selection.js';
7
7
  import { PointerSelection } from './pointer.js';
8
8
  import { TouchSelection } from './touch.js';
9
+ import { WheelZoom } from './zoom.js';
9
10
  const MODIFYING = new Set([
10
11
  'deleteWordLeft',
11
12
  'deleteWordRight',
@@ -15,9 +16,12 @@ const MODIFYING = new Set([
15
16
  'deleteLine',
16
17
  'moveLineUp',
17
18
  'moveLineDown',
19
+ 'moveStatementUp',
20
+ 'moveStatementDown',
18
21
  'toggleLineComment',
19
22
  'toggleBlockComment',
20
23
  'startNewLine',
24
+ 'completeCurrentStatement',
21
25
  'startNewLineBefore',
22
26
  'splitLine',
23
27
  'joinLines',
@@ -28,8 +32,16 @@ const MODIFYING = new Set([
28
32
  'outdent',
29
33
  'insertNewline',
30
34
  'smartBackspace',
31
- 'deleteForward'
35
+ 'deleteForward',
36
+ 'sortLines',
37
+ 'reverseLines',
38
+ 'uniqueLines',
39
+ 'convertIndentsToSpaces',
40
+ 'convertIndentsToTabs',
41
+ 'hippieCompletion',
42
+ 'hippieBackwardCompletion'
32
43
  ]);
44
+ const CODE_BLOCK_COMMANDS = new Set(['codeBlockStart', 'codeBlockEnd', 'codeBlockStartWithSelection', 'codeBlockEndWithSelection']);
33
45
  const VIEW_COMMANDS = new Set([
34
46
  'collapseRegion',
35
47
  'expandRegion',
@@ -45,10 +57,26 @@ const VIEW_COMMANDS = new Set([
45
57
  'expandAllToLevel3',
46
58
  'expandAllToLevel4',
47
59
  'expandAllToLevel5',
48
- 'toggleColumnMode'
60
+ 'toggleColumnMode',
61
+ 'increaseFontSize',
62
+ 'decreaseFontSize',
63
+ 'resetFontSize',
64
+ 'methodUp',
65
+ 'methodDown',
66
+ 'nextChange',
67
+ 'previousChange',
68
+ 'pasteAsPlainText'
49
69
  ]);
70
+ const ZOOM_STEPS = { increaseFontSize: 1, decreaseFontSize: -1, resetFontSize: 0 };
50
71
  /* The clipboard text of the last copy or cut of a bare caret, which pastes back as whole lines. Shared, since it can be pasted in another editor. */
51
72
  let lineClip = null;
73
+ /*
74
+ * Makes `text` the copy that pastes back as whole lines (or not), for a paste from a history that kept what the
75
+ * copy was. The clipboard itself is the caller's.
76
+ */
77
+ export function rememberCopy(text, wholeLines) {
78
+ lineClip = wholeLines ? text : null;
79
+ }
52
80
  function selectionSignature(selections) {
53
81
  return selections.map((selection) => `${selection.anchor}:${selection.head}`).join(',');
54
82
  }
@@ -66,6 +94,9 @@ export class InputController {
66
94
  touch;
67
95
  cleanup = [];
68
96
  keyHandlers = new Set();
97
+ navigateListeners = new Set();
98
+ copyListeners = new Set();
99
+ wordSources = null;
69
100
  gesture;
70
101
  clickHandlers = new Set();
71
102
  inlayHandlers = new Set();
@@ -79,6 +110,7 @@ export class InputController {
79
110
  /* The Extend Selection presses that wait for a server's ranges, which are answered one after the other. */
80
111
  expansions = Promise.resolve();
81
112
  lastInputAt = 0;
113
+ wheelZoom = new WheelZoom();
82
114
  desiredXs = [];
83
115
  keepDesiredXs = false;
84
116
  view;
@@ -175,12 +207,12 @@ export class InputController {
175
207
  });
176
208
  this.listen(input, 'paste', (event) => {
177
209
  event.preventDefault();
178
- this.paste(event.clipboardData?.getData('text/plain') ?? '');
210
+ this.pasteText(event.clipboardData?.getData('text/plain') ?? '');
179
211
  });
180
212
  this.listen(input, 'copy', (event) => this.copy(event, false));
181
213
  this.listen(input, 'cut', (event) => this.copy(event, true));
182
214
  this.listen(viewport, 'scroll', () => this.view.scrolled());
183
- this.listen(viewport, 'wheel', () => this.view.cancelScroll());
215
+ this.listen(viewport, 'wheel', (event) => this.wheel(event));
184
216
  this.listen(viewport, 'pointermove', (event) => this.view.hoverMoved(event));
185
217
  this.listen(viewport, 'pointerleave', () => {
186
218
  this.view.setHover(null);
@@ -234,6 +266,8 @@ export class InputController {
234
266
  }
235
267
  this.cleanup.length = 0;
236
268
  this.keyHandlers.clear();
269
+ this.navigateListeners.clear();
270
+ this.copyListeners.clear();
237
271
  }
238
272
  blockedByReadOnly() {
239
273
  return this.view.blockedByReadOnly();
@@ -267,15 +301,25 @@ export class InputController {
267
301
  this.view.ensureVisible(selection.head);
268
302
  }
269
303
  }
270
- paste(text) {
304
+ /* Pastes as a paste from the clipboard does; false when a read-only editor refused. */
305
+ pasteText(text, options = {}) {
271
306
  if (this.blockedByReadOnly()) {
272
- return;
307
+ return false;
273
308
  }
274
309
  this.unfoldCarets();
275
310
  this.historyGroup++;
276
- this.view.model.paste(this.native.normalizeNewlines(text), { ...this.commandOptions(), wholeLines: text !== '' && text === lineClip });
311
+ const pasted = this.view.model.paste(this.native.normalizeNewlines(text), {
312
+ ...this.commandOptions(),
313
+ ...(options.reindent === false ? { indentOnPaste: false } : {}),
314
+ wholeLines: options.wholeLines ?? (text !== '' && text === lineClip)
315
+ });
277
316
  this.historyGroup++;
278
317
  this.view.revealCaret();
318
+ return pasted;
319
+ }
320
+ /* Told what a copy or cut put on the clipboard. */
321
+ onCopy(listener) {
322
+ return subscribe(this.copyListeners, listener);
279
323
  }
280
324
  commandOptions() {
281
325
  const { settings } = this.view;
@@ -289,17 +333,47 @@ export class InputController {
289
333
  tabOutOfClosers: keys.tabOutOfClosers,
290
334
  smartEnter: keys.smartIndentOnEnter,
291
335
  indentOnPaste: keys.indentOnPaste,
336
+ indentGuides: settings.guides,
292
337
  smartSemicolon: keys.smartSemicolon,
293
338
  smartArrow: keys.smartArrow,
294
339
  language: settings.language ?? 'plaintext',
295
340
  camelCase: keys.camelHumps,
296
341
  visualLine: (offset) => this.view.rowOf(offset),
297
- lineSpan: (line) => this.view.lineSpan(line)
342
+ lineSpan: (line) => this.view.lineSpan(line),
343
+ structure: () => this.view.structureRanges(),
344
+ ...(this.wordSources === null ? {} : { wordSources: this.wordSources })
298
345
  };
299
346
  }
347
+ /* The texts Hippie completion takes words from after those of this document; null takes them away. */
348
+ setWordSources(source) {
349
+ this.wordSources = source;
350
+ }
300
351
  /* Folding is the view's, since it knows where the ranges are. */
301
352
  viewCommand(name) {
302
353
  const { view } = this;
354
+ if (name in ZOOM_STEPS) {
355
+ this.options.zoom(ZOOM_STEPS[name]);
356
+ return true;
357
+ }
358
+ if (name === 'methodUp' || name === 'methodDown') {
359
+ const from = view.model.getPrimary().head;
360
+ const moved = view.goToMethod(name === 'methodUp' ? -1 : 1);
361
+ if (moved) {
362
+ emit(this.navigateListeners, from);
363
+ }
364
+ return moved;
365
+ }
366
+ if (name === 'pasteAsPlainText') {
367
+ // The clipboard is read once a person asks, and an editor with no way to read it does nothing.
368
+ if (this.blockedByReadOnly() || globalThis.navigator?.clipboard?.readText === undefined) {
369
+ return false;
370
+ }
371
+ void navigator.clipboard.readText().then((text) => this.pasteText(text, { reindent: false }), () => undefined);
372
+ return true;
373
+ }
374
+ if (name === 'nextChange' || name === 'previousChange') {
375
+ return view.goToChange(name === 'nextChange' ? 1 : -1);
376
+ }
303
377
  if (view.settings.folding === false && name !== 'toggleColumnMode') {
304
378
  return false;
305
379
  }
@@ -323,6 +397,18 @@ export class InputController {
323
397
  run[name]();
324
398
  return true;
325
399
  }
400
+ /* A pinch comes as the wheel with Ctrl, on every platform. */
401
+ wheel(event) {
402
+ this.view.cancelScroll();
403
+ if (!(event.ctrlKey || (this.options.apple && event.metaKey)) || !this.options.wheelZooms()) {
404
+ return;
405
+ }
406
+ event.preventDefault();
407
+ const step = this.wheelZoom.step(event);
408
+ if (step !== 0) {
409
+ this.options.zoom(step);
410
+ }
411
+ }
326
412
  /* Runs a model command on every caret, with the folds that would hide its result opened first. */
327
413
  command(name) {
328
414
  if (VIEW_COMMANDS.has(name)) {
@@ -386,7 +472,10 @@ export class InputController {
386
472
  }
387
473
  }
388
474
  }
389
- const folded = name === 'moveLineUp' || name === 'moveLineDown' ? this.view.getFolds().collapsed : [];
475
+ const before = model.getPrimary().head;
476
+ const folded = name === 'moveLineUp' || name === 'moveLineDown' || name === 'moveStatementUp' || name === 'moveStatementDown'
477
+ ? this.view.getFolds().collapsed
478
+ : [];
390
479
  const result = model.execute(name, {
391
480
  ...this.commandOptions(),
392
481
  onLinesMoved: (moves) => this.view.refoldMoved(folded, moves)
@@ -397,9 +486,19 @@ export class InputController {
397
486
  if (name === 'smartEnd' || name === 'selectSmartEnd') {
398
487
  this.view.markRowEnd(model.getPrimary().head);
399
488
  }
489
+ if (name === 'hippieCompletion' || name === 'hippieBackwardCompletion') {
490
+ this.view.setHippieSource(model.hippieSource);
491
+ }
400
492
  this.view.revealCaret();
493
+ if (CODE_BLOCK_COMMANDS.has(name) && model.getPrimary().head !== before) {
494
+ emit(this.navigateListeners, before);
495
+ }
401
496
  return result;
402
497
  }
498
+ /* Told the offset the primary caret left when a command that navigates moved it. */
499
+ onNavigate(listener) {
500
+ return subscribe(this.navigateListeners, listener);
501
+ }
403
502
  typeText(text) {
404
503
  if (this.blockedByReadOnly()) {
405
504
  return;
@@ -624,6 +723,7 @@ export class InputController {
624
723
  if (event.isComposing || this.native.composing) {
625
724
  return;
626
725
  }
726
+ this.view.setHippieSource(null);
627
727
  const added = this.gesture.keydown(event);
628
728
  if (added !== null) {
629
729
  event.preventDefault();
@@ -699,6 +799,7 @@ export class InputController {
699
799
  : selections.map((selection) => model.slice(Math.min(selection.anchor, selection.head), Math.max(selection.anchor, selection.head))).join('\n');
700
800
  event.clipboardData?.setData('text/plain', text);
701
801
  lineClip = empty ? text : null;
802
+ emit(this.copyListeners, { text, wholeLines: empty, cut });
702
803
  if (!cut || this.blockedByReadOnly()) {
703
804
  return;
704
805
  }
package/dist/editor.css CHANGED
@@ -17,6 +17,7 @@
17
17
  --editor-added: var(--status-idle);
18
18
  --editor-modified: var(--accent);
19
19
  --editor-deleted: var(--status-error);
20
+ --editor-todo: var(--status-running);
20
21
  --editor-mark-number-mix: 72%;
21
22
  --editor-mark-bar-width: 3px;
22
23
  --editor-mark-gap: 4px;
@@ -38,6 +39,7 @@
38
39
  --editor-margin: color-mix(in srgb, var(--text) 16%, transparent);
39
40
  --editor-whitespace: color-mix(in srgb, var(--text) 32%, transparent);
40
41
  --editor-hatch: color-mix(in srgb, var(--text) 10%, transparent);
42
+ --editor-todo: var(--status-idle);
41
43
  --editor-mark-number-mix: 82%;
42
44
  --editor-sticky-shadow: color-mix(in srgb, black 60%, transparent);
43
45
  }
@@ -478,11 +480,15 @@
478
480
  left: 6px;
479
481
  background: var(--editor-occurrence);
480
482
  }
483
+ .se-tick-todo,
481
484
  .se-tick-error,
482
485
  .se-tick-warning,
483
486
  .se-tick-info {
484
487
  left: 10px;
485
488
  }
489
+ .se-tick-todo {
490
+ background: var(--editor-todo);
491
+ }
486
492
  /* The only part of the track that takes the pointer, with a wider reach than the 4px it draws. */
487
493
  .se-tick[data-offset] {
488
494
  pointer-events: auto;
@@ -646,11 +652,16 @@
646
652
  .se-find-match,
647
653
  .se-find-current,
648
654
  .se-occurrence,
655
+ .se-hippie-source,
649
656
  .se-bracket-match,
650
657
  .se-bracket-unmatched {
651
658
  position: absolute;
652
659
  border-radius: var(--radius-xs);
653
660
  }
661
+ .se-hippie-source {
662
+ background: color-mix(in srgb, var(--accent) 22%, transparent);
663
+ border-radius: var(--radius-sm);
664
+ }
654
665
  .se-find-match {
655
666
  background: var(--find-match);
656
667
  }
@@ -741,6 +752,14 @@
741
752
  white-space: pre;
742
753
  cursor: default;
743
754
  }
755
+ .se-swatch {
756
+ height: 12px;
757
+ margin-top: calc((var(--code-line-height, 20px) - 12px) / 2);
758
+ padding: 0;
759
+ border-radius: var(--radius-sm);
760
+ box-shadow: inset 0 0 0 1px var(--border);
761
+ cursor: pointer;
762
+ }
744
763
  .se-inlay-link {
745
764
  text-decoration: underline;
746
765
  text-underline-offset: 2px;
package/dist/engine.js CHANGED
@@ -6,6 +6,7 @@ import { resolveSmartKeys } from './smart-keys.js';
6
6
  import { emit, subscribe } from './listeners.js';
7
7
  import { fillLens, lensSignature } from './lens.js';
8
8
  import { EditorView } from './view.js';
9
+ import { clampFontSize, fontSizeRange } from './zoom.js';
9
10
  const DEFAULT_TAB_SIZE = 4;
10
11
  const DEFAULT_LABEL = 'Code editor';
11
12
  const DEFAULT_WIDGET_OWNER = 'default';
@@ -23,6 +24,9 @@ class SmartEditor {
23
24
  caretOffset = 0;
24
25
  saves = new Set();
25
26
  blurs = new Set();
27
+ fontSizes = new Set();
28
+ fontSizeRange;
29
+ fontSize = null;
26
30
  subscription;
27
31
  language;
28
32
  theme;
@@ -31,10 +35,13 @@ class SmartEditor {
31
35
  lensRevisions = new Map();
32
36
  tokenizerRequest = 0;
33
37
  settingText = false;
38
+ /* The hints of each owner, in the order the owners first set theirs. */
39
+ inlayOwners = new Map();
34
40
  disposed = false;
35
41
  engine;
36
42
  constructor(engine, element, options) {
37
43
  this.engine = engine;
44
+ this.fontSizeRange = fontSizeRange(options.zoom);
38
45
  this.model = new DocumentModel(options.text);
39
46
  this.language = options.language;
40
47
  this.theme = options.theme;
@@ -54,7 +61,8 @@ class SmartEditor {
54
61
  whitespace: options.whitespace === true,
55
62
  rightMargin: options.rightMargin ?? null,
56
63
  foldOutline: options.foldOutline ?? 'hover',
57
- folding: options.folding !== false
64
+ folding: options.folding !== false,
65
+ todoWords: options.todoWords
58
66
  };
59
67
  this.view = new EditorView(element, this.model, this.settings);
60
68
  this.grammarPreparation = new GrammarPreparation(this.model, () => this.view.grammarChanged());
@@ -63,8 +71,13 @@ class SmartEditor {
63
71
  keymap: engine.keymap,
64
72
  apple: engine.apple ?? false,
65
73
  save: () => emit(this.saves),
66
- blur: () => emit(this.blurs)
74
+ blur: () => emit(this.blurs),
75
+ zoom: (step) => this.zoom(step),
76
+ wheelZooms: () => options.zoom?.wheel !== false
67
77
  });
78
+ if (options.fontSize !== undefined) {
79
+ this.setFontSize(options.fontSize);
80
+ }
68
81
  this.revision = this.model.getRevision();
69
82
  this.caretOffset = this.model.getPrimary().head;
70
83
  this.subscription = this.model.subscribe((snapshot) => {
@@ -273,6 +286,14 @@ class SmartEditor {
273
286
  return false;
274
287
  }
275
288
  }
289
+ cleanUpWhitespace(options) {
290
+ const changed = !this.settings.readOnly && this.model.cleanUpWhitespace({ ...options, language: this.settings.language });
291
+ this.model.markSaved();
292
+ return changed;
293
+ }
294
+ markSaved() {
295
+ this.model.markSaved();
296
+ }
276
297
  setMarkers(markers) {
277
298
  this.view.setMarkers(markers.map((marker) => ({
278
299
  severity: marker.severity,
@@ -283,14 +304,21 @@ class SmartEditor {
283
304
  ...(marker.message === undefined ? {} : { message: marker.message })
284
305
  })));
285
306
  }
286
- setInlayHints(hints) {
287
- this.view.setInlays(hints.map((hint, index) => ({
307
+ setInlayHints(hints, owner = DEFAULT_WIDGET_OWNER) {
308
+ if (hints.length === 0) {
309
+ this.inlayOwners.delete(owner);
310
+ }
311
+ else {
312
+ this.inlayOwners.set(owner, hints);
313
+ }
314
+ this.view.setInlays([...this.inlayOwners.values()].flat().map((hint, index) => ({
288
315
  id: hint.id ?? `hint-${index}`,
289
316
  at: this.offsetAt(hint.position),
290
317
  text: hint.label,
291
318
  ...(hint.parts === undefined ? {} : { parts: hint.parts }),
292
319
  ...(hint.paddingLeft ? { gapLeft: INLAY_GAP } : {}),
293
- ...(hint.paddingRight ? { gapRight: INLAY_GAP } : {})
320
+ ...(hint.paddingRight ? { gapRight: INLAY_GAP } : {}),
321
+ ...(hint.swatch === undefined ? {} : { swatch: hint.swatch })
294
322
  })));
295
323
  }
296
324
  onInlayHover(listener) {
@@ -655,9 +683,31 @@ class SmartEditor {
655
683
  this.settings.label = label;
656
684
  this.view.applySettings();
657
685
  }
686
+ setTodoWords(words) {
687
+ this.settings.todoWords = [...words];
688
+ this.view.applySettings();
689
+ }
658
690
  setFoldHints(hints) {
659
691
  this.view.setFoldHints(hints === null ? null : this.foldHintsByOffset(hints));
660
692
  }
693
+ setDeclarations(positions) {
694
+ this.view.setDeclarations(positions === null ? null : positions.map((position) => this.offsetAt(position)));
695
+ }
696
+ onNavigate(listener) {
697
+ return this.controller.onNavigate((from) => listener(this.positionAt(from)));
698
+ }
699
+ hasFocus() {
700
+ return this.view.focused;
701
+ }
702
+ setWordSources(source) {
703
+ this.controller.setWordSources(source);
704
+ }
705
+ onCopy(listener) {
706
+ return this.controller.onCopy(listener);
707
+ }
708
+ paste(text, options) {
709
+ return this.controller.pasteText(text, options);
710
+ }
661
711
  foldHintsByOffset(hints) {
662
712
  const lineOf = (line) => this.model.getLine(Math.min(line, this.model.getLineCount() - 1));
663
713
  const within = (line, character) => Math.min(line.end, line.start + Math.max(0, character));
@@ -700,6 +750,32 @@ class SmartEditor {
700
750
  refreshFont() {
701
751
  this.view.refreshFont();
702
752
  }
753
+ setFontSize(size) {
754
+ const next = size === null || !Number.isFinite(size) ? null : clampFontSize(size, this.fontSizeRange);
755
+ if (next !== this.fontSize) {
756
+ this.fontSize = next;
757
+ this.view.setFontSize(next);
758
+ }
759
+ }
760
+ getFontSize() {
761
+ return this.view.getFontSize();
762
+ }
763
+ onFontSizeChange(listener) {
764
+ return subscribe(this.fontSizes, listener);
765
+ }
766
+ /* Steps from the size on screen, so the first step from the page's size is one pixel away from it. */
767
+ zoom(step) {
768
+ const before = this.fontSize;
769
+ const current = this.view.getFontSize();
770
+ // A page size outside the range must not make a step the other way.
771
+ if (step !== 0 && Math.sign(clampFontSize(current + step, this.fontSizeRange) - current) !== step) {
772
+ return;
773
+ }
774
+ this.setFontSize(step === 0 ? null : current + step);
775
+ if (this.fontSize !== before) {
776
+ emit(this.fontSizes, this.fontSize);
777
+ }
778
+ }
703
779
  setReadOnly(readOnly, reason) {
704
780
  this.settings.readOnly = readOnly;
705
781
  this.settings.readOnlyReason = reason;
@@ -728,6 +804,7 @@ class SmartEditor {
728
804
  this.carets.clear();
729
805
  this.saves.clear();
730
806
  this.blurs.clear();
807
+ this.fontSizes.clear();
731
808
  this.subscription.dispose();
732
809
  this.controller.dispose();
733
810
  this.view.dispose();
package/dist/fake.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Editor, EditorAttributionHover, EditorAttributionMark, EditorBlock, EditorCodeBlockOptions, EditorLineAction, EditorReplacement, EditorLineHighlight, LineToken, EditorChangeMark, EditorCodeVision, EditorClick, EditorClickHandler, EditorContextMenu, EditorContentChange, EditorEngine, EditorFindQuery, EditorFindState, EditorReplaceOptions, EditorGutterAction, EditorGutterMarker, EditorHighlight, EditorHover, EditorIndentation, EditorGhostText, EditorInlayClick, EditorInlayClickHandler, EditorInlayHint, EditorInlayTarget, EditorKeyHandler, EditorInputPopup, EditorMarker, EditorMessages, EditorOptions, EditorPosition, EditorRemoteCursor, EditorRange, EditorReveal, EditorRect, EditorRunCommand, EditorSelectionRanges, EditorFoldHints, EditorFoldOutline, EditorFolds, EditorSemanticToken, EditorSmartKeys, EditorApplyEditsOptions, EditorTextChange, EditorTrackedRange, EditorTheme, EditorWidget } from './types.ts';
1
+ import type { Editor, EditorAttributionHover, EditorAttributionMark, EditorBlock, EditorCodeBlockOptions, EditorLineAction, EditorReplacement, EditorLineHighlight, LineToken, EditorChangeMark, EditorCodeVision, EditorClick, EditorClickHandler, EditorContextMenu, EditorContentChange, EditorEngine, EditorFindQuery, EditorFindState, EditorReplaceOptions, EditorGutterAction, EditorGutterMarker, EditorHighlight, EditorHover, EditorIndentation, EditorGhostText, EditorInlayClick, EditorInlayClickHandler, EditorInlayHint, EditorInlayTarget, EditorKeyHandler, EditorInputPopup, EditorMarker, EditorMessages, EditorOptions, EditorPosition, EditorRemoteCursor, EditorRange, EditorReveal, EditorRect, EditorRunCommand, EditorSelectionRanges, EditorFoldHints, EditorFoldOutline, EditorFolds, EditorSemanticToken, EditorSmartKeys, EditorApplyEditsOptions, EditorCopy, EditorPasteOptions, EditorTextChange, EditorTrackedRange, EditorTheme, EditorWhitespaceCleanup, EditorWidget } from './types.ts';
2
2
  import { type Listener } from './listeners.ts';
3
3
  export declare class FakeEditor implements Editor {
4
4
  readonly element: HTMLElement;
@@ -139,7 +139,25 @@ export declare class FakeEditor implements Editor {
139
139
  setFoldOutline(outline: EditorFoldOutline): void;
140
140
  label: string;
141
141
  setLabel(label: string): void;
142
+ todoWords: readonly string[] | undefined;
143
+ setTodoWords(words: readonly string[]): void;
142
144
  setFoldHints(hints: EditorFoldHints | null): void;
145
+ declarations: readonly EditorPosition[] | null;
146
+ setDeclarations(positions: readonly EditorPosition[] | null): void;
147
+ private readonly navigations;
148
+ onNavigate(listener: (from: EditorPosition) => void): () => void;
149
+ navigate(from: EditorPosition): void;
150
+ hasFocus(): boolean;
151
+ private readonly copies;
152
+ onCopy(listener: (copy: EditorCopy) => void): () => void;
153
+ copy(text: string, wholeLines?: boolean, cut?: boolean): void;
154
+ readonly pastes: Array<{
155
+ text: string;
156
+ options: EditorPasteOptions | undefined;
157
+ }>;
158
+ paste(text: string, options?: EditorPasteOptions): boolean;
159
+ wordSources: (() => readonly string[]) | null;
160
+ setWordSources(source: (() => readonly string[]) | null): void;
143
161
  setSmartKeys(keys: Partial<EditorSmartKeys>): void;
144
162
  setIndentation(indentation: EditorIndentation): void;
145
163
  markers: readonly EditorMarker[];
@@ -159,7 +177,8 @@ export declare class FakeEditor implements Editor {
159
177
  private readonly keys;
160
178
  setMarkers(markers: readonly EditorMarker[]): void;
161
179
  inlayHints: readonly EditorInlayHint[];
162
- setInlayHints(hints: readonly EditorInlayHint[]): void;
180
+ private readonly inlayOwners;
181
+ setInlayHints(hints: readonly EditorInlayHint[], owner?: string): void;
163
182
  private readonly inlayHovers;
164
183
  private readonly inlayHandlers;
165
184
  inlayLink: {
@@ -224,8 +243,18 @@ export declare class FakeEditor implements Editor {
224
243
  openContextMenu(menu: EditorContextMenu): void;
225
244
  press(event: Pick<KeyboardEvent, 'key'> & Partial<KeyboardEvent>): boolean;
226
245
  applyEdits(edits: readonly EditorContentChange[], options?: EditorApplyEditsOptions): boolean;
246
+ readonly cleanups: EditorWhitespaceCleanup[];
247
+ savedMarks: number;
248
+ cleanUpWhitespace(options: EditorWhitespaceCleanup): boolean;
249
+ markSaved(): void;
227
250
  setTheme(theme: EditorTheme): void;
228
251
  refreshFont(): void;
252
+ fontSize: number | null;
253
+ private readonly fontSizeListeners;
254
+ setFontSize(size: number | null): void;
255
+ getFontSize(): number;
256
+ onFontSizeChange(listener: (size: number | null) => void): () => void;
257
+ zoomTo(size: number | null): void;
229
258
  setReadOnly(readOnly: boolean, reason?: string): void;
230
259
  isReadOnly(): boolean;
231
260
  readonly commands: EditorRunCommand[];