@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.
- package/dist/attribution.d.ts +9 -8
- package/dist/attribution.js +44 -9
- package/dist/bidi.d.ts +44 -0
- package/dist/bidi.js +26 -0
- package/dist/column-selection.js +2 -1
- package/dist/controller.d.ts +6 -1
- package/dist/controller.js +93 -3
- package/dist/editor.css +81 -1
- package/dist/engine.js +189 -41
- package/dist/fake.d.ts +45 -5
- package/dist/fake.js +121 -13
- package/dist/find-search.d.ts +26 -0
- package/dist/find-search.js +130 -0
- package/dist/find.d.ts +50 -2
- package/dist/find.js +575 -25
- package/dist/geometry-stops.d.ts +6 -0
- package/dist/geometry-stops.js +47 -0
- package/dist/grammar-preparation.d.ts +29 -0
- package/dist/grammar-preparation.js +147 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -0
- package/dist/keymap-table.d.ts +10 -1
- package/dist/keymap-table.js +37 -1
- package/dist/keymap.d.ts +1 -0
- package/dist/keymap.js +4 -1
- package/dist/layout-changes.d.ts +6 -0
- package/dist/layout-changes.js +27 -0
- package/dist/layout.d.ts +45 -2
- package/dist/layout.js +202 -58
- package/dist/offsets.d.ts +1 -0
- package/dist/offsets.js +23 -0
- package/dist/outline.js +5 -4
- package/dist/paint.d.ts +11 -3
- package/dist/paint.js +180 -34
- package/dist/search-client.d.ts +27 -0
- package/dist/search-client.js +210 -0
- package/dist/search-protocol.d.ts +103 -0
- package/dist/search-protocol.js +3 -0
- package/dist/search-worker.d.ts +11 -0
- package/dist/search-worker.js +137 -0
- package/dist/semantic.d.ts +2 -1
- package/dist/semantic.js +6 -1
- package/dist/shiki-document.d.ts +8 -0
- package/dist/shiki-document.js +93 -0
- package/dist/shiki-worker.d.ts +65 -0
- package/dist/shiki-worker.js +265 -0
- package/dist/shiki.d.ts +1 -0
- package/dist/shiki.js +96 -33
- package/dist/testing.d.ts +1 -0
- package/dist/tokens.d.ts +2 -0
- package/dist/tokens.js +37 -7
- package/dist/touch.d.ts +27 -0
- package/dist/touch.js +100 -0
- package/dist/types.d.ts +86 -2
- package/dist/uniform-geometry.d.ts +7 -0
- package/dist/uniform-geometry.js +49 -0
- package/dist/view.d.ts +69 -17
- package/dist/view.js +427 -97
- package/dist/worker-client.d.ts +37 -0
- package/dist/worker-client.js +195 -0
- package/package.json +17 -2
- package/src/attribution.ts +50 -14
- package/src/bidi.ts +32 -0
- package/src/column-selection.ts +2 -1
- package/src/controller.ts +97 -3
- package/src/editor.css +81 -1
- package/src/engine.ts +222 -42
- package/src/fake.ts +157 -14
- package/src/find-search.ts +165 -0
- package/src/find.ts +622 -21
- package/src/geometry-stops.ts +51 -0
- package/src/grammar-preparation.ts +158 -0
- package/src/index.ts +10 -0
- package/src/keymap-table.ts +44 -2
- package/src/keymap.ts +5 -1
- package/src/layout-changes.ts +33 -0
- package/src/layout.ts +262 -63
- package/src/offsets.ts +24 -0
- package/src/outline.ts +5 -4
- package/src/paint.ts +202 -36
- package/src/search-client.ts +306 -0
- package/src/search-protocol.ts +100 -0
- package/src/search-worker.ts +171 -0
- package/src/semantic.ts +8 -2
- package/src/shiki-document.ts +143 -0
- package/src/shiki-worker.ts +344 -0
- package/src/shiki.ts +103 -33
- package/src/testing.ts +2 -0
- package/src/tokens.ts +36 -7
- package/src/touch.ts +134 -0
- package/src/types.ts +178 -8
- package/src/uniform-geometry.ts +57 -0
- package/src/view.ts +505 -102
- 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
|
-
|
|
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) => ({
|
|
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
|
|
296
|
-
|
|
297
|
-
if (mark === null || query === null || this.blockedByReadOnly()) {
|
|
356
|
+
const match = find.currentMatch;
|
|
357
|
+
if (this.blockedByReadOnly()) {
|
|
298
358
|
return false;
|
|
299
359
|
}
|
|
300
|
-
|
|
301
|
-
|
|
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 =
|
|
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
|
|
323
|
-
|
|
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
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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;
|