@adecore/editor 0.22.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +184 -41
- package/dist/fake.d.ts +43 -5
- package/dist/fake.js +117 -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 +84 -2
- package/dist/uniform-geometry.d.ts +7 -0
- package/dist/uniform-geometry.js +49 -0
- package/dist/view.d.ts +68 -17
- package/dist/view.js +424 -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 +216 -42
- package/src/fake.ts +152 -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 +174 -8
- package/src/uniform-geometry.ts +57 -0
- package/src/view.ts +500 -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;
|
|
@@ -27,6 +29,7 @@ export interface EditorOptions {
|
|
|
27
29
|
readonly whitespace?: boolean;
|
|
28
30
|
readonly rightMargin?: number | null;
|
|
29
31
|
readonly foldOutline?: EditorFoldOutline;
|
|
32
|
+
readonly folding?: boolean;
|
|
30
33
|
readonly messages?: Partial<EditorMessages>;
|
|
31
34
|
readonly label?: string;
|
|
32
35
|
readonly folds?: EditorFolds;
|
|
@@ -37,6 +40,12 @@ export interface EditorOptions {
|
|
|
37
40
|
}
|
|
38
41
|
export interface EditorMessages {
|
|
39
42
|
readonly noMoreOccurrences: string;
|
|
43
|
+
readonly fold: string;
|
|
44
|
+
readonly unfold: string;
|
|
45
|
+
}
|
|
46
|
+
export interface EditorInputPopup {
|
|
47
|
+
readonly controls: string;
|
|
48
|
+
readonly activeDescendant?: string;
|
|
40
49
|
}
|
|
41
50
|
export interface EditorSmartKeys {
|
|
42
51
|
readonly autoPairBrackets: boolean;
|
|
@@ -93,8 +102,11 @@ export interface EditorLineHighlight {
|
|
|
93
102
|
readonly color: EditorMarkColor;
|
|
94
103
|
readonly fill?: EditorMarkColor;
|
|
95
104
|
readonly sign?: string;
|
|
105
|
+
readonly bar?: 'solid' | 'hatched';
|
|
106
|
+
readonly emphasis?: ReadonlyArray<ReadonlyArray<readonly [number, number]>>;
|
|
96
107
|
}
|
|
97
108
|
export interface EditorCodeBlockOptions {
|
|
109
|
+
readonly tokens?: ReadonlyArray<readonly LineToken[]> | null;
|
|
98
110
|
readonly firstLine?: number;
|
|
99
111
|
readonly sign?: string;
|
|
100
112
|
readonly color?: EditorMarkColor;
|
|
@@ -117,9 +129,14 @@ export interface EditorContentChange {
|
|
|
117
129
|
readonly range: EditorRange;
|
|
118
130
|
readonly text: string;
|
|
119
131
|
}
|
|
132
|
+
export interface EditorApplyEditsOptions {
|
|
133
|
+
readonly mapSelections?: (range: EditorRange) => EditorRange;
|
|
134
|
+
readonly mergeUndo?: boolean;
|
|
135
|
+
}
|
|
120
136
|
export interface EditorTextChange {
|
|
121
137
|
readonly changes: readonly EditorContentChange[];
|
|
122
138
|
readonly source: 'input' | 'command' | 'external';
|
|
139
|
+
readonly typed?: boolean;
|
|
123
140
|
}
|
|
124
141
|
export type EditorMarkerSeverity = 'error' | 'warning' | 'info' | 'hint';
|
|
125
142
|
export interface EditorMarker {
|
|
@@ -162,6 +179,17 @@ export interface EditorWidget {
|
|
|
162
179
|
readonly line: number;
|
|
163
180
|
readonly placement?: 'above' | 'below';
|
|
164
181
|
readonly height?: number;
|
|
182
|
+
readonly fixed?: boolean;
|
|
183
|
+
render(container: HTMLElement): void;
|
|
184
|
+
}
|
|
185
|
+
export interface EditorReplacement {
|
|
186
|
+
readonly id: string;
|
|
187
|
+
readonly startLine: number;
|
|
188
|
+
readonly endLine: number;
|
|
189
|
+
readonly height?: number;
|
|
190
|
+
readonly label?: string;
|
|
191
|
+
readonly enterable?: boolean;
|
|
192
|
+
onReveal?(): void;
|
|
165
193
|
render(container: HTMLElement): void;
|
|
166
194
|
}
|
|
167
195
|
export interface EditorLineAction {
|
|
@@ -187,6 +215,7 @@ export interface EditorSemanticToken {
|
|
|
187
215
|
readonly character: number;
|
|
188
216
|
readonly length: number;
|
|
189
217
|
readonly scopes: readonly string[];
|
|
218
|
+
readonly within?: LineTokenKind;
|
|
190
219
|
}
|
|
191
220
|
export interface ScopeStyle {
|
|
192
221
|
readonly color: string;
|
|
@@ -197,7 +226,26 @@ export type ScopeColorSource = (theme: EditorTheme) => Promise<ScopeColors | nul
|
|
|
197
226
|
export interface EditorInlayHint {
|
|
198
227
|
readonly position: EditorPosition;
|
|
199
228
|
readonly label: string;
|
|
229
|
+
readonly id?: string;
|
|
230
|
+
readonly parts?: readonly string[];
|
|
231
|
+
readonly paddingLeft?: boolean;
|
|
232
|
+
readonly paddingRight?: boolean;
|
|
233
|
+
}
|
|
234
|
+
export interface EditorInlayTarget {
|
|
235
|
+
readonly id: string;
|
|
236
|
+
readonly part: number | null;
|
|
237
|
+
readonly rect: EditorRect;
|
|
238
|
+
}
|
|
239
|
+
export interface EditorInlayClick {
|
|
240
|
+
readonly id: string;
|
|
241
|
+
readonly part: number | null;
|
|
242
|
+
readonly mod: boolean;
|
|
243
|
+
readonly alt: boolean;
|
|
244
|
+
readonly shift: boolean;
|
|
245
|
+
readonly clicks: 1 | 2;
|
|
246
|
+
readonly touch: boolean;
|
|
200
247
|
}
|
|
248
|
+
export type EditorInlayClickHandler = (click: EditorInlayClick) => boolean;
|
|
201
249
|
export interface EditorGhostText {
|
|
202
250
|
readonly position: EditorPosition;
|
|
203
251
|
readonly text: string;
|
|
@@ -207,10 +255,13 @@ export interface EditorGutterAction {
|
|
|
207
255
|
readonly line: number;
|
|
208
256
|
readonly label: string;
|
|
209
257
|
}
|
|
258
|
+
export type EditorGutterIcon = 'sparkles' | 'book-open';
|
|
210
259
|
export interface EditorGutterMarker {
|
|
211
260
|
readonly id: string;
|
|
212
261
|
readonly line: number;
|
|
213
262
|
readonly label: string;
|
|
263
|
+
readonly icon?: EditorGutterIcon;
|
|
264
|
+
readonly pressed?: boolean;
|
|
214
265
|
}
|
|
215
266
|
export type EditorReveal = 'relative' | 'center' | 'centerDown' | 'centerUp';
|
|
216
267
|
export interface EditorIndentation {
|
|
@@ -228,6 +279,13 @@ export interface EditorFindState {
|
|
|
228
279
|
readonly count: number;
|
|
229
280
|
readonly current: number | null;
|
|
230
281
|
readonly noSelection?: boolean;
|
|
282
|
+
readonly limited?: boolean;
|
|
283
|
+
readonly searching?: boolean;
|
|
284
|
+
readonly failed?: 'invalid' | 'timeout' | 'unavailable' | 'error';
|
|
285
|
+
readonly captureFailed?: 'timeout' | 'unavailable' | 'error';
|
|
286
|
+
readonly replaceFailed?: 'limit' | 'timeout' | 'unavailable' | 'error';
|
|
287
|
+
readonly replaced?: number;
|
|
288
|
+
readonly large?: boolean;
|
|
231
289
|
}
|
|
232
290
|
export interface EditorReplaceOptions {
|
|
233
291
|
readonly preserveCase?: boolean;
|
|
@@ -251,6 +309,7 @@ export interface Editor {
|
|
|
251
309
|
findStep(direction: 1 | -1): void;
|
|
252
310
|
replace(replacement: string, options?: EditorReplaceOptions): boolean;
|
|
253
311
|
replaceAll(replacement: string, options?: EditorReplaceOptions): number;
|
|
312
|
+
replaceAllAsync(replacement: string, options?: EditorReplaceOptions): Promise<number>;
|
|
254
313
|
setReplacePreview(replacement: string | null, options?: EditorReplaceOptions): void;
|
|
255
314
|
selectFindMatches(): number;
|
|
256
315
|
findFromCursor(query: EditorFindQuery, direction: 1 | -1): boolean;
|
|
@@ -265,12 +324,15 @@ export interface Editor {
|
|
|
265
324
|
setFoldOutline(outline: EditorFoldOutline): void;
|
|
266
325
|
setLabel(label: string): void;
|
|
267
326
|
setFoldHints(hints: EditorFoldHints | null): void;
|
|
268
|
-
setChangeMarks(marks: readonly EditorChangeMark[]): void;
|
|
327
|
+
setChangeMarks(marks: readonly EditorChangeMark[], layer?: string): void;
|
|
269
328
|
setBlocks(blocks: readonly EditorBlock[] | null): void;
|
|
270
329
|
onScope(listener: (scope: readonly EditorBlock[]) => void): () => void;
|
|
271
330
|
setAttributionMarks(marks: readonly EditorAttributionMark[]): void;
|
|
272
331
|
setRemoteCursors(cursors: readonly EditorRemoteCursor[]): void;
|
|
273
332
|
setLineHighlights(highlights: readonly EditorLineHighlight[]): void;
|
|
333
|
+
setLineNumbers(labels: ((line: number) => string | null) | null): void;
|
|
334
|
+
setLineLabels(labels: ((line: number) => string | null) | null): void;
|
|
335
|
+
setLineTokens(tokens: ((line: number) => readonly LineToken[] | null | undefined) | null): void;
|
|
274
336
|
renderCode(container: HTMLElement, text: string, options?: EditorCodeBlockOptions): void;
|
|
275
337
|
onAttributionHover(listener: (hover: EditorAttributionHover | null) => void): () => void;
|
|
276
338
|
setMarkers(markers: readonly EditorMarker[]): void;
|
|
@@ -278,6 +340,12 @@ export interface Editor {
|
|
|
278
340
|
setLink(range: EditorRange | null): void;
|
|
279
341
|
setSemanticTokens(tokens: readonly EditorSemanticToken[] | null): void;
|
|
280
342
|
setInlayHints(hints: readonly EditorInlayHint[]): void;
|
|
343
|
+
onInlayHover?(listener: (target: EditorInlayTarget | null) => void): () => void;
|
|
344
|
+
onInlayClick?(handler: EditorInlayClickHandler): () => void;
|
|
345
|
+
setInlayLink?(target: {
|
|
346
|
+
readonly id: string;
|
|
347
|
+
readonly part: number | null;
|
|
348
|
+
} | null): void;
|
|
281
349
|
setGhostText(ghost: EditorGhostText | null): void;
|
|
282
350
|
setGutterAction(action: EditorGutterAction | null): void;
|
|
283
351
|
onGutterAction(listener: (line: number) => void): () => void;
|
|
@@ -285,6 +353,11 @@ export interface Editor {
|
|
|
285
353
|
onGutterMarker(listener: (id: string) => void): () => void;
|
|
286
354
|
getCaret(): EditorPosition;
|
|
287
355
|
getScrollTop(): number;
|
|
356
|
+
setScrollTop(top: number): void;
|
|
357
|
+
getLineHeight(line: number): number;
|
|
358
|
+
getBaseLineHeight?(): number;
|
|
359
|
+
onLineHeights(listener: () => void): () => void;
|
|
360
|
+
getContentHeight(): number;
|
|
288
361
|
getFolds(): EditorFolds;
|
|
289
362
|
getSelection(): EditorRange;
|
|
290
363
|
getSelections(): EditorRange[];
|
|
@@ -292,12 +365,16 @@ export interface Editor {
|
|
|
292
365
|
setCaret(position: EditorPosition, reveal?: EditorReveal): void;
|
|
293
366
|
setSelection(range: EditorRange, reveal?: EditorReveal): void;
|
|
294
367
|
setSelections(ranges: readonly EditorRange[], reveal?: EditorReveal): void;
|
|
368
|
+
setInputPopup(popup: EditorInputPopup | null): void;
|
|
369
|
+
announce(message: string): void;
|
|
370
|
+
setMessages(messages: Partial<EditorMessages>): void;
|
|
295
371
|
onCaret(listener: (position: EditorPosition) => void): () => void;
|
|
296
372
|
onHover(listener: (hover: EditorHover | null) => void): () => void;
|
|
297
373
|
rectAt(position: EditorPosition): EditorRect | null;
|
|
298
374
|
getVisibleRange(): EditorRange;
|
|
299
375
|
onViewChange(listener: () => void): () => void;
|
|
300
376
|
setWidgets(widgets: readonly EditorWidget[], owner?: string): void;
|
|
377
|
+
setReplacements?(replacements: readonly EditorReplacement[], owner?: string): void;
|
|
301
378
|
setLineActions(actions: readonly EditorLineAction[], owner?: string): void;
|
|
302
379
|
setCodeVision(rows: readonly EditorCodeVision[]): void;
|
|
303
380
|
onClick(handler: EditorClickHandler): () => void;
|
|
@@ -305,10 +382,11 @@ export interface Editor {
|
|
|
305
382
|
onKeyDown(handler: EditorKeyHandler): () => void;
|
|
306
383
|
setSelectionRanges(provider: EditorSelectionRanges | null): void;
|
|
307
384
|
trackRange(range: EditorRange): EditorTrackedRange;
|
|
308
|
-
applyEdits(edits: readonly EditorContentChange[]): boolean;
|
|
385
|
+
applyEdits(edits: readonly EditorContentChange[], options?: EditorApplyEditsOptions): boolean;
|
|
309
386
|
setTheme(theme: EditorTheme): void;
|
|
310
387
|
refreshFont(): void;
|
|
311
388
|
setReadOnly(readOnly: boolean, reason?: string): void;
|
|
389
|
+
isReadOnly?(): boolean;
|
|
312
390
|
runCommand(command: EditorRunCommand): boolean;
|
|
313
391
|
focus(): void;
|
|
314
392
|
dispose(): void;
|
|
@@ -328,7 +406,9 @@ export interface LineToken {
|
|
|
328
406
|
readonly length: number;
|
|
329
407
|
readonly color: string;
|
|
330
408
|
readonly fontStyle: number;
|
|
409
|
+
readonly kind?: LineTokenKind;
|
|
331
410
|
}
|
|
411
|
+
export type LineTokenKind = 'comment' | 'string' | 'regex';
|
|
332
412
|
export interface TokenizedLine {
|
|
333
413
|
readonly tokens: readonly LineToken[];
|
|
334
414
|
readonly state: unknown;
|
|
@@ -337,9 +417,11 @@ export interface LineTokenizer {
|
|
|
337
417
|
tokenizeLine(text: string, state: unknown): TokenizedLine;
|
|
338
418
|
sameState(a: unknown, b: unknown): boolean;
|
|
339
419
|
stale?(): boolean;
|
|
420
|
+
prepare?(text: string): Promise<boolean>;
|
|
340
421
|
}
|
|
341
422
|
export type TokenizerSource = (language: string | undefined, theme: EditorTheme, text?: string) => Promise<LineTokenizer | null>;
|
|
342
423
|
export interface SmartEditorEngineOptions {
|
|
424
|
+
readonly searchWorker?: EditorSearchClientOptions['workerFactory'];
|
|
343
425
|
readonly keymap?: Keymap;
|
|
344
426
|
readonly tokenizer: TokenizerSource;
|
|
345
427
|
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,7 @@ export interface ViewSettings {
|
|
|
18
20
|
whitespace: boolean;
|
|
19
21
|
rightMargin: number | null;
|
|
20
22
|
foldOutline: 'off' | 'hover' | 'always';
|
|
23
|
+
folding?: boolean;
|
|
21
24
|
}
|
|
22
25
|
export type ViewFold = Omit<FoldingRange, 'kind'> & {
|
|
23
26
|
kind: FoldingRange['kind'] | 'custom';
|
|
@@ -31,6 +34,14 @@ export interface ViewSemanticToken {
|
|
|
31
34
|
from: number;
|
|
32
35
|
to: number;
|
|
33
36
|
scopes: readonly string[];
|
|
37
|
+
within?: LineTokenKind;
|
|
38
|
+
}
|
|
39
|
+
export interface GutterMarker {
|
|
40
|
+
id: string;
|
|
41
|
+
line: number;
|
|
42
|
+
label: string;
|
|
43
|
+
icon?: EditorGutterIcon;
|
|
44
|
+
pressed?: boolean;
|
|
34
45
|
}
|
|
35
46
|
export interface ViewMarker {
|
|
36
47
|
severity: EditorMarkerSeverity;
|
|
@@ -58,6 +69,7 @@ export declare class EditorView {
|
|
|
58
69
|
private readonly preview;
|
|
59
70
|
private readonly signs;
|
|
60
71
|
private readonly notice;
|
|
72
|
+
private readonly live;
|
|
61
73
|
private readonly sticky;
|
|
62
74
|
private readonly overview;
|
|
63
75
|
private readonly tickTip;
|
|
@@ -69,10 +81,17 @@ export declare class EditorView {
|
|
|
69
81
|
private readonly findListeners;
|
|
70
82
|
private readonly scopeListeners;
|
|
71
83
|
private readonly viewListeners;
|
|
84
|
+
private readonly lineHeightListeners;
|
|
85
|
+
private announcedLineHeights;
|
|
72
86
|
private readonly gutterActionListeners;
|
|
73
87
|
private gutterAction;
|
|
74
88
|
private readonly gutterMarkerListeners;
|
|
75
89
|
private readonly gutterMarkers;
|
|
90
|
+
private lineTokenProvider;
|
|
91
|
+
private lineNumberProvider;
|
|
92
|
+
private lineNumberLabels;
|
|
93
|
+
private lineNumberRevision;
|
|
94
|
+
private lineNumberWidth;
|
|
76
95
|
private semantic;
|
|
77
96
|
private scopeColors;
|
|
78
97
|
private semanticVersion;
|
|
@@ -86,8 +105,9 @@ export declare class EditorView {
|
|
|
86
105
|
private readonly outline;
|
|
87
106
|
private stickyEntries;
|
|
88
107
|
private scopeKey;
|
|
89
|
-
private
|
|
108
|
+
private readonly changeLayers;
|
|
90
109
|
private changeVersion;
|
|
110
|
+
private changeCache;
|
|
91
111
|
private readonly attribution;
|
|
92
112
|
private readonly highlights;
|
|
93
113
|
private remoteCarets;
|
|
@@ -111,8 +131,13 @@ export declare class EditorView {
|
|
|
111
131
|
private frameGeometry;
|
|
112
132
|
private disposed;
|
|
113
133
|
private inlays;
|
|
134
|
+
private readonly inlayHoverListeners;
|
|
135
|
+
private inlayHover;
|
|
136
|
+
private inlayLink;
|
|
137
|
+
private inlayLinkElement;
|
|
114
138
|
private readonly blocks;
|
|
115
139
|
private lenses;
|
|
140
|
+
private readonly replacements;
|
|
116
141
|
private occurrences;
|
|
117
142
|
private replacePreview;
|
|
118
143
|
private dropCaret;
|
|
@@ -133,6 +158,8 @@ export declare class EditorView {
|
|
|
133
158
|
private foldTimer;
|
|
134
159
|
private colorTimer;
|
|
135
160
|
private noticeTimer;
|
|
161
|
+
private liveTimer;
|
|
162
|
+
private lineLabelProvider;
|
|
136
163
|
private bracketCache;
|
|
137
164
|
private wrapWidth;
|
|
138
165
|
private rowEndCaret;
|
|
@@ -141,10 +168,17 @@ export declare class EditorView {
|
|
|
141
168
|
readonly settings: ViewSettings;
|
|
142
169
|
constructor(container: HTMLElement, model: DocumentModel, settings: ViewSettings);
|
|
143
170
|
applySettings(): void;
|
|
171
|
+
repaint(): void;
|
|
144
172
|
refreshFont(): void;
|
|
145
173
|
setTokenizer(tokenizer: LineTokenizer | null): void;
|
|
174
|
+
grammarChanged(): void;
|
|
175
|
+
setLineTokens(tokens: ((line: number) => readonly LineToken[] | null | undefined) | null): void;
|
|
176
|
+
setLineNumbers(labels: ((line: number) => string | null) | null): void;
|
|
177
|
+
private lineNumberLabel;
|
|
146
178
|
setInlays(inlays: readonly Inlay[]): void;
|
|
147
179
|
setBlockWidgets(owner: string, blocks: readonly BlockWidget[]): void;
|
|
180
|
+
setReplacements(owner: string, replacements: readonly BlockReplacement[]): void;
|
|
181
|
+
private allReplacements;
|
|
148
182
|
setLenses(lenses: readonly BlockWidget[]): void;
|
|
149
183
|
private allBlocks;
|
|
150
184
|
setOccurrences(occurrences: readonly Occurrence[]): void;
|
|
@@ -159,10 +193,15 @@ export declare class EditorView {
|
|
|
159
193
|
setMarkers(markers: readonly ViewMarker[]): void;
|
|
160
194
|
setComposition(text: string | undefined): void;
|
|
161
195
|
notify(message: string): void;
|
|
196
|
+
private foldName;
|
|
197
|
+
announce(message: string): void;
|
|
198
|
+
setInputPopup(popup: EditorInputPopup | null): void;
|
|
199
|
+
setLineLabels(labels: ((line: number) => string | null) | null): void;
|
|
162
200
|
get gutterElement(): HTMLElement;
|
|
163
201
|
get stickyElement(): HTMLElement;
|
|
164
202
|
focus(): void;
|
|
165
203
|
get focused(): boolean;
|
|
204
|
+
get contentHeight(): number;
|
|
166
205
|
get viewportHeight(): number;
|
|
167
206
|
private get scrollTop();
|
|
168
207
|
private get scrollLeft();
|
|
@@ -272,6 +311,9 @@ export declare class EditorView {
|
|
|
272
311
|
markRowEnd(offset: number): void;
|
|
273
312
|
onHover(listener: (offset: number | null) => void): () => void;
|
|
274
313
|
private selectionOccurrences;
|
|
314
|
+
private get paintWindow();
|
|
315
|
+
private paintRectangles;
|
|
316
|
+
private visibleTextBounds;
|
|
275
317
|
private wrapSigns;
|
|
276
318
|
private indentOf;
|
|
277
319
|
private effectiveIndent;
|
|
@@ -283,7 +325,26 @@ export declare class EditorView {
|
|
|
283
325
|
setColumnMode(on: boolean): void;
|
|
284
326
|
setDropCaret(offset: number | null): void;
|
|
285
327
|
hoverMoved(event: PointerEvent): void;
|
|
328
|
+
inlayAt(target: EventTarget | null): {
|
|
329
|
+
id: string;
|
|
330
|
+
part: number | null;
|
|
331
|
+
element: HTMLElement;
|
|
332
|
+
} | null;
|
|
333
|
+
setInlayHover(target: EventTarget | null): void;
|
|
334
|
+
onInlayHover(listener: (target: {
|
|
335
|
+
id: string;
|
|
336
|
+
part: number | null;
|
|
337
|
+
rect: EditorRect;
|
|
338
|
+
} | null) => void): () => void;
|
|
339
|
+
setInlayLink(target: {
|
|
340
|
+
id: string;
|
|
341
|
+
part: number | null;
|
|
342
|
+
} | null): void;
|
|
343
|
+
private applyInlayLink;
|
|
286
344
|
setHover(offset: number | null): void;
|
|
345
|
+
getLineHeight(line: number): number;
|
|
346
|
+
onLineHeights(listener: () => void): () => void;
|
|
347
|
+
setScrollTop(top: number): void;
|
|
287
348
|
onViewChange(listener: () => void): () => void;
|
|
288
349
|
private announceView;
|
|
289
350
|
private caretOf;
|
|
@@ -309,8 +370,8 @@ export declare class EditorView {
|
|
|
309
370
|
scrolled(): void;
|
|
310
371
|
render(): void;
|
|
311
372
|
private paintDecorations;
|
|
312
|
-
setChangeMarks(marks: readonly EditorChangeMark[]): void;
|
|
313
|
-
private
|
|
373
|
+
setChangeMarks(marks: readonly EditorChangeMark[], layer?: string): void;
|
|
374
|
+
private resolvedChanges;
|
|
314
375
|
private changedLines;
|
|
315
376
|
setRemoteCarets(carets: readonly {
|
|
316
377
|
id: string;
|
|
@@ -331,13 +392,7 @@ export declare class EditorView {
|
|
|
331
392
|
endLine: number;
|
|
332
393
|
color: string;
|
|
333
394
|
}[]): void;
|
|
334
|
-
setLineHighlights(highlights: readonly
|
|
335
|
-
startLine: number;
|
|
336
|
-
endLine: number;
|
|
337
|
-
color: string;
|
|
338
|
-
sign?: string;
|
|
339
|
-
fill?: string;
|
|
340
|
-
}[]): void;
|
|
395
|
+
setLineHighlights(highlights: readonly EditorLineHighlight[]): void;
|
|
341
396
|
private highlightedLines;
|
|
342
397
|
private highlightMarks;
|
|
343
398
|
renderCode(container: HTMLElement, text: string, options: EditorCodeBlockOptions): void;
|
|
@@ -369,11 +424,7 @@ export declare class EditorView {
|
|
|
369
424
|
label: string;
|
|
370
425
|
} | null): void;
|
|
371
426
|
onGutterAction(listener: (line: number) => void): () => void;
|
|
372
|
-
setGutterMarkers(owner: string, markers: readonly
|
|
373
|
-
id: string;
|
|
374
|
-
line: number;
|
|
375
|
-
label: string;
|
|
376
|
-
}[]): void;
|
|
427
|
+
setGutterMarkers(owner: string, markers: readonly GutterMarker[]): void;
|
|
377
428
|
onGutterMarker(listener: (id: string) => void): () => void;
|
|
378
429
|
gutterMarkerIdOf(target: EventTarget | null): string | null;
|
|
379
430
|
pressGutterMarker(id: string): void;
|