@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/touch.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/* A finger that moves further than this, in pixels, is scrolling and not tapping. */
|
|
2
|
+
const TAP_SLOP = 10;
|
|
3
|
+
/* A finger held still this long selects the word under it. */
|
|
4
|
+
const LONG_PRESS_MS = 500;
|
|
5
|
+
/* A second tap this soon after the first, this close to it, is a double tap. */
|
|
6
|
+
const DOUBLE_TAP_MS = 300;
|
|
7
|
+
const DOUBLE_TAP_DISTANCE = 30;
|
|
8
|
+
/*
|
|
9
|
+
* A finger on the text. The viewport scrolls natively, so a drag is left to the browser and makes no
|
|
10
|
+
* selection; a tap places the caret, a double tap or a long press selects a word.
|
|
11
|
+
*/
|
|
12
|
+
export class TouchSelection {
|
|
13
|
+
contact;
|
|
14
|
+
timer;
|
|
15
|
+
lastTap;
|
|
16
|
+
host;
|
|
17
|
+
constructor(host) {
|
|
18
|
+
this.host = host;
|
|
19
|
+
}
|
|
20
|
+
/* Whether the finger that is down held still long enough to select a word. */
|
|
21
|
+
get pressed() {
|
|
22
|
+
return this.contact?.pressed === true;
|
|
23
|
+
}
|
|
24
|
+
start(event, area = 'text', taken) {
|
|
25
|
+
this.cancel();
|
|
26
|
+
this.contact = { id: event.pointerId, x: event.clientX, y: event.clientY, area, moved: false, pressed: false, taken };
|
|
27
|
+
if (area === 'text') {
|
|
28
|
+
this.timer = setTimeout(() => this.press(), LONG_PRESS_MS);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
move(event) {
|
|
32
|
+
const contact = this.contact;
|
|
33
|
+
if (contact === undefined || event.pointerId !== contact.id || contact.moved) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (Math.abs(event.clientX - contact.x) > TAP_SLOP || Math.abs(event.clientY - contact.y) > TAP_SLOP) {
|
|
37
|
+
contact.moved = true;
|
|
38
|
+
this.clearTimer();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/* The finger lifted: a tap that did not scroll and was not a long press lands here. */
|
|
42
|
+
end(event) {
|
|
43
|
+
const contact = this.contact;
|
|
44
|
+
if (contact === undefined || event.pointerId !== contact.id) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
this.cancel();
|
|
48
|
+
if (event.type === 'pointercancel' || contact.moved || contact.pressed) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
this.tap(contact, event);
|
|
52
|
+
}
|
|
53
|
+
dispose() {
|
|
54
|
+
this.cancel();
|
|
55
|
+
}
|
|
56
|
+
tap(contact, event) {
|
|
57
|
+
const { model } = this.host;
|
|
58
|
+
const offset = this.host.offsetAt(contact.x, contact.y);
|
|
59
|
+
this.host.focus();
|
|
60
|
+
if (contact.area === 'gutter') {
|
|
61
|
+
const line = this.host.lineAt(offset);
|
|
62
|
+
model.setSelections([{ anchor: line.from, head: line.to }]);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (contact.taken?.()) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const last = this.lastTap;
|
|
69
|
+
const double = last !== undefined &&
|
|
70
|
+
event.timeStamp - last.time <= DOUBLE_TAP_MS &&
|
|
71
|
+
Math.abs(contact.x - last.x) <= DOUBLE_TAP_DISTANCE &&
|
|
72
|
+
Math.abs(contact.y - last.y) <= DOUBLE_TAP_DISTANCE;
|
|
73
|
+
this.lastTap = double ? undefined : { time: event.timeStamp, x: contact.x, y: contact.y };
|
|
74
|
+
const word = double ? model.wordSelectionAt(offset, this.host.camelHumps()) : null;
|
|
75
|
+
model.setSelections([word === null ? { anchor: offset, head: offset } : { anchor: word.from, head: word.to }]);
|
|
76
|
+
}
|
|
77
|
+
press() {
|
|
78
|
+
const contact = this.contact;
|
|
79
|
+
this.timer = undefined;
|
|
80
|
+
if (contact === undefined || contact.moved) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
contact.pressed = true;
|
|
84
|
+
this.lastTap = undefined;
|
|
85
|
+
const offset = this.host.offsetAt(contact.x, contact.y);
|
|
86
|
+
const word = this.host.model.wordSelectionAt(offset, this.host.camelHumps());
|
|
87
|
+
this.host.focus();
|
|
88
|
+
this.host.model.setSelections([word === null ? { anchor: offset, head: offset } : { anchor: word.from, head: word.to }]);
|
|
89
|
+
}
|
|
90
|
+
clearTimer() {
|
|
91
|
+
if (this.timer !== undefined) {
|
|
92
|
+
clearTimeout(this.timer);
|
|
93
|
+
}
|
|
94
|
+
this.timer = undefined;
|
|
95
|
+
}
|
|
96
|
+
cancel() {
|
|
97
|
+
this.clearTimer();
|
|
98
|
+
this.contact = undefined;
|
|
99
|
+
}
|
|
100
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { EditorSearchClientOptions } from './search-client.ts';
|
|
1
2
|
import type { Keymap } from './keymap-table.ts';
|
|
2
3
|
import type { EditorCommand, FoldRole } from '@adecore/editor-core';
|
|
3
4
|
export type { EditorCommand, FoldRole };
|
|
@@ -14,6 +15,7 @@ export interface EditorFolds {
|
|
|
14
15
|
}
|
|
15
16
|
export type EditorTheme = string;
|
|
16
17
|
export interface EditorOptions {
|
|
18
|
+
readonly handBack?: readonly KeyChord[];
|
|
17
19
|
readonly text: string;
|
|
18
20
|
readonly language?: string;
|
|
19
21
|
readonly path?: string;
|
|
@@ -24,9 +26,11 @@ export interface EditorOptions {
|
|
|
24
26
|
readonly indentation?: EditorIndentation;
|
|
25
27
|
readonly smartKeys?: Partial<EditorSmartKeys>;
|
|
26
28
|
readonly guides?: boolean;
|
|
29
|
+
readonly stickyScroll?: boolean;
|
|
27
30
|
readonly whitespace?: boolean;
|
|
28
31
|
readonly rightMargin?: number | null;
|
|
29
32
|
readonly foldOutline?: EditorFoldOutline;
|
|
33
|
+
readonly folding?: boolean;
|
|
30
34
|
readonly messages?: Partial<EditorMessages>;
|
|
31
35
|
readonly label?: string;
|
|
32
36
|
readonly folds?: EditorFolds;
|
|
@@ -37,6 +41,12 @@ export interface EditorOptions {
|
|
|
37
41
|
}
|
|
38
42
|
export interface EditorMessages {
|
|
39
43
|
readonly noMoreOccurrences: string;
|
|
44
|
+
readonly fold: string;
|
|
45
|
+
readonly unfold: string;
|
|
46
|
+
}
|
|
47
|
+
export interface EditorInputPopup {
|
|
48
|
+
readonly controls: string;
|
|
49
|
+
readonly activeDescendant?: string;
|
|
40
50
|
}
|
|
41
51
|
export interface EditorSmartKeys {
|
|
42
52
|
readonly autoPairBrackets: boolean;
|
|
@@ -93,8 +103,11 @@ export interface EditorLineHighlight {
|
|
|
93
103
|
readonly color: EditorMarkColor;
|
|
94
104
|
readonly fill?: EditorMarkColor;
|
|
95
105
|
readonly sign?: string;
|
|
106
|
+
readonly bar?: 'solid' | 'hatched';
|
|
107
|
+
readonly emphasis?: ReadonlyArray<ReadonlyArray<readonly [number, number]>>;
|
|
96
108
|
}
|
|
97
109
|
export interface EditorCodeBlockOptions {
|
|
110
|
+
readonly tokens?: ReadonlyArray<readonly LineToken[]> | null;
|
|
98
111
|
readonly firstLine?: number;
|
|
99
112
|
readonly sign?: string;
|
|
100
113
|
readonly color?: EditorMarkColor;
|
|
@@ -117,9 +130,14 @@ export interface EditorContentChange {
|
|
|
117
130
|
readonly range: EditorRange;
|
|
118
131
|
readonly text: string;
|
|
119
132
|
}
|
|
133
|
+
export interface EditorApplyEditsOptions {
|
|
134
|
+
readonly mapSelections?: (range: EditorRange) => EditorRange;
|
|
135
|
+
readonly mergeUndo?: boolean;
|
|
136
|
+
}
|
|
120
137
|
export interface EditorTextChange {
|
|
121
138
|
readonly changes: readonly EditorContentChange[];
|
|
122
139
|
readonly source: 'input' | 'command' | 'external';
|
|
140
|
+
readonly typed?: boolean;
|
|
123
141
|
}
|
|
124
142
|
export type EditorMarkerSeverity = 'error' | 'warning' | 'info' | 'hint';
|
|
125
143
|
export interface EditorMarker {
|
|
@@ -162,6 +180,17 @@ export interface EditorWidget {
|
|
|
162
180
|
readonly line: number;
|
|
163
181
|
readonly placement?: 'above' | 'below';
|
|
164
182
|
readonly height?: number;
|
|
183
|
+
readonly fixed?: boolean;
|
|
184
|
+
render(container: HTMLElement): void;
|
|
185
|
+
}
|
|
186
|
+
export interface EditorReplacement {
|
|
187
|
+
readonly id: string;
|
|
188
|
+
readonly startLine: number;
|
|
189
|
+
readonly endLine: number;
|
|
190
|
+
readonly height?: number;
|
|
191
|
+
readonly label?: string;
|
|
192
|
+
readonly enterable?: boolean;
|
|
193
|
+
onReveal?(): void;
|
|
165
194
|
render(container: HTMLElement): void;
|
|
166
195
|
}
|
|
167
196
|
export interface EditorLineAction {
|
|
@@ -187,6 +216,7 @@ export interface EditorSemanticToken {
|
|
|
187
216
|
readonly character: number;
|
|
188
217
|
readonly length: number;
|
|
189
218
|
readonly scopes: readonly string[];
|
|
219
|
+
readonly within?: LineTokenKind;
|
|
190
220
|
}
|
|
191
221
|
export interface ScopeStyle {
|
|
192
222
|
readonly color: string;
|
|
@@ -197,7 +227,26 @@ export type ScopeColorSource = (theme: EditorTheme) => Promise<ScopeColors | nul
|
|
|
197
227
|
export interface EditorInlayHint {
|
|
198
228
|
readonly position: EditorPosition;
|
|
199
229
|
readonly label: string;
|
|
230
|
+
readonly id?: string;
|
|
231
|
+
readonly parts?: readonly string[];
|
|
232
|
+
readonly paddingLeft?: boolean;
|
|
233
|
+
readonly paddingRight?: boolean;
|
|
234
|
+
}
|
|
235
|
+
export interface EditorInlayTarget {
|
|
236
|
+
readonly id: string;
|
|
237
|
+
readonly part: number | null;
|
|
238
|
+
readonly rect: EditorRect;
|
|
239
|
+
}
|
|
240
|
+
export interface EditorInlayClick {
|
|
241
|
+
readonly id: string;
|
|
242
|
+
readonly part: number | null;
|
|
243
|
+
readonly mod: boolean;
|
|
244
|
+
readonly alt: boolean;
|
|
245
|
+
readonly shift: boolean;
|
|
246
|
+
readonly clicks: 1 | 2;
|
|
247
|
+
readonly touch: boolean;
|
|
200
248
|
}
|
|
249
|
+
export type EditorInlayClickHandler = (click: EditorInlayClick) => boolean;
|
|
201
250
|
export interface EditorGhostText {
|
|
202
251
|
readonly position: EditorPosition;
|
|
203
252
|
readonly text: string;
|
|
@@ -207,10 +256,13 @@ export interface EditorGutterAction {
|
|
|
207
256
|
readonly line: number;
|
|
208
257
|
readonly label: string;
|
|
209
258
|
}
|
|
259
|
+
export type EditorGutterIcon = 'sparkles' | 'book-open';
|
|
210
260
|
export interface EditorGutterMarker {
|
|
211
261
|
readonly id: string;
|
|
212
262
|
readonly line: number;
|
|
213
263
|
readonly label: string;
|
|
264
|
+
readonly icon?: EditorGutterIcon;
|
|
265
|
+
readonly pressed?: boolean;
|
|
214
266
|
}
|
|
215
267
|
export type EditorReveal = 'relative' | 'center' | 'centerDown' | 'centerUp';
|
|
216
268
|
export interface EditorIndentation {
|
|
@@ -228,6 +280,13 @@ export interface EditorFindState {
|
|
|
228
280
|
readonly count: number;
|
|
229
281
|
readonly current: number | null;
|
|
230
282
|
readonly noSelection?: boolean;
|
|
283
|
+
readonly limited?: boolean;
|
|
284
|
+
readonly searching?: boolean;
|
|
285
|
+
readonly failed?: 'invalid' | 'timeout' | 'unavailable' | 'error';
|
|
286
|
+
readonly captureFailed?: 'timeout' | 'unavailable' | 'error';
|
|
287
|
+
readonly replaceFailed?: 'limit' | 'timeout' | 'unavailable' | 'error';
|
|
288
|
+
readonly replaced?: number;
|
|
289
|
+
readonly large?: boolean;
|
|
231
290
|
}
|
|
232
291
|
export interface EditorReplaceOptions {
|
|
233
292
|
readonly preserveCase?: boolean;
|
|
@@ -251,6 +310,7 @@ export interface Editor {
|
|
|
251
310
|
findStep(direction: 1 | -1): void;
|
|
252
311
|
replace(replacement: string, options?: EditorReplaceOptions): boolean;
|
|
253
312
|
replaceAll(replacement: string, options?: EditorReplaceOptions): number;
|
|
313
|
+
replaceAllAsync(replacement: string, options?: EditorReplaceOptions): Promise<number>;
|
|
254
314
|
setReplacePreview(replacement: string | null, options?: EditorReplaceOptions): void;
|
|
255
315
|
selectFindMatches(): number;
|
|
256
316
|
findFromCursor(query: EditorFindQuery, direction: 1 | -1): boolean;
|
|
@@ -260,17 +320,21 @@ export interface Editor {
|
|
|
260
320
|
setIndentation(indentation: EditorIndentation): void;
|
|
261
321
|
setSmartKeys(keys: Partial<EditorSmartKeys>): void;
|
|
262
322
|
setGuides(guides: boolean): void;
|
|
323
|
+
setStickyScroll?(sticky: boolean): void;
|
|
263
324
|
setWhitespace(whitespace: boolean): void;
|
|
264
325
|
setRightMargin(column: number | null): void;
|
|
265
326
|
setFoldOutline(outline: EditorFoldOutline): void;
|
|
266
327
|
setLabel(label: string): void;
|
|
267
328
|
setFoldHints(hints: EditorFoldHints | null): void;
|
|
268
|
-
setChangeMarks(marks: readonly EditorChangeMark[]): void;
|
|
329
|
+
setChangeMarks(marks: readonly EditorChangeMark[], layer?: string): void;
|
|
269
330
|
setBlocks(blocks: readonly EditorBlock[] | null): void;
|
|
270
331
|
onScope(listener: (scope: readonly EditorBlock[]) => void): () => void;
|
|
271
332
|
setAttributionMarks(marks: readonly EditorAttributionMark[]): void;
|
|
272
333
|
setRemoteCursors(cursors: readonly EditorRemoteCursor[]): void;
|
|
273
334
|
setLineHighlights(highlights: readonly EditorLineHighlight[]): void;
|
|
335
|
+
setLineNumbers(labels: ((line: number) => string | null) | null): void;
|
|
336
|
+
setLineLabels(labels: ((line: number) => string | null) | null): void;
|
|
337
|
+
setLineTokens(tokens: ((line: number) => readonly LineToken[] | null | undefined) | null): void;
|
|
274
338
|
renderCode(container: HTMLElement, text: string, options?: EditorCodeBlockOptions): void;
|
|
275
339
|
onAttributionHover(listener: (hover: EditorAttributionHover | null) => void): () => void;
|
|
276
340
|
setMarkers(markers: readonly EditorMarker[]): void;
|
|
@@ -278,6 +342,12 @@ export interface Editor {
|
|
|
278
342
|
setLink(range: EditorRange | null): void;
|
|
279
343
|
setSemanticTokens(tokens: readonly EditorSemanticToken[] | null): void;
|
|
280
344
|
setInlayHints(hints: readonly EditorInlayHint[]): void;
|
|
345
|
+
onInlayHover?(listener: (target: EditorInlayTarget | null) => void): () => void;
|
|
346
|
+
onInlayClick?(handler: EditorInlayClickHandler): () => void;
|
|
347
|
+
setInlayLink?(target: {
|
|
348
|
+
readonly id: string;
|
|
349
|
+
readonly part: number | null;
|
|
350
|
+
} | null): void;
|
|
281
351
|
setGhostText(ghost: EditorGhostText | null): void;
|
|
282
352
|
setGutterAction(action: EditorGutterAction | null): void;
|
|
283
353
|
onGutterAction(listener: (line: number) => void): () => void;
|
|
@@ -285,6 +355,11 @@ export interface Editor {
|
|
|
285
355
|
onGutterMarker(listener: (id: string) => void): () => void;
|
|
286
356
|
getCaret(): EditorPosition;
|
|
287
357
|
getScrollTop(): number;
|
|
358
|
+
setScrollTop(top: number): void;
|
|
359
|
+
getLineHeight(line: number): number;
|
|
360
|
+
getBaseLineHeight?(): number;
|
|
361
|
+
onLineHeights(listener: () => void): () => void;
|
|
362
|
+
getContentHeight(): number;
|
|
288
363
|
getFolds(): EditorFolds;
|
|
289
364
|
getSelection(): EditorRange;
|
|
290
365
|
getSelections(): EditorRange[];
|
|
@@ -292,12 +367,16 @@ export interface Editor {
|
|
|
292
367
|
setCaret(position: EditorPosition, reveal?: EditorReveal): void;
|
|
293
368
|
setSelection(range: EditorRange, reveal?: EditorReveal): void;
|
|
294
369
|
setSelections(ranges: readonly EditorRange[], reveal?: EditorReveal): void;
|
|
370
|
+
setInputPopup(popup: EditorInputPopup | null): void;
|
|
371
|
+
announce(message: string): void;
|
|
372
|
+
setMessages(messages: Partial<EditorMessages>): void;
|
|
295
373
|
onCaret(listener: (position: EditorPosition) => void): () => void;
|
|
296
374
|
onHover(listener: (hover: EditorHover | null) => void): () => void;
|
|
297
375
|
rectAt(position: EditorPosition): EditorRect | null;
|
|
298
376
|
getVisibleRange(): EditorRange;
|
|
299
377
|
onViewChange(listener: () => void): () => void;
|
|
300
378
|
setWidgets(widgets: readonly EditorWidget[], owner?: string): void;
|
|
379
|
+
setReplacements?(replacements: readonly EditorReplacement[], owner?: string): void;
|
|
301
380
|
setLineActions(actions: readonly EditorLineAction[], owner?: string): void;
|
|
302
381
|
setCodeVision(rows: readonly EditorCodeVision[]): void;
|
|
303
382
|
onClick(handler: EditorClickHandler): () => void;
|
|
@@ -305,10 +384,11 @@ export interface Editor {
|
|
|
305
384
|
onKeyDown(handler: EditorKeyHandler): () => void;
|
|
306
385
|
setSelectionRanges(provider: EditorSelectionRanges | null): void;
|
|
307
386
|
trackRange(range: EditorRange): EditorTrackedRange;
|
|
308
|
-
applyEdits(edits: readonly EditorContentChange[]): boolean;
|
|
387
|
+
applyEdits(edits: readonly EditorContentChange[], options?: EditorApplyEditsOptions): boolean;
|
|
309
388
|
setTheme(theme: EditorTheme): void;
|
|
310
389
|
refreshFont(): void;
|
|
311
390
|
setReadOnly(readOnly: boolean, reason?: string): void;
|
|
391
|
+
isReadOnly?(): boolean;
|
|
312
392
|
runCommand(command: EditorRunCommand): boolean;
|
|
313
393
|
focus(): void;
|
|
314
394
|
dispose(): void;
|
|
@@ -328,7 +408,9 @@ export interface LineToken {
|
|
|
328
408
|
readonly length: number;
|
|
329
409
|
readonly color: string;
|
|
330
410
|
readonly fontStyle: number;
|
|
411
|
+
readonly kind?: LineTokenKind;
|
|
331
412
|
}
|
|
413
|
+
export type LineTokenKind = 'comment' | 'string' | 'regex';
|
|
332
414
|
export interface TokenizedLine {
|
|
333
415
|
readonly tokens: readonly LineToken[];
|
|
334
416
|
readonly state: unknown;
|
|
@@ -337,9 +419,11 @@ export interface LineTokenizer {
|
|
|
337
419
|
tokenizeLine(text: string, state: unknown): TokenizedLine;
|
|
338
420
|
sameState(a: unknown, b: unknown): boolean;
|
|
339
421
|
stale?(): boolean;
|
|
422
|
+
prepare?(text: string): Promise<boolean>;
|
|
340
423
|
}
|
|
341
424
|
export type TokenizerSource = (language: string | undefined, theme: EditorTheme, text?: string) => Promise<LineTokenizer | null>;
|
|
342
425
|
export interface SmartEditorEngineOptions {
|
|
426
|
+
readonly searchWorker?: EditorSearchClientOptions['workerFactory'];
|
|
343
427
|
readonly keymap?: Keymap;
|
|
344
428
|
readonly tokenizer: TokenizerSource;
|
|
345
429
|
readonly scopeColors?: ScopeColorSource;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { LayoutMetrics, LineGeometry } from './layout.ts';
|
|
2
|
+
export declare function uniformGeometry(line: {
|
|
3
|
+
start: number;
|
|
4
|
+
end: number;
|
|
5
|
+
text: string;
|
|
6
|
+
next?: number;
|
|
7
|
+
}, metrics: LayoutMetrics, breaks: number[], triggers: number[], indent: number): LineGeometry | null;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export function uniformGeometry(line, metrics, breaks, triggers, indent) {
|
|
2
|
+
const rowStarts = [0, ...breaks];
|
|
3
|
+
const firstLength = rowStarts[1] ?? line.text.length;
|
|
4
|
+
let continuationLength = 0;
|
|
5
|
+
for (let row = 1; row < rowStarts.length; row++) {
|
|
6
|
+
continuationLength = Math.max(continuationLength, (rowStarts[row + 1] ?? line.text.length) - rowStarts[row]);
|
|
7
|
+
}
|
|
8
|
+
// A shared prefix preserves repeated floating-point addition exactly, even for fallback font metrics.
|
|
9
|
+
if (Math.max(firstLength, continuationLength) > 4096) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
const positions = (start, length) => {
|
|
13
|
+
const result = [start];
|
|
14
|
+
for (let index = 0; index < length; index++) {
|
|
15
|
+
result.push(result.at(-1) + metrics.charWidth);
|
|
16
|
+
}
|
|
17
|
+
return result;
|
|
18
|
+
};
|
|
19
|
+
const uniform = { first: positions(0, firstLength), continuation: positions(indent, continuationLength) };
|
|
20
|
+
const geometry = {
|
|
21
|
+
start: line.start,
|
|
22
|
+
end: line.end,
|
|
23
|
+
next: line.next ?? line.end,
|
|
24
|
+
text: line.text,
|
|
25
|
+
offsets: [],
|
|
26
|
+
before: [],
|
|
27
|
+
after: [],
|
|
28
|
+
rowOf: [],
|
|
29
|
+
rowStarts,
|
|
30
|
+
rowEnds: [],
|
|
31
|
+
rowTriggers: triggers,
|
|
32
|
+
runs: [],
|
|
33
|
+
inlays: [],
|
|
34
|
+
subRows: rowStarts.length,
|
|
35
|
+
width: 0,
|
|
36
|
+
uniform
|
|
37
|
+
};
|
|
38
|
+
for (let row = 0; row < rowStarts.length; row++) {
|
|
39
|
+
const from = rowStarts[row];
|
|
40
|
+
const to = rowStarts[row + 1] ?? line.text.length;
|
|
41
|
+
const end = uniform[row === 0 ? 'first' : 'continuation'][to - from];
|
|
42
|
+
geometry.rowEnds.push(end);
|
|
43
|
+
geometry.width = Math.max(geometry.width, end);
|
|
44
|
+
if (from < to) {
|
|
45
|
+
geometry.runs.push({ from, to, x: row === 0 ? 0 : indent, subRow: row, text: line.text.slice(from, to) });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return geometry;
|
|
49
|
+
}
|
package/dist/view.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { type DocumentModel, type FoldHints, type FoldRole, type FoldingRange, type Selection as EditorSelection } from '@adecore/editor-core';
|
|
2
|
+
import { type EditorSearchClientOptions } from './search-client.ts';
|
|
2
3
|
import { FindController } from './find.ts';
|
|
3
|
-
import { type BlockWidget, EditorLayout, type Inlay } from './layout.ts';
|
|
4
|
+
import { type BlockReplacement, type BlockWidget, EditorLayout, type Inlay } from './layout.ts';
|
|
4
5
|
import { type ScrollKind } from './scroll.ts';
|
|
5
6
|
import { TokenCache } from './tokens.ts';
|
|
6
|
-
import type { EditorBlock, EditorChangeMark, EditorCodeBlockOptions, EditorFindQuery, EditorFindState, EditorHighlightKind, EditorMarkerSeverity, EditorMessages, EditorRect, EditorSmartKeys, LineTokenizer, ScopeColors } from './types.ts';
|
|
7
|
+
import type { EditorBlock, EditorChangeMark, EditorCodeBlockOptions, EditorFindQuery, EditorFindState, EditorHighlightKind, EditorInputPopup, EditorLineHighlight, EditorGutterIcon, EditorMarkerSeverity, EditorMessages, EditorRect, EditorSmartKeys, LineToken, LineTokenKind, LineTokenizer, ScopeColors } from './types.ts';
|
|
7
8
|
export interface ViewSettings {
|
|
9
|
+
searchWorker?: EditorSearchClientOptions['workerFactory'];
|
|
8
10
|
language: string | undefined;
|
|
9
11
|
tabSize: number;
|
|
10
12
|
insertSpaces: boolean;
|
|
@@ -18,6 +20,8 @@ export interface ViewSettings {
|
|
|
18
20
|
whitespace: boolean;
|
|
19
21
|
rightMargin: number | null;
|
|
20
22
|
foldOutline: 'off' | 'hover' | 'always';
|
|
23
|
+
folding?: boolean;
|
|
24
|
+
stickyScroll?: boolean;
|
|
21
25
|
}
|
|
22
26
|
export type ViewFold = Omit<FoldingRange, 'kind'> & {
|
|
23
27
|
kind: FoldingRange['kind'] | 'custom';
|
|
@@ -31,6 +35,14 @@ export interface ViewSemanticToken {
|
|
|
31
35
|
from: number;
|
|
32
36
|
to: number;
|
|
33
37
|
scopes: readonly string[];
|
|
38
|
+
within?: LineTokenKind;
|
|
39
|
+
}
|
|
40
|
+
export interface GutterMarker {
|
|
41
|
+
id: string;
|
|
42
|
+
line: number;
|
|
43
|
+
label: string;
|
|
44
|
+
icon?: EditorGutterIcon;
|
|
45
|
+
pressed?: boolean;
|
|
34
46
|
}
|
|
35
47
|
export interface ViewMarker {
|
|
36
48
|
severity: EditorMarkerSeverity;
|
|
@@ -58,6 +70,7 @@ export declare class EditorView {
|
|
|
58
70
|
private readonly preview;
|
|
59
71
|
private readonly signs;
|
|
60
72
|
private readonly notice;
|
|
73
|
+
private readonly live;
|
|
61
74
|
private readonly sticky;
|
|
62
75
|
private readonly overview;
|
|
63
76
|
private readonly tickTip;
|
|
@@ -69,10 +82,17 @@ export declare class EditorView {
|
|
|
69
82
|
private readonly findListeners;
|
|
70
83
|
private readonly scopeListeners;
|
|
71
84
|
private readonly viewListeners;
|
|
85
|
+
private readonly lineHeightListeners;
|
|
86
|
+
private announcedLineHeights;
|
|
72
87
|
private readonly gutterActionListeners;
|
|
73
88
|
private gutterAction;
|
|
74
89
|
private readonly gutterMarkerListeners;
|
|
75
90
|
private readonly gutterMarkers;
|
|
91
|
+
private lineTokenProvider;
|
|
92
|
+
private lineNumberProvider;
|
|
93
|
+
private lineNumberLabels;
|
|
94
|
+
private lineNumberRevision;
|
|
95
|
+
private lineNumberWidth;
|
|
76
96
|
private semantic;
|
|
77
97
|
private scopeColors;
|
|
78
98
|
private semanticVersion;
|
|
@@ -86,8 +106,9 @@ export declare class EditorView {
|
|
|
86
106
|
private readonly outline;
|
|
87
107
|
private stickyEntries;
|
|
88
108
|
private scopeKey;
|
|
89
|
-
private
|
|
109
|
+
private readonly changeLayers;
|
|
90
110
|
private changeVersion;
|
|
111
|
+
private changeCache;
|
|
91
112
|
private readonly attribution;
|
|
92
113
|
private readonly highlights;
|
|
93
114
|
private remoteCarets;
|
|
@@ -111,8 +132,13 @@ export declare class EditorView {
|
|
|
111
132
|
private frameGeometry;
|
|
112
133
|
private disposed;
|
|
113
134
|
private inlays;
|
|
135
|
+
private readonly inlayHoverListeners;
|
|
136
|
+
private inlayHover;
|
|
137
|
+
private inlayLink;
|
|
138
|
+
private inlayLinkElement;
|
|
114
139
|
private readonly blocks;
|
|
115
140
|
private lenses;
|
|
141
|
+
private readonly replacements;
|
|
116
142
|
private occurrences;
|
|
117
143
|
private replacePreview;
|
|
118
144
|
private dropCaret;
|
|
@@ -133,6 +159,8 @@ export declare class EditorView {
|
|
|
133
159
|
private foldTimer;
|
|
134
160
|
private colorTimer;
|
|
135
161
|
private noticeTimer;
|
|
162
|
+
private liveTimer;
|
|
163
|
+
private lineLabelProvider;
|
|
136
164
|
private bracketCache;
|
|
137
165
|
private wrapWidth;
|
|
138
166
|
private rowEndCaret;
|
|
@@ -141,10 +169,17 @@ export declare class EditorView {
|
|
|
141
169
|
readonly settings: ViewSettings;
|
|
142
170
|
constructor(container: HTMLElement, model: DocumentModel, settings: ViewSettings);
|
|
143
171
|
applySettings(): void;
|
|
172
|
+
repaint(): void;
|
|
144
173
|
refreshFont(): void;
|
|
145
174
|
setTokenizer(tokenizer: LineTokenizer | null): void;
|
|
175
|
+
grammarChanged(): void;
|
|
176
|
+
setLineTokens(tokens: ((line: number) => readonly LineToken[] | null | undefined) | null): void;
|
|
177
|
+
setLineNumbers(labels: ((line: number) => string | null) | null): void;
|
|
178
|
+
private lineNumberLabel;
|
|
146
179
|
setInlays(inlays: readonly Inlay[]): void;
|
|
147
180
|
setBlockWidgets(owner: string, blocks: readonly BlockWidget[]): void;
|
|
181
|
+
setReplacements(owner: string, replacements: readonly BlockReplacement[]): void;
|
|
182
|
+
private allReplacements;
|
|
148
183
|
setLenses(lenses: readonly BlockWidget[]): void;
|
|
149
184
|
private allBlocks;
|
|
150
185
|
setOccurrences(occurrences: readonly Occurrence[]): void;
|
|
@@ -159,10 +194,15 @@ export declare class EditorView {
|
|
|
159
194
|
setMarkers(markers: readonly ViewMarker[]): void;
|
|
160
195
|
setComposition(text: string | undefined): void;
|
|
161
196
|
notify(message: string): void;
|
|
197
|
+
private foldName;
|
|
198
|
+
announce(message: string): void;
|
|
199
|
+
setInputPopup(popup: EditorInputPopup | null): void;
|
|
200
|
+
setLineLabels(labels: ((line: number) => string | null) | null): void;
|
|
162
201
|
get gutterElement(): HTMLElement;
|
|
163
202
|
get stickyElement(): HTMLElement;
|
|
164
203
|
focus(): void;
|
|
165
204
|
get focused(): boolean;
|
|
205
|
+
get contentHeight(): number;
|
|
166
206
|
get viewportHeight(): number;
|
|
167
207
|
private get scrollTop();
|
|
168
208
|
private get scrollLeft();
|
|
@@ -272,6 +312,9 @@ export declare class EditorView {
|
|
|
272
312
|
markRowEnd(offset: number): void;
|
|
273
313
|
onHover(listener: (offset: number | null) => void): () => void;
|
|
274
314
|
private selectionOccurrences;
|
|
315
|
+
private get paintWindow();
|
|
316
|
+
private paintRectangles;
|
|
317
|
+
private visibleTextBounds;
|
|
275
318
|
private wrapSigns;
|
|
276
319
|
private indentOf;
|
|
277
320
|
private effectiveIndent;
|
|
@@ -283,7 +326,26 @@ export declare class EditorView {
|
|
|
283
326
|
setColumnMode(on: boolean): void;
|
|
284
327
|
setDropCaret(offset: number | null): void;
|
|
285
328
|
hoverMoved(event: PointerEvent): void;
|
|
329
|
+
inlayAt(target: EventTarget | null): {
|
|
330
|
+
id: string;
|
|
331
|
+
part: number | null;
|
|
332
|
+
element: HTMLElement;
|
|
333
|
+
} | null;
|
|
334
|
+
setInlayHover(target: EventTarget | null): void;
|
|
335
|
+
onInlayHover(listener: (target: {
|
|
336
|
+
id: string;
|
|
337
|
+
part: number | null;
|
|
338
|
+
rect: EditorRect;
|
|
339
|
+
} | null) => void): () => void;
|
|
340
|
+
setInlayLink(target: {
|
|
341
|
+
id: string;
|
|
342
|
+
part: number | null;
|
|
343
|
+
} | null): void;
|
|
344
|
+
private applyInlayLink;
|
|
286
345
|
setHover(offset: number | null): void;
|
|
346
|
+
getLineHeight(line: number): number;
|
|
347
|
+
onLineHeights(listener: () => void): () => void;
|
|
348
|
+
setScrollTop(top: number): void;
|
|
287
349
|
onViewChange(listener: () => void): () => void;
|
|
288
350
|
private announceView;
|
|
289
351
|
private caretOf;
|
|
@@ -309,8 +371,8 @@ export declare class EditorView {
|
|
|
309
371
|
scrolled(): void;
|
|
310
372
|
render(): void;
|
|
311
373
|
private paintDecorations;
|
|
312
|
-
setChangeMarks(marks: readonly EditorChangeMark[]): void;
|
|
313
|
-
private
|
|
374
|
+
setChangeMarks(marks: readonly EditorChangeMark[], layer?: string): void;
|
|
375
|
+
private resolvedChanges;
|
|
314
376
|
private changedLines;
|
|
315
377
|
setRemoteCarets(carets: readonly {
|
|
316
378
|
id: string;
|
|
@@ -331,13 +393,7 @@ export declare class EditorView {
|
|
|
331
393
|
endLine: number;
|
|
332
394
|
color: string;
|
|
333
395
|
}[]): void;
|
|
334
|
-
setLineHighlights(highlights: readonly
|
|
335
|
-
startLine: number;
|
|
336
|
-
endLine: number;
|
|
337
|
-
color: string;
|
|
338
|
-
sign?: string;
|
|
339
|
-
fill?: string;
|
|
340
|
-
}[]): void;
|
|
396
|
+
setLineHighlights(highlights: readonly EditorLineHighlight[]): void;
|
|
341
397
|
private highlightedLines;
|
|
342
398
|
private highlightMarks;
|
|
343
399
|
renderCode(container: HTMLElement, text: string, options: EditorCodeBlockOptions): void;
|
|
@@ -369,11 +425,7 @@ export declare class EditorView {
|
|
|
369
425
|
label: string;
|
|
370
426
|
} | null): void;
|
|
371
427
|
onGutterAction(listener: (line: number) => void): () => void;
|
|
372
|
-
setGutterMarkers(owner: string, markers: readonly
|
|
373
|
-
id: string;
|
|
374
|
-
line: number;
|
|
375
|
-
label: string;
|
|
376
|
-
}[]): void;
|
|
428
|
+
setGutterMarkers(owner: string, markers: readonly GutterMarker[]): void;
|
|
377
429
|
onGutterMarker(listener: (id: string) => void): () => void;
|
|
378
430
|
gutterMarkerIdOf(target: EventTarget | null): string | null;
|
|
379
431
|
pressGutterMarker(id: string): void;
|