@adecore/editor 0.22.1 → 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.
Files changed (94) hide show
  1. package/dist/attribution.d.ts +9 -8
  2. package/dist/attribution.js +44 -9
  3. package/dist/bidi.d.ts +44 -0
  4. package/dist/bidi.js +26 -0
  5. package/dist/column-selection.js +2 -1
  6. package/dist/controller.d.ts +6 -1
  7. package/dist/controller.js +93 -3
  8. package/dist/editor.css +81 -1
  9. package/dist/engine.js +184 -41
  10. package/dist/fake.d.ts +43 -5
  11. package/dist/fake.js +117 -13
  12. package/dist/find-search.d.ts +26 -0
  13. package/dist/find-search.js +130 -0
  14. package/dist/find.d.ts +50 -2
  15. package/dist/find.js +575 -25
  16. package/dist/geometry-stops.d.ts +6 -0
  17. package/dist/geometry-stops.js +47 -0
  18. package/dist/grammar-preparation.d.ts +29 -0
  19. package/dist/grammar-preparation.js +147 -0
  20. package/dist/index.d.ts +3 -1
  21. package/dist/index.js +2 -0
  22. package/dist/keymap-table.d.ts +10 -1
  23. package/dist/keymap-table.js +37 -1
  24. package/dist/keymap.d.ts +1 -0
  25. package/dist/keymap.js +4 -1
  26. package/dist/layout-changes.d.ts +6 -0
  27. package/dist/layout-changes.js +27 -0
  28. package/dist/layout.d.ts +45 -2
  29. package/dist/layout.js +202 -58
  30. package/dist/offsets.d.ts +1 -0
  31. package/dist/offsets.js +23 -0
  32. package/dist/outline.js +5 -4
  33. package/dist/paint.d.ts +11 -3
  34. package/dist/paint.js +180 -34
  35. package/dist/search-client.d.ts +27 -0
  36. package/dist/search-client.js +210 -0
  37. package/dist/search-protocol.d.ts +103 -0
  38. package/dist/search-protocol.js +3 -0
  39. package/dist/search-worker.d.ts +11 -0
  40. package/dist/search-worker.js +137 -0
  41. package/dist/semantic.d.ts +2 -1
  42. package/dist/semantic.js +6 -1
  43. package/dist/shiki-document.d.ts +8 -0
  44. package/dist/shiki-document.js +93 -0
  45. package/dist/shiki-worker.d.ts +65 -0
  46. package/dist/shiki-worker.js +265 -0
  47. package/dist/shiki.d.ts +1 -0
  48. package/dist/shiki.js +96 -33
  49. package/dist/testing.d.ts +1 -0
  50. package/dist/tokens.d.ts +2 -0
  51. package/dist/tokens.js +37 -7
  52. package/dist/touch.d.ts +27 -0
  53. package/dist/touch.js +100 -0
  54. package/dist/types.d.ts +84 -2
  55. package/dist/uniform-geometry.d.ts +7 -0
  56. package/dist/uniform-geometry.js +49 -0
  57. package/dist/view.d.ts +68 -17
  58. package/dist/view.js +424 -97
  59. package/dist/worker-client.d.ts +37 -0
  60. package/dist/worker-client.js +195 -0
  61. package/package.json +17 -2
  62. package/src/attribution.ts +50 -14
  63. package/src/bidi.ts +32 -0
  64. package/src/column-selection.ts +2 -1
  65. package/src/controller.ts +97 -3
  66. package/src/editor.css +81 -1
  67. package/src/engine.ts +216 -42
  68. package/src/fake.ts +152 -14
  69. package/src/find-search.ts +165 -0
  70. package/src/find.ts +622 -21
  71. package/src/geometry-stops.ts +51 -0
  72. package/src/grammar-preparation.ts +158 -0
  73. package/src/index.ts +10 -0
  74. package/src/keymap-table.ts +44 -2
  75. package/src/keymap.ts +5 -1
  76. package/src/layout-changes.ts +33 -0
  77. package/src/layout.ts +262 -63
  78. package/src/offsets.ts +24 -0
  79. package/src/outline.ts +5 -4
  80. package/src/paint.ts +202 -36
  81. package/src/search-client.ts +306 -0
  82. package/src/search-protocol.ts +100 -0
  83. package/src/search-worker.ts +171 -0
  84. package/src/semantic.ts +8 -2
  85. package/src/shiki-document.ts +143 -0
  86. package/src/shiki-worker.ts +344 -0
  87. package/src/shiki.ts +103 -33
  88. package/src/testing.ts +2 -0
  89. package/src/tokens.ts +36 -7
  90. package/src/touch.ts +134 -0
  91. package/src/types.ts +174 -8
  92. package/src/uniform-geometry.ts +57 -0
  93. package/src/view.ts +500 -102
  94. package/src/worker-client.ts +212 -0
@@ -0,0 +1,212 @@
1
+ export type WorkerRequestPort = Pick<Worker, 'addEventListener' | 'removeEventListener' | 'postMessage' | 'terminate'>;
2
+ export type WorkerRequestErrorKind = 'timeout' | 'superseded' | 'unavailable' | 'error' | 'disposed';
3
+ export class WorkerRequestError extends Error {
4
+ readonly kind: WorkerRequestErrorKind;
5
+ constructor(kind: WorkerRequestErrorKind, message: string) {
6
+ super(message);
7
+ this.kind = kind;
8
+ this.name = 'WorkerRequestError';
9
+ }
10
+ }
11
+ export interface WorkerRequestOptions<Input extends { id: number }, Output extends { id: number }> {
12
+ readonly workerFactory: () => WorkerRequestPort;
13
+ readonly deadline?: number;
14
+ readonly schedule?: (callback: () => void, delay: number) => () => void;
15
+ readonly prepare?: (input: Input) => Input;
16
+ readonly accepts?: (reply: Output, input: Input) => boolean;
17
+ readonly failure?: (reply: Output) => { error: Error; restart: boolean } | undefined;
18
+ readonly stopped?: () => void;
19
+ }
20
+ export interface WorkerRequestClient<Input extends { id: number }, Output extends { id: number }> {
21
+ request(input: (id: number) => Input, deadline?: number, validate?: () => void): Promise<Output>;
22
+ cancel(): void;
23
+ release(): void;
24
+ dispose(): void;
25
+ }
26
+ function scheduleTimer(callback: () => void, delay: number): () => void {
27
+ const timer = setTimeout(callback, delay);
28
+ return () => clearTimeout(timer);
29
+ }
30
+ export function createWorkerRequestClient<Input extends { id: number }, Output extends { id: number }>(
31
+ options: WorkerRequestOptions<Input, Output>
32
+ ): WorkerRequestClient<Input, Output> {
33
+ const deadline = options.deadline ?? 1500;
34
+ if (!Number.isFinite(deadline) || deadline <= 0 || deadline > 2147483647) {
35
+ throw new RangeError('The worker deadline must fit a positive browser timer.');
36
+ }
37
+ const schedule = options.schedule ?? scheduleTimer;
38
+ type Request = { input: Input; deadline: number; resolve: (reply: Output) => void; reject: (error: Error) => void };
39
+ let worker: WorkerRequestPort | undefined, detach: (() => void) | undefined, cancelTimer: (() => void) | undefined;
40
+ let active: Request | undefined, pending: Request | undefined;
41
+ let unavailable: WorkerRequestError | undefined;
42
+ let disposed = false,
43
+ nextId = 0;
44
+ const stopWorker = (): void => {
45
+ cancelTimer?.();
46
+ cancelTimer = undefined;
47
+ detach?.();
48
+ detach = undefined;
49
+ const previous = worker;
50
+ worker = undefined;
51
+ options.stopped?.();
52
+ previous?.terminate();
53
+ };
54
+ const fail = (request: Request, error: Error, restart = true): void => {
55
+ if (active !== request) {
56
+ return;
57
+ }
58
+ active = undefined;
59
+ if (restart) {
60
+ stopWorker();
61
+ } else {
62
+ cancelTimer?.();
63
+ cancelTimer = undefined;
64
+ }
65
+ request.reject(error);
66
+ };
67
+ const startWorker = (): WorkerRequestPort => {
68
+ if (worker !== undefined) {
69
+ return worker;
70
+ }
71
+ let created: WorkerRequestPort;
72
+ try {
73
+ created = options.workerFactory();
74
+ } catch (error) {
75
+ unavailable = new WorkerRequestError('unavailable', error instanceof Error ? error.message : String(error));
76
+ throw unavailable;
77
+ }
78
+ worker = created;
79
+ let received = false;
80
+ const onMessage = (event: Event): void => {
81
+ if (worker !== created) {
82
+ return;
83
+ }
84
+ const reply = (event as MessageEvent<Output | { type: 'ready' }>).data;
85
+ if (reply === null || typeof reply !== 'object') {
86
+ if (active !== undefined) {
87
+ fail(active, new WorkerRequestError('error', 'The worker returned an invalid response.'));
88
+ }
89
+ return;
90
+ }
91
+ received = true;
92
+ if ('type' in reply && reply.type === 'ready') {
93
+ return;
94
+ }
95
+ const request = active;
96
+ if (request === undefined || !('id' in reply) || reply.id !== request.input.id) {
97
+ return;
98
+ }
99
+ try {
100
+ if (options.accepts?.(reply, request.input) === false) {
101
+ return;
102
+ }
103
+ const failure = options.failure?.(reply);
104
+ if (failure !== undefined) {
105
+ fail(request, failure.error, failure.restart);
106
+ return;
107
+ }
108
+ active = undefined;
109
+ cancelTimer?.();
110
+ cancelTimer = undefined;
111
+ request.resolve(reply);
112
+ } catch (error) {
113
+ fail(request, new WorkerRequestError('error', error instanceof Error ? error.message : String(error)));
114
+ }
115
+ };
116
+ const onError = (event: Event): void => {
117
+ if (worker !== created) {
118
+ return;
119
+ }
120
+ const error = new WorkerRequestError(received ? 'error' : 'unavailable', (event as ErrorEvent).message || 'The worker failed.');
121
+ if (!received) {
122
+ unavailable = error;
123
+ }
124
+ if (active !== undefined) {
125
+ fail(active, error);
126
+ } else {
127
+ stopWorker();
128
+ }
129
+ };
130
+ const onMessageError = (): void => {
131
+ if (worker !== created) {
132
+ return;
133
+ }
134
+ if (active !== undefined) {
135
+ fail(active, new WorkerRequestError('error', 'The worker response could not be decoded.'));
136
+ } else {
137
+ stopWorker();
138
+ }
139
+ };
140
+ created.addEventListener('message', onMessage);
141
+ created.addEventListener('error', onError);
142
+ created.addEventListener('messageerror', onMessageError);
143
+ detach = () => {
144
+ created.removeEventListener('message', onMessage);
145
+ created.removeEventListener('error', onError);
146
+ created.removeEventListener('messageerror', onMessageError);
147
+ };
148
+ return created;
149
+ };
150
+ const pump = (): void => {
151
+ const request = pending;
152
+ if (disposed || request === undefined) {
153
+ return;
154
+ }
155
+ pending = undefined;
156
+ active = request;
157
+ try {
158
+ const target = startWorker();
159
+ cancelTimer = schedule(() => fail(request, new WorkerRequestError('timeout', 'The worker exceeded its time limit.')), request.deadline);
160
+ target.postMessage(options.prepare?.(request.input) ?? request.input);
161
+ } catch (error) {
162
+ fail(
163
+ request,
164
+ error instanceof WorkerRequestError ? error : new WorkerRequestError('error', error instanceof Error ? error.message : String(error))
165
+ );
166
+ }
167
+ };
168
+ const cancel = (kind: 'superseded' | 'disposed'): void => {
169
+ const error = new WorkerRequestError(kind, kind === 'disposed' ? 'The worker client was disposed.' : 'A newer request superseded this request.');
170
+ pending?.reject(error);
171
+ pending = undefined;
172
+ if (active !== undefined) {
173
+ fail(active, error);
174
+ }
175
+ };
176
+ return {
177
+ request(input, duration = deadline, validate) {
178
+ if (disposed) {
179
+ return Promise.reject(new WorkerRequestError('disposed', 'The worker client was disposed.'));
180
+ }
181
+ if (unavailable !== undefined) {
182
+ return Promise.reject(unavailable);
183
+ }
184
+ cancel('superseded');
185
+ try {
186
+ validate?.();
187
+ if (!Number.isFinite(duration) || duration <= 0 || duration > 2147483647) {
188
+ throw new RangeError('The request deadline must fit a positive browser timer.');
189
+ }
190
+ } catch (error) {
191
+ return Promise.reject(error);
192
+ }
193
+ return new Promise((resolve, reject) => {
194
+ pending = { input: input(++nextId), deadline: duration, resolve, reject };
195
+ // A burst before the microtask posts only its newest request.
196
+ queueMicrotask(pump);
197
+ });
198
+ },
199
+ cancel() {
200
+ cancel('superseded');
201
+ },
202
+ release() {
203
+ cancel('superseded');
204
+ stopWorker();
205
+ },
206
+ dispose() {
207
+ disposed = true;
208
+ cancel('disposed');
209
+ stopWorker();
210
+ }
211
+ };
212
+ }