@adecore/editor 0.22.1 → 0.23.1

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 (94) hide show
  1. package/dist/attribution.d.ts +9 -8
  2. package/dist/attribution.js +44 -9
  3. package/dist/bidi.d.ts +44 -0
  4. package/dist/bidi.js +26 -0
  5. package/dist/column-selection.js +2 -1
  6. package/dist/controller.d.ts +6 -1
  7. package/dist/controller.js +93 -3
  8. package/dist/editor.css +81 -1
  9. package/dist/engine.js +189 -41
  10. package/dist/fake.d.ts +45 -5
  11. package/dist/fake.js +121 -13
  12. package/dist/find-search.d.ts +26 -0
  13. package/dist/find-search.js +130 -0
  14. package/dist/find.d.ts +50 -2
  15. package/dist/find.js +575 -25
  16. package/dist/geometry-stops.d.ts +6 -0
  17. package/dist/geometry-stops.js +47 -0
  18. package/dist/grammar-preparation.d.ts +29 -0
  19. package/dist/grammar-preparation.js +147 -0
  20. package/dist/index.d.ts +3 -1
  21. package/dist/index.js +2 -0
  22. package/dist/keymap-table.d.ts +10 -1
  23. package/dist/keymap-table.js +37 -1
  24. package/dist/keymap.d.ts +1 -0
  25. package/dist/keymap.js +4 -1
  26. package/dist/layout-changes.d.ts +6 -0
  27. package/dist/layout-changes.js +27 -0
  28. package/dist/layout.d.ts +45 -2
  29. package/dist/layout.js +202 -58
  30. package/dist/offsets.d.ts +1 -0
  31. package/dist/offsets.js +23 -0
  32. package/dist/outline.js +5 -4
  33. package/dist/paint.d.ts +11 -3
  34. package/dist/paint.js +180 -34
  35. package/dist/search-client.d.ts +27 -0
  36. package/dist/search-client.js +210 -0
  37. package/dist/search-protocol.d.ts +103 -0
  38. package/dist/search-protocol.js +3 -0
  39. package/dist/search-worker.d.ts +11 -0
  40. package/dist/search-worker.js +137 -0
  41. package/dist/semantic.d.ts +2 -1
  42. package/dist/semantic.js +6 -1
  43. package/dist/shiki-document.d.ts +8 -0
  44. package/dist/shiki-document.js +93 -0
  45. package/dist/shiki-worker.d.ts +65 -0
  46. package/dist/shiki-worker.js +265 -0
  47. package/dist/shiki.d.ts +1 -0
  48. package/dist/shiki.js +96 -33
  49. package/dist/testing.d.ts +1 -0
  50. package/dist/tokens.d.ts +2 -0
  51. package/dist/tokens.js +37 -7
  52. package/dist/touch.d.ts +27 -0
  53. package/dist/touch.js +100 -0
  54. package/dist/types.d.ts +86 -2
  55. package/dist/uniform-geometry.d.ts +7 -0
  56. package/dist/uniform-geometry.js +49 -0
  57. package/dist/view.d.ts +69 -17
  58. package/dist/view.js +427 -97
  59. package/dist/worker-client.d.ts +37 -0
  60. package/dist/worker-client.js +195 -0
  61. package/package.json +17 -2
  62. package/src/attribution.ts +50 -14
  63. package/src/bidi.ts +32 -0
  64. package/src/column-selection.ts +2 -1
  65. package/src/controller.ts +97 -3
  66. package/src/editor.css +81 -1
  67. package/src/engine.ts +222 -42
  68. package/src/fake.ts +157 -14
  69. package/src/find-search.ts +165 -0
  70. package/src/find.ts +622 -21
  71. package/src/geometry-stops.ts +51 -0
  72. package/src/grammar-preparation.ts +158 -0
  73. package/src/index.ts +10 -0
  74. package/src/keymap-table.ts +44 -2
  75. package/src/keymap.ts +5 -1
  76. package/src/layout-changes.ts +33 -0
  77. package/src/layout.ts +262 -63
  78. package/src/offsets.ts +24 -0
  79. package/src/outline.ts +5 -4
  80. package/src/paint.ts +202 -36
  81. package/src/search-client.ts +306 -0
  82. package/src/search-protocol.ts +100 -0
  83. package/src/search-worker.ts +171 -0
  84. package/src/semantic.ts +8 -2
  85. package/src/shiki-document.ts +143 -0
  86. package/src/shiki-worker.ts +344 -0
  87. package/src/shiki.ts +103 -33
  88. package/src/testing.ts +2 -0
  89. package/src/tokens.ts +36 -7
  90. package/src/touch.ts +134 -0
  91. package/src/types.ts +178 -8
  92. package/src/uniform-geometry.ts +57 -0
  93. package/src/view.ts +505 -102
  94. package/src/worker-client.ts +212 -0
package/dist/engine.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import { changedSpans, DocumentModel, replacementText } from '@adecore/editor-core';
2
+ import { MAX_REPLACEMENT_CHARACTERS } from './search-protocol.js';
3
+ import { GrammarPreparation } from './grammar-preparation.js';
2
4
  import { InputController } from './controller.js';
3
5
  import { resolveSmartKeys } from './smart-keys.js';
4
6
  import { emit, subscribe } from './listeners.js';
@@ -7,11 +9,14 @@ import { EditorView } from './view.js';
7
9
  const DEFAULT_TAB_SIZE = 4;
8
10
  const DEFAULT_LABEL = 'Code editor';
9
11
  const DEFAULT_WIDGET_OWNER = 'default';
12
+ /* The space a hint's padding keeps clear; a whole pixel count so the pill stays on the pixel grid. */
13
+ const INLAY_GAP = 4;
10
14
  class SmartEditor {
11
15
  model;
12
16
  settings;
13
17
  view;
14
18
  controller;
19
+ grammarPreparation;
15
20
  changes = new Set();
16
21
  textChanges = new Set();
17
22
  carets = new Set();
@@ -34,6 +39,7 @@ class SmartEditor {
34
39
  this.language = options.language;
35
40
  this.theme = options.theme;
36
41
  this.settings = {
42
+ searchWorker: engine.searchWorker,
37
43
  language: options.language,
38
44
  tabSize: options.indentation?.tabSize ?? DEFAULT_TAB_SIZE,
39
45
  insertSpaces: options.indentation?.insertSpaces ?? true,
@@ -44,13 +50,16 @@ class SmartEditor {
44
50
  messages: options.messages ?? {},
45
51
  label: options.label ?? DEFAULT_LABEL,
46
52
  guides: options.guides !== false,
53
+ stickyScroll: options.stickyScroll !== false,
47
54
  whitespace: options.whitespace === true,
48
55
  rightMargin: options.rightMargin ?? null,
49
- foldOutline: options.foldOutline ?? 'hover'
56
+ foldOutline: options.foldOutline ?? 'hover',
57
+ folding: options.folding !== false
50
58
  };
51
59
  this.view = new EditorView(element, this.model, this.settings);
60
+ this.grammarPreparation = new GrammarPreparation(this.model, () => this.view.grammarChanged());
52
61
  this.controller = new InputController(this.view, {
53
- handBack: engine.handBack ?? [],
62
+ handBack: [...(engine.handBack ?? []), ...(options.handBack ?? [])],
54
63
  keymap: engine.keymap,
55
64
  apple: engine.apple ?? false,
56
65
  save: () => emit(this.saves),
@@ -62,8 +71,9 @@ class SmartEditor {
62
71
  this.caretMoved(snapshot.selections.at(-1).head);
63
72
  if (snapshot.revision !== this.revision) {
64
73
  this.revision = snapshot.revision;
74
+ this.grammarPreparation.edited(snapshot.changes ?? []);
65
75
  if (snapshot.contentEdits !== undefined && snapshot.contentEdits.length > 0) {
66
- this.announceTextChange(snapshot.contentEdits, snapshot.source ?? 'external');
76
+ this.announceTextChange(snapshot.contentEdits, snapshot.source ?? 'external', snapshot.typed === true);
67
77
  }
68
78
  if (!this.settingText) {
69
79
  emit(this.changes);
@@ -96,6 +106,7 @@ class SmartEditor {
96
106
  }
97
107
  loadTokenizer() {
98
108
  const request = ++this.tokenizerRequest;
109
+ this.grammarPreparation.begin();
99
110
  void this.engine
100
111
  .scopeColors?.(this.theme)
101
112
  .catch(() => null)
@@ -110,6 +121,7 @@ class SmartEditor {
110
121
  .then((tokenizer) => {
111
122
  if (!this.disposed && request === this.tokenizerRequest) {
112
123
  this.view.setTokenizer(tokenizer);
124
+ this.grammarPreparation.ready(tokenizer);
113
125
  }
114
126
  });
115
127
  }
@@ -136,9 +148,10 @@ class SmartEditor {
136
148
  onTextChange(listener) {
137
149
  return subscribe(this.textChanges, listener);
138
150
  }
139
- announceTextChange(edits, source) {
151
+ announceTextChange(edits, source, typed) {
140
152
  const change = {
141
153
  source,
154
+ ...(typed ? { typed } : {}),
142
155
  changes: edits.map((edit) => ({
143
156
  range: { start: { line: edit.start.line, character: edit.start.column }, end: { line: edit.end.line, character: edit.end.column } },
144
157
  text: edit.text
@@ -160,6 +173,21 @@ class SmartEditor {
160
173
  getScrollTop() {
161
174
  return this.view.scrollPlace.y;
162
175
  }
176
+ setScrollTop(top) {
177
+ this.view.setScrollTop(top);
178
+ }
179
+ getLineHeight(line) {
180
+ return this.view.getLineHeight(line);
181
+ }
182
+ getBaseLineHeight() {
183
+ return this.view.layout.metrics.lineHeight;
184
+ }
185
+ onLineHeights(listener) {
186
+ return this.view.onLineHeights(listener);
187
+ }
188
+ getContentHeight() {
189
+ return this.view.contentHeight;
190
+ }
163
191
  getSelection() {
164
192
  return this.rangeOf(this.model.getPrimary());
165
193
  }
@@ -218,12 +246,29 @@ class SmartEditor {
218
246
  setSelectionRanges(provider) {
219
247
  this.controller.setSelectionRanges(provider);
220
248
  }
221
- applyEdits(edits) {
249
+ applyEdits(edits, options = {}) {
222
250
  if (this.settings.readOnly || edits.length === 0) {
223
251
  return false;
224
252
  }
225
253
  try {
226
- return this.model.applyEdits(edits.map((edit) => ({ from: this.offsetAt(edit.range.start), to: this.offsetAt(edit.range.end), text: edit.text })), { source: 'command' });
254
+ const { mapSelections } = options;
255
+ return this.model.applyEdits(edits.map((edit) => ({ from: this.offsetAt(edit.range.start), to: this.offsetAt(edit.range.end), text: edit.text })), {
256
+ source: 'command',
257
+ joinPrevious: options.mergeUndo === true,
258
+ selectionPositions: mapSelections &&
259
+ this.model.getSelections().map((selection) => {
260
+ const { start, end } = mapSelections(this.rangeOf(selection));
261
+ const from = { line: start.line, column: start.character };
262
+ const to = { line: end.line, column: end.character };
263
+ if (selection.head < selection.anchor) {
264
+ return { anchor: to, head: from };
265
+ }
266
+ return {
267
+ anchor: from,
268
+ head: selection.head === selection.anchor && start.line === end.line && start.character === end.character ? from : to
269
+ };
270
+ })
271
+ });
227
272
  }
228
273
  catch {
229
274
  return false;
@@ -240,7 +285,23 @@ class SmartEditor {
240
285
  })));
241
286
  }
242
287
  setInlayHints(hints) {
243
- this.view.setInlays(hints.map((hint, index) => ({ id: `hint-${index}`, at: this.offsetAt(hint.position), text: hint.label })));
288
+ this.view.setInlays(hints.map((hint, index) => ({
289
+ id: hint.id ?? `hint-${index}`,
290
+ at: this.offsetAt(hint.position),
291
+ text: hint.label,
292
+ ...(hint.parts === undefined ? {} : { parts: hint.parts }),
293
+ ...(hint.paddingLeft ? { gapLeft: INLAY_GAP } : {}),
294
+ ...(hint.paddingRight ? { gapRight: INLAY_GAP } : {})
295
+ })));
296
+ }
297
+ onInlayHover(listener) {
298
+ return this.view.onInlayHover(listener);
299
+ }
300
+ onInlayClick(handler) {
301
+ return this.controller.onInlayClick(handler);
302
+ }
303
+ setInlayLink(target) {
304
+ this.view.setInlayLink(target);
244
305
  }
245
306
  setGhostText(ghost) {
246
307
  this.view.setGhost(ghost === null ? null : { at: this.offsetAt(ghost.position), text: ghost.text, accessory: ghost.accessory });
@@ -250,7 +311,7 @@ class SmartEditor {
250
311
  ? null
251
312
  : tokens.map((token) => {
252
313
  const from = this.offsetAt({ line: token.line, character: token.character });
253
- return { from, to: from + token.length, scopes: token.scopes };
314
+ return { from, to: from + token.length, scopes: token.scopes, within: token.within };
254
315
  }));
255
316
  }
256
317
  setHighlights(highlights) {
@@ -292,19 +353,23 @@ class SmartEditor {
292
353
  }
293
354
  replace(replacement, replaceOptions = {}) {
294
355
  const { find } = this.view;
295
- const mark = find.currentMark;
296
- const query = find.activeQuery;
297
- if (mark === null || query === null || this.blockedByReadOnly()) {
356
+ const match = find.currentMatch;
357
+ if (this.blockedByReadOnly()) {
298
358
  return false;
299
359
  }
300
- try {
301
- const options = { caseSensitive: query.caseSensitive, wholeWord: query.wholeWord, regex: query.regex, from: mark.from, to: mark.to, maxResults: 1 };
302
- const match = this.model.find(query.text, options)[0];
303
- if (match === undefined) {
360
+ if (find.activeQuery?.regex === true) {
361
+ if (find.currentMark === null) {
304
362
  return false;
305
363
  }
364
+ void find.replaceOne(replacement, replaceOptions.preserveCase === true, () => !this.disposed && !this.settings.readOnly);
365
+ return true;
366
+ }
367
+ if (match === null) {
368
+ return false;
369
+ }
370
+ try {
306
371
  // The next match is looked for after what was written, or a replacement that holds the query would find itself again.
307
- find.pendingAnchor = mark.from + replacementText(this.model.getText(), match, replacement, false, replaceOptions.preserveCase).length;
372
+ find.pendingAnchor = match.to;
308
373
  if (!this.model.replace(match, replacement, { preserveCase: replaceOptions.preserveCase })) {
309
374
  find.pendingAnchor = undefined;
310
375
  return false;
@@ -319,23 +384,48 @@ class SmartEditor {
319
384
  return true;
320
385
  }
321
386
  replaceAll(replacement, options = {}) {
322
- const query = this.view.find.activeQuery;
323
- if (query === null || this.blockedByReadOnly()) {
387
+ const { find } = this.view;
388
+ const query = find.activeQuery;
389
+ if (query === null || find.state.noSelection === true || this.blockedByReadOnly()) {
324
390
  return 0;
325
391
  }
326
392
  try {
327
- return this.model.replaceAll(query.text, replacement, {
328
- caseSensitive: query.caseSensitive,
329
- wholeWord: query.wholeWord,
330
- regex: query.regex,
331
- preserveCase: options.preserveCase,
332
- ...this.view.find.scope
333
- });
393
+ const matches = find.completeMatches;
394
+ if (matches !== null) {
395
+ let characters = 0;
396
+ for (const match of matches) {
397
+ characters += replacementText('', match, replacement, false, options.preserveCase, MAX_REPLACEMENT_CHARACTERS).length;
398
+ if (characters > MAX_REPLACEMENT_CHARACTERS) {
399
+ find.reportReplaceFailed('limit');
400
+ return 0;
401
+ }
402
+ }
403
+ const count = this.model.replaceMatches(matches, replacement, { preserveCase: options.preserveCase });
404
+ find.reportReplaced(count);
405
+ return count;
406
+ }
407
+ void this.replaceAllAsync(replacement, options);
408
+ return 0;
334
409
  }
335
- catch {
410
+ catch (error) {
411
+ find.reportReplaceFailed(error instanceof RangeError ? 'limit' : 'error');
336
412
  return 0;
337
413
  }
338
414
  }
415
+ async replaceAllAsync(replacement, options = {}) {
416
+ const { find } = this.view;
417
+ if (this.disposed || this.blockedByReadOnly() || find.activeQuery === null || find.state.noSelection) {
418
+ return 0;
419
+ }
420
+ if (find.state.limited) {
421
+ find.reportReplaceFailed('limit');
422
+ return 0;
423
+ }
424
+ if (find.completeMatches !== null) {
425
+ return this.replaceAll(replacement, options);
426
+ }
427
+ return find.replaceAll(replacement, options.preserveCase === true, () => !this.disposed && !this.settings.readOnly);
428
+ }
339
429
  setReplacePreview(replacement, options = {}) {
340
430
  this.view.setReplacePreview(replacement, options.preserveCase === true);
341
431
  }
@@ -359,24 +449,38 @@ class SmartEditor {
359
449
  if (query.text === '') {
360
450
  return false;
361
451
  }
362
- let matches;
452
+ const { anchor, head } = this.model.getPrimary();
453
+ const offset = direction === 1 ? Math.max(anchor, head) : Math.min(anchor, head);
454
+ const reveal = (target) => {
455
+ if (target === null || this.disposed) {
456
+ return false;
457
+ }
458
+ this.view.ensureVisible(target.from);
459
+ this.model.setSelections([direction === 1 ? { anchor: target.from, head: target.to } : { anchor: target.to, head: target.from }]);
460
+ this.view.revealCaret(target.from > head ? 'centerDown' : 'centerUp');
461
+ return true;
462
+ };
463
+ if (query.regex) {
464
+ const revision = this.model.getRevision();
465
+ void this.view.find.nextFromCursor(query, offset, direction).then((target) => {
466
+ const current = this.model.getPrimary();
467
+ if (this.model.getRevision() === revision && current.anchor === anchor && current.head === head) {
468
+ reveal(target);
469
+ }
470
+ });
471
+ return true;
472
+ }
363
473
  try {
364
- matches = this.model.find(query.text, { caseSensitive: query.caseSensitive, wholeWord: query.wholeWord, regex: query.regex });
474
+ return reveal(this.model.findNext(query.text, offset, {
475
+ caseSensitive: query.caseSensitive,
476
+ wholeWord: query.wholeWord,
477
+ backwards: direction === -1,
478
+ wrap: true
479
+ }));
365
480
  }
366
481
  catch {
367
482
  return false;
368
483
  }
369
- if (matches.length === 0) {
370
- return false;
371
- }
372
- const { anchor, head } = this.model.getPrimary();
373
- const from = Math.min(anchor, head);
374
- const to = Math.max(anchor, head);
375
- const target = direction === 1 ? (matches.find((match) => match.from >= to) ?? matches[0]) : (matches.findLast((match) => match.to <= from) ?? matches.at(-1));
376
- this.view.ensureVisible(target.from);
377
- this.model.setSelections([direction === 1 ? { anchor: target.from, head: target.to } : { anchor: target.to, head: target.from }]);
378
- this.view.revealCaret(target.from > head ? 'centerDown' : 'centerUp');
379
- return true;
380
484
  }
381
485
  blockedByReadOnly() {
382
486
  if (!this.settings.readOnly) {
@@ -406,8 +510,8 @@ class SmartEditor {
406
510
  }
407
511
  this.view.applySettings();
408
512
  }
409
- setChangeMarks(marks) {
410
- this.view.setChangeMarks(marks);
513
+ setChangeMarks(marks, layer) {
514
+ this.view.setChangeMarks(marks, layer);
411
515
  }
412
516
  setAttributionMarks(marks) {
413
517
  this.view.setAttributionMarks(marks);
@@ -415,6 +519,26 @@ class SmartEditor {
415
519
  setLineHighlights(highlights) {
416
520
  this.view.setLineHighlights(highlights);
417
521
  }
522
+ setLineLabels(labels) {
523
+ this.view.setLineLabels(labels);
524
+ }
525
+ setInputPopup(popup) {
526
+ this.view.setInputPopup(popup);
527
+ }
528
+ announce(message) {
529
+ this.view.announce(message);
530
+ }
531
+ setMessages(messages) {
532
+ this.settings.messages = { ...this.settings.messages, ...messages };
533
+ this.view.repaint();
534
+ }
535
+ setLineNumbers(labels) {
536
+ this.view.setLineNumbers(labels);
537
+ }
538
+ setLineTokens(tokens) {
539
+ this.grammarPreparation.pause(tokens !== null);
540
+ this.view.setLineTokens(tokens);
541
+ }
418
542
  renderCode(container, text, options = {}) {
419
543
  this.view.renderCode(container, text, options);
420
544
  }
@@ -430,12 +554,28 @@ class SmartEditor {
430
554
  at: this.offsetAt({ line: widget.line, character: 0 }),
431
555
  placement: widget.placement ?? 'below',
432
556
  height: widget.height,
557
+ fixed: widget.fixed,
433
558
  render: (container) => {
434
559
  container.classList.add('se-widget');
435
560
  widget.render(container);
436
561
  }
437
562
  })));
438
563
  }
564
+ setReplacements(replacements, owner = DEFAULT_WIDGET_OWNER) {
565
+ this.view.setReplacements(owner, replacements.map((replacement) => ({
566
+ id: `replacement:${owner}:${replacement.id}`,
567
+ from: this.offsetAt({ line: replacement.startLine, character: 0 }),
568
+ to: this.model.getLine(Math.max(0, Math.min(replacement.endLine, this.model.getLineCount() - 1))).end,
569
+ height: replacement.height,
570
+ label: replacement.label,
571
+ enterable: replacement.enterable,
572
+ onReveal: replacement.onReveal === undefined ? undefined : () => replacement.onReveal(),
573
+ render: (container) => {
574
+ container.classList.add('se-widget-replacement');
575
+ replacement.render(container);
576
+ }
577
+ })));
578
+ }
439
579
  setLineActions(actions, owner = DEFAULT_WIDGET_OWNER) {
440
580
  this.view.setLineActions(owner, actions.map((action) => ({
441
581
  id: action.id,
@@ -502,6 +642,10 @@ class SmartEditor {
502
642
  this.settings.guides = guides;
503
643
  this.view.applySettings();
504
644
  }
645
+ setStickyScroll(sticky) {
646
+ this.settings.stickyScroll = sticky;
647
+ this.view.applySettings();
648
+ }
505
649
  setWhitespace(whitespace) {
506
650
  this.settings.whitespace = whitespace;
507
651
  this.view.applySettings();
@@ -568,6 +712,9 @@ class SmartEditor {
568
712
  this.settings.readOnlyReason = reason;
569
713
  this.view.applySettings();
570
714
  }
715
+ isReadOnly() {
716
+ return this.settings.readOnly;
717
+ }
571
718
  runCommand(command) {
572
719
  return this.controller.command(command);
573
720
  }
@@ -582,6 +729,7 @@ class SmartEditor {
582
729
  return;
583
730
  }
584
731
  this.disposed = true;
732
+ this.grammarPreparation.dispose();
585
733
  this.changes.clear();
586
734
  this.textChanges.clear();
587
735
  this.carets.clear();
package/dist/fake.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- import type { Editor, EditorAttributionHover, EditorAttributionMark, EditorBlock, EditorCodeBlockOptions, EditorLineAction, EditorLineHighlight, EditorChangeMark, EditorCodeVision, EditorClick, EditorClickHandler, EditorContextMenu, EditorContentChange, EditorEngine, EditorFindQuery, EditorFindState, EditorReplaceOptions, EditorGutterAction, EditorGutterMarker, EditorHighlight, EditorHover, EditorIndentation, EditorGhostText, EditorInlayHint, EditorKeyHandler, EditorMarker, EditorOptions, EditorPosition, EditorRemoteCursor, EditorRange, EditorReveal, EditorRect, EditorRunCommand, EditorSelectionRanges, EditorFoldHints, EditorFoldOutline, EditorFolds, EditorSemanticToken, EditorSmartKeys, 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, EditorTextChange, EditorTrackedRange, EditorTheme, 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;
5
5
  readonly language: string | undefined;
6
6
  readonly path: string | undefined;
7
7
  readonly column: number | null;
8
- readonly scrollTop: number | null;
8
+ scrollTop: number | null;
9
9
  wrap: boolean;
10
10
  theme: EditorTheme;
11
11
  readOnly: boolean;
@@ -54,6 +54,7 @@ export declare class FakeEditor implements Editor {
54
54
  replacementsOfAll: string[];
55
55
  replace(replacement: string, options?: EditorReplaceOptions): boolean;
56
56
  replaceAll(replacement: string, options?: EditorReplaceOptions): number;
57
+ replaceAllAsync(replacement: string, options?: EditorReplaceOptions): Promise<number>;
57
58
  setReplacePreview(replacement: string | null): void;
58
59
  selectFindMatches(): number;
59
60
  findFromCursor(query: EditorFindQuery, direction: 1 | -1): boolean;
@@ -63,8 +64,9 @@ export declare class FakeEditor implements Editor {
63
64
  setWrap(wrap: boolean): void;
64
65
  blocks: readonly EditorBlock[] | null;
65
66
  private readonly scopes;
66
- changeMarks: readonly EditorChangeMark[];
67
- setChangeMarks(marks: readonly EditorChangeMark[]): void;
67
+ get changeMarks(): readonly EditorChangeMark[];
68
+ private readonly changeLayers;
69
+ setChangeMarks(marks: readonly EditorChangeMark[], layer?: string): void;
68
70
  lineHighlights: readonly EditorLineHighlight[];
69
71
  setLineHighlights(highlights: readonly EditorLineHighlight[]): void;
70
72
  codeBlocks: {
@@ -72,6 +74,18 @@ export declare class FakeEditor implements Editor {
72
74
  text: string;
73
75
  options: EditorCodeBlockOptions;
74
76
  }[];
77
+ lineNumbers: ((line: number) => string | null) | null;
78
+ lineTokens: ((line: number) => readonly LineToken[] | null | undefined) | null;
79
+ setLineNumbers(labels: ((line: number) => string | null) | null): void;
80
+ lineLabels: ((line: number) => string | null) | null;
81
+ setLineLabels(labels: ((line: number) => string | null) | null): void;
82
+ inputPopup: EditorInputPopup | null;
83
+ setInputPopup(popup: EditorInputPopup | null): void;
84
+ announcements: string[];
85
+ announce(message: string): void;
86
+ messages: Partial<EditorMessages>;
87
+ setMessages(messages: Partial<EditorMessages>): void;
88
+ setLineTokens(tokens: ((line: number) => readonly LineToken[] | null | undefined) | null): void;
75
89
  renderCode(container: HTMLElement, text: string, options?: EditorCodeBlockOptions): void;
76
90
  remoteCursors: readonly EditorRemoteCursor[];
77
91
  setRemoteCursors(cursors: readonly EditorRemoteCursor[]): void;
@@ -84,6 +98,8 @@ export declare class FakeEditor implements Editor {
84
98
  get widgets(): readonly EditorWidget[];
85
99
  private readonly drawnWidgets;
86
100
  setWidgets(widgets: readonly EditorWidget[], owner?: string): void;
101
+ readonly replacementsByOwner: Map<string, readonly EditorReplacement[]>;
102
+ setReplacements(replacements: readonly EditorReplacement[], owner?: string): void;
87
103
  readonly lineActionsByOwner: Map<string, readonly EditorLineAction[]>;
88
104
  setLineActions(actions: readonly EditorLineAction[], owner?: string): void;
89
105
  codeVision: readonly EditorCodeVision[];
@@ -103,9 +119,11 @@ export declare class FakeEditor implements Editor {
103
119
  enterScope(scope: readonly EditorBlock[]): void;
104
120
  smartKeys: Partial<EditorSmartKeys>;
105
121
  guides: boolean;
122
+ stickyScroll: boolean;
106
123
  whitespace: boolean;
107
124
  rightMargin: number | null;
108
125
  setGuides(guides: boolean): void;
126
+ setStickyScroll(sticky: boolean): void;
109
127
  setWhitespace(whitespace: boolean): void;
110
128
  setRightMargin(column: number | null): void;
111
129
  foldOutline: EditorFoldOutline;
@@ -129,11 +147,26 @@ export declare class FakeEditor implements Editor {
129
147
  };
130
148
  private readonly carets;
131
149
  private readonly hovers;
150
+ private readonly lineHeights;
132
151
  private readonly views;
133
152
  private readonly keys;
134
153
  setMarkers(markers: readonly EditorMarker[]): void;
135
154
  inlayHints: readonly EditorInlayHint[];
136
155
  setInlayHints(hints: readonly EditorInlayHint[]): void;
156
+ private readonly inlayHovers;
157
+ private readonly inlayHandlers;
158
+ inlayLink: {
159
+ readonly id: string;
160
+ readonly part: number | null;
161
+ } | null;
162
+ onInlayHover(listener: (target: EditorInlayTarget | null) => void): () => void;
163
+ hoverInlay(id: string | null, part?: number | null): void;
164
+ onInlayClick(handler: EditorInlayClickHandler): () => void;
165
+ clickInlay(click: Partial<EditorInlayClick> & Pick<EditorInlayClick, 'id'>): boolean;
166
+ setInlayLink(target: {
167
+ readonly id: string;
168
+ readonly part: number | null;
169
+ } | null): void;
137
170
  ghost: EditorGhostText | null;
138
171
  setGhostText(ghost: EditorGhostText | null): void;
139
172
  semanticTokens: readonly EditorSemanticToken[] | null;
@@ -146,6 +179,12 @@ export declare class FakeEditor implements Editor {
146
179
  getFolds(): EditorFolds;
147
180
  getScrollTop(): number;
148
181
  selection: EditorRange | null;
182
+ contentHeight: number;
183
+ setScrollTop(top: number): void;
184
+ getLineHeight(line: number): number;
185
+ getBaseLineHeight(): number;
186
+ onLineHeights(listener: Listener): () => void;
187
+ getContentHeight(): number;
149
188
  getSelection(): EditorRange;
150
189
  private otherSelections;
151
190
  get otherCarets(): EditorPosition[];
@@ -174,10 +213,11 @@ export declare class FakeEditor implements Editor {
174
213
  click(click: EditorClick): boolean;
175
214
  openContextMenu(menu: EditorContextMenu): void;
176
215
  press(event: Pick<KeyboardEvent, 'key'> & Partial<KeyboardEvent>): boolean;
177
- applyEdits(edits: readonly EditorContentChange[]): boolean;
216
+ applyEdits(edits: readonly EditorContentChange[], options?: EditorApplyEditsOptions): boolean;
178
217
  setTheme(theme: EditorTheme): void;
179
218
  refreshFont(): void;
180
219
  setReadOnly(readOnly: boolean, reason?: string): void;
220
+ isReadOnly(): boolean;
181
221
  readonly commands: EditorRunCommand[];
182
222
  runCommand(command: EditorRunCommand): boolean;
183
223
  focus(): void;