@adecore/editor-react 0.43.0 → 0.44.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/PickPopup.js +94 -73
  2. package/dist/completion.d.ts +28 -0
  3. package/dist/completion.js +76 -15
  4. package/dist/editor-language.d.ts +4 -0
  5. package/dist/editor-language.js +6 -0
  6. package/dist/host-types.d.ts +4 -0
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.js +2 -0
  9. package/dist/key-priority.d.ts +1 -0
  10. package/dist/key-priority.js +2 -0
  11. package/dist/live-templates.d.ts +16 -0
  12. package/dist/live-templates.js +289 -0
  13. package/dist/locales/en.json +30 -0
  14. package/dist/locales/nl.json +30 -0
  15. package/dist/markup-context.d.ts +18 -0
  16. package/dist/markup-context.js +122 -5
  17. package/dist/markup.d.ts +3 -0
  18. package/dist/markup.js +16 -4
  19. package/dist/pick.d.ts +1 -0
  20. package/dist/pick.js +11 -1
  21. package/dist/popups.d.ts +1 -0
  22. package/dist/postfix.d.ts +21 -0
  23. package/dist/postfix.js +212 -0
  24. package/dist/project-language.d.ts +2 -0
  25. package/dist/project-language.js +3 -0
  26. package/dist/shortcut-keys.d.ts +5 -0
  27. package/dist/snippet-insert.d.ts +10 -0
  28. package/dist/snippet-insert.js +217 -0
  29. package/dist/snippet.d.ts +7 -1
  30. package/dist/snippet.js +65 -8
  31. package/dist/surround-constructs.d.ts +10 -0
  32. package/dist/surround-constructs.js +100 -0
  33. package/dist/surround.d.ts +18 -0
  34. package/dist/surround.js +399 -0
  35. package/dist/template-builtins.d.ts +3 -0
  36. package/dist/template-builtins.js +46 -0
  37. package/dist/template-context.d.ts +12 -0
  38. package/dist/template-context.js +56 -0
  39. package/dist/templates.d.ts +59 -0
  40. package/dist/templates.js +103 -0
  41. package/package.json +6 -6
  42. package/src/PickPopup.tsx +7 -0
  43. package/src/completion.ts +111 -13
  44. package/src/editor-language.ts +6 -0
  45. package/src/host-types.ts +7 -0
  46. package/src/index.ts +16 -0
  47. package/src/key-priority.ts +2 -0
  48. package/src/live-templates.ts +315 -0
  49. package/src/locales/en.json +30 -0
  50. package/src/locales/nl.json +30 -0
  51. package/src/markup-context.ts +131 -6
  52. package/src/markup.ts +15 -5
  53. package/src/pick.ts +17 -1
  54. package/src/popups.ts +2 -0
  55. package/src/postfix.ts +224 -0
  56. package/src/project-language.ts +3 -0
  57. package/src/snippet-insert.ts +258 -0
  58. package/src/snippet.ts +82 -7
  59. package/src/surround-constructs.ts +85 -0
  60. package/src/surround.ts +430 -0
  61. package/src/template-builtins.ts +94 -0
  62. package/src/template-context.ts +65 -0
  63. package/src/templates.ts +197 -0
@@ -0,0 +1,197 @@
1
+ import { BUILT_IN_LIVE_TEMPLATES, BUILT_IN_POSTFIX_TEMPLATES } from './template-builtins.ts';
2
+ import { checkSnippet } from './snippet.ts';
3
+
4
+ export { BUILT_IN_LIVE_TEMPLATES, BUILT_IN_POSTFIX_TEMPLATES };
5
+ export { type TemplatesFeature } from './live-templates.ts';
6
+
7
+ /* The families of language a live template belongs to; a family also matches the languages that build on it. */
8
+ export type TemplateLanguage = 'javascript' | 'typescript' | 'php' | 'css' | 'html' | 'xml' | 'other';
9
+
10
+ /* What the text at the caret is: code, a comment or a string. */
11
+ export type TemplatePlace = 'code' | 'comment' | 'string';
12
+
13
+ const MAX_KEY_LENGTH = 40;
14
+ const MAX_BODY_LENGTH = 20_000;
15
+ const POSTFIX_LANGUAGES: readonly string[] = ['javascript', 'typescript', 'php'];
16
+ const LANGUAGES: readonly string[] = ['javascript', 'typescript', 'php', 'css', 'html', 'xml', 'other'];
17
+ const PLACES: readonly string[] = ['code', 'comment', 'string'];
18
+
19
+ /* A text that Tab expands after its key, in the syntax of a snippet. */
20
+ export interface LiveTemplate {
21
+ /* Stable; a built-in one is `builtin.<language>.<key>`. */
22
+ readonly id: string;
23
+
24
+ /* One to 40 characters, none of them whitespace. */
25
+ readonly key: string;
26
+
27
+ /* Snippet syntax; the leading tabs of a line are one indentation unit each. */
28
+ readonly body: string;
29
+ readonly description?: string;
30
+ readonly languages: readonly TemplateLanguage[];
31
+
32
+ /* Where it applies; `['code']` without it. */
33
+ readonly places?: readonly TemplatePlace[];
34
+
35
+ /* What Insert Live Template sorts by; the first language without it. */
36
+ readonly group?: string;
37
+ }
38
+
39
+ /* A text that Tab expands after a dot and its key, around the expression before the dot. */
40
+ export interface PostfixTemplate {
41
+ readonly id: string;
42
+
43
+ /* Without the dot; identifier characters only. */
44
+ readonly key: string;
45
+
46
+ /* Snippet syntax, in which `$EXPR` is the expression. */
47
+ readonly body: string;
48
+ readonly description?: string;
49
+
50
+ /* Shown at the end of its row, as in `if (expr) {}`. */
51
+ readonly example?: string;
52
+ readonly languages: readonly ('javascript' | 'typescript' | 'php')[];
53
+
54
+ /* `any` without it. */
55
+ readonly expression?: 'any' | 'statement';
56
+ }
57
+
58
+ /* Each is on unless false. */
59
+ export interface TemplateSettings {
60
+ /* Live templates are rows of the suggestion list. */
61
+ readonly liveInCompletion?: boolean;
62
+
63
+ /* Tab after a dot and a key expands a postfix template. */
64
+ readonly postfix?: boolean;
65
+
66
+ /* Postfix templates are rows of the suggestion list. */
67
+ readonly postfixInCompletion?: boolean;
68
+ }
69
+
70
+ /* What Save as Live Template hands the host. */
71
+ export interface LiveTemplateDraft {
72
+ readonly body: string;
73
+ readonly languages: readonly TemplateLanguage[];
74
+ readonly places: readonly TemplatePlace[];
75
+ }
76
+
77
+ export interface TemplateRegistryOptions {
78
+ /* Whether the built-in templates are part of the registry; true by default. */
79
+ readonly builtins?: boolean;
80
+ }
81
+
82
+ export interface TemplateUpdate {
83
+ readonly live?: readonly LiveTemplate[];
84
+ readonly postfix?: readonly PostfixTemplate[];
85
+
86
+ /* Ids of the built-in templates that are off. */
87
+ readonly disabled?: readonly string[];
88
+ readonly settings?: TemplateSettings;
89
+ }
90
+
91
+ /*
92
+ * The templates the editors of a project know: the built-in ones and the ones a host sets. A host that keeps
93
+ * templates feeds them through `set`, and the editors read the registry on every use.
94
+ */
95
+ export class TemplateRegistry {
96
+ private readonly builtins: boolean;
97
+ private readonly listeners = new Set<() => void>();
98
+ private own: { live: readonly LiveTemplate[]; postfix: readonly PostfixTemplate[] } = { live: [], postfix: [] };
99
+ private off: ReadonlySet<string> = new Set();
100
+ private current: Required<TemplateSettings> = { liveInCompletion: true, postfix: true, postfixInCompletion: true };
101
+ private liveList: readonly LiveTemplate[];
102
+ private postfixList: readonly PostfixTemplate[];
103
+
104
+ constructor(options: TemplateRegistryOptions = {}) {
105
+ this.builtins = options.builtins !== false;
106
+ this.liveList = this.listed(BUILT_IN_LIVE_TEMPLATES, []);
107
+ this.postfixList = this.listed(BUILT_IN_POSTFIX_TEMPLATES, []);
108
+ }
109
+
110
+ /* The built-in templates that are not disabled, then the host's. */
111
+ get live(): readonly LiveTemplate[] {
112
+ return this.liveList;
113
+ }
114
+
115
+ get postfix(): readonly PostfixTemplate[] {
116
+ return this.postfixList;
117
+ }
118
+
119
+ get settings(): Required<TemplateSettings> {
120
+ return this.current;
121
+ }
122
+
123
+ /* Replaces what the update names. A template that fails `checkTemplate` is dropped; this never throws. */
124
+ set(update: TemplateUpdate): void {
125
+ this.own = {
126
+ live: update.live === undefined ? this.own.live : update.live.filter((template) => checkTemplate(template, 'live') === null),
127
+ postfix: update.postfix === undefined ? this.own.postfix : update.postfix.filter((template) => checkTemplate(template, 'postfix') === null)
128
+ };
129
+ this.off = update.disabled === undefined ? this.off : new Set(update.disabled);
130
+
131
+ if (update.settings !== undefined) {
132
+ this.current = {
133
+ liveInCompletion: update.settings.liveInCompletion !== false,
134
+ postfix: update.settings.postfix !== false,
135
+ postfixInCompletion: update.settings.postfixInCompletion !== false
136
+ };
137
+ }
138
+
139
+ this.liveList = this.listed(BUILT_IN_LIVE_TEMPLATES, this.own.live);
140
+ this.postfixList = this.listed(BUILT_IN_POSTFIX_TEMPLATES, this.own.postfix);
141
+
142
+ for (const listener of [...this.listeners]) {
143
+ listener();
144
+ }
145
+ }
146
+
147
+ /* Calls `listener` after every `set`. Returns the function that stops it. */
148
+ onChange(listener: () => void): () => void {
149
+ this.listeners.add(listener);
150
+
151
+ return () => {
152
+ this.listeners.delete(listener);
153
+ };
154
+ }
155
+
156
+ private listed<T extends { readonly id: string }>(builtins: readonly T[], own: readonly T[]): readonly T[] {
157
+ return [...(this.builtins ? builtins.filter((template) => !this.off.has(template.id)) : []), ...own];
158
+ }
159
+ }
160
+
161
+ /*
162
+ * Why a template cannot be used, in English for a host to show, or null. `kind` says which rules apply; without it a
163
+ * template with an `expression` or an `example` counts as a postfix one.
164
+ */
165
+ export function checkTemplate(template: LiveTemplate | PostfixTemplate, kind?: 'live' | 'postfix'): string | null {
166
+ const postfix = kind === undefined ? 'expression' in template || 'example' in template : kind === 'postfix';
167
+
168
+ if (template.id === '') {
169
+ return 'The template has no id.';
170
+ }
171
+
172
+ if (template.key === '' || template.key.length > MAX_KEY_LENGTH) {
173
+ return `The key is one to ${MAX_KEY_LENGTH} characters.`;
174
+ }
175
+
176
+ if (postfix ? !/^[\p{L}\p{N}_$]+$/u.test(template.key) : /\s/.test(template.key)) {
177
+ return postfix ? 'The key holds letters, digits, underscores and dollar signs only.' : 'The key holds no whitespace.';
178
+ }
179
+
180
+ if (template.body.trim() === '') {
181
+ return 'The text is empty.';
182
+ }
183
+
184
+ if (template.body.length > MAX_BODY_LENGTH) {
185
+ return `The text is longer than ${MAX_BODY_LENGTH} characters.`;
186
+ }
187
+
188
+ if (template.languages.length === 0 || template.languages.some((language) => !(postfix ? POSTFIX_LANGUAGES : LANGUAGES).includes(language))) {
189
+ return 'The languages are empty or not known.';
190
+ }
191
+
192
+ if (!postfix && (template as LiveTemplate).places?.some((place) => !PLACES.includes(place)) === true) {
193
+ return 'The places are not known.';
194
+ }
195
+
196
+ return checkSnippet(template.body);
197
+ }