@adecore/editor-react 0.42.0 → 0.44.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 (150) hide show
  1. package/dist/CallHierarchyPanel.js +177 -181
  2. package/dist/EditorContextMenu.js +118 -105
  3. package/dist/LanguagePopups.js +7 -0
  4. package/dist/PickPopup.js +245 -104
  5. package/dist/WrapCard.d.ts +8 -0
  6. package/dist/WrapCard.js +172 -0
  7. package/dist/call-hierarchy-model.d.ts +4 -2
  8. package/dist/call-hierarchy-model.js +20 -0
  9. package/dist/call-hierarchy.d.ts +3 -0
  10. package/dist/call-hierarchy.js +54 -22
  11. package/dist/clipboard-history.d.ts +31 -0
  12. package/dist/clipboard-history.js +70 -0
  13. package/dist/code-actions.d.ts +3 -1
  14. package/dist/code-actions.js +50 -10
  15. package/dist/code-vision.js +2 -3
  16. package/dist/completion.d.ts +28 -0
  17. package/dist/completion.js +83 -27
  18. package/dist/context-menu-rows.d.ts +1 -1
  19. package/dist/context-menu-rows.js +4 -0
  20. package/dist/definition-link.js +15 -5
  21. package/dist/document-colors.d.ts +24 -0
  22. package/dist/document-colors.js +194 -0
  23. package/dist/document-links.d.ts +22 -0
  24. package/dist/document-links.js +133 -0
  25. package/dist/document-query.d.ts +15 -0
  26. package/dist/document-query.js +54 -0
  27. package/dist/edit-locations.d.ts +20 -0
  28. package/dist/edit-locations.js +136 -0
  29. package/dist/editor-language.d.ts +23 -1
  30. package/dist/editor-language.js +83 -2
  31. package/dist/emmet.d.ts +13 -0
  32. package/dist/emmet.js +62 -0
  33. package/dist/folding.js +2 -3
  34. package/dist/format-on-type.js +3 -5
  35. package/dist/highlights.js +2 -3
  36. package/dist/history.d.ts +7 -0
  37. package/dist/history.js +79 -1
  38. package/dist/host-types.d.ts +10 -0
  39. package/dist/index.d.ts +13 -2
  40. package/dist/index.js +10 -0
  41. package/dist/inlay-hints.js +2 -2
  42. package/dist/inline-completion.d.ts +39 -0
  43. package/dist/inline-completion.js +221 -0
  44. package/dist/key-priority.d.ts +9 -5
  45. package/dist/key-priority.js +11 -6
  46. package/dist/linked-editing.d.ts +26 -0
  47. package/dist/linked-editing.js +215 -0
  48. package/dist/live-templates.d.ts +16 -0
  49. package/dist/live-templates.js +289 -0
  50. package/dist/locales/en.json +61 -2
  51. package/dist/locales/nl.json +61 -2
  52. package/dist/markup-context.d.ts +55 -0
  53. package/dist/markup-context.js +408 -0
  54. package/dist/markup.d.ts +39 -0
  55. package/dist/markup.js +465 -0
  56. package/dist/navigation.js +4 -6
  57. package/dist/paste-history.d.ts +7 -0
  58. package/dist/paste-history.js +104 -0
  59. package/dist/peek.js +3 -4
  60. package/dist/pick.d.ts +21 -2
  61. package/dist/pick.js +152 -19
  62. package/dist/popups.d.ts +10 -0
  63. package/dist/popups.js +2 -1
  64. package/dist/postfix.d.ts +21 -0
  65. package/dist/postfix.js +212 -0
  66. package/dist/project-language.d.ts +20 -1
  67. package/dist/project-language.js +132 -18
  68. package/dist/rename.js +8 -11
  69. package/dist/rendered-docs.js +1 -2
  70. package/dist/selection-ranges.js +2 -3
  71. package/dist/shortcut-keys.d.ts +24 -0
  72. package/dist/signature.js +3 -6
  73. package/dist/snippet-insert.d.ts +10 -0
  74. package/dist/snippet-insert.js +217 -0
  75. package/dist/snippet-session.d.ts +2 -2
  76. package/dist/snippet-session.js +3 -3
  77. package/dist/snippet.d.ts +7 -1
  78. package/dist/snippet.js +65 -8
  79. package/dist/surround-constructs.d.ts +10 -0
  80. package/dist/surround-constructs.js +100 -0
  81. package/dist/surround.d.ts +18 -0
  82. package/dist/surround.js +399 -0
  83. package/dist/symbol-picker.js +4 -6
  84. package/dist/symbols.js +22 -3
  85. package/dist/template-builtins.d.ts +3 -0
  86. package/dist/template-builtins.js +46 -0
  87. package/dist/template-context.d.ts +12 -0
  88. package/dist/template-context.js +56 -0
  89. package/dist/templates.d.ts +59 -0
  90. package/dist/templates.js +103 -0
  91. package/dist/testing.d.ts +23 -1
  92. package/dist/testing.js +114 -0
  93. package/package.json +7 -6
  94. package/src/CallHierarchyPanel.tsx +26 -11
  95. package/src/EditorContextMenu.tsx +7 -0
  96. package/src/LanguagePopups.tsx +4 -0
  97. package/src/PickPopup.tsx +47 -5
  98. package/src/WrapCard.tsx +64 -0
  99. package/src/call-hierarchy-model.ts +25 -3
  100. package/src/call-hierarchy.ts +62 -20
  101. package/src/clipboard-history.ts +102 -0
  102. package/src/code-actions.ts +48 -11
  103. package/src/code-vision.ts +3 -3
  104. package/src/completion.ts +123 -25
  105. package/src/context-menu-rows.ts +3 -2
  106. package/src/definition-link.ts +17 -5
  107. package/src/document-colors.ts +189 -0
  108. package/src/document-links.ts +129 -0
  109. package/src/document-query.ts +71 -0
  110. package/src/edit-locations.ts +162 -0
  111. package/src/editor-language.ts +86 -3
  112. package/src/emmet-module.d.ts +44 -0
  113. package/src/emmet.ts +73 -0
  114. package/src/folding.ts +3 -3
  115. package/src/format-on-type.ts +5 -5
  116. package/src/highlights.ts +3 -3
  117. package/src/history.ts +81 -1
  118. package/src/host-types.ts +17 -0
  119. package/src/index.ts +28 -3
  120. package/src/inlay-hints.ts +2 -2
  121. package/src/inline-completion.ts +221 -0
  122. package/src/key-priority.ts +11 -6
  123. package/src/linked-editing.ts +199 -0
  124. package/src/live-templates.ts +315 -0
  125. package/src/locales/en.json +61 -2
  126. package/src/locales/nl.json +61 -2
  127. package/src/markup-context.ts +387 -0
  128. package/src/markup.ts +377 -0
  129. package/src/navigation.ts +6 -6
  130. package/src/paste-history.ts +111 -0
  131. package/src/peek.ts +4 -4
  132. package/src/pick.ts +218 -20
  133. package/src/popups.ts +21 -1
  134. package/src/postfix.ts +224 -0
  135. package/src/project-language.ts +139 -19
  136. package/src/rename.ts +11 -11
  137. package/src/rendered-docs.ts +2 -2
  138. package/src/selection-ranges.ts +3 -3
  139. package/src/signature.ts +6 -6
  140. package/src/snippet-insert.ts +258 -0
  141. package/src/snippet-session.ts +9 -4
  142. package/src/snippet.ts +82 -7
  143. package/src/surround-constructs.ts +85 -0
  144. package/src/surround.ts +430 -0
  145. package/src/symbol-picker.ts +6 -6
  146. package/src/symbols.ts +30 -4
  147. package/src/template-builtins.ts +94 -0
  148. package/src/template-context.ts +65 -0
  149. package/src/templates.ts +197 -0
  150. package/src/testing.ts +126 -1
@@ -70,6 +70,12 @@
70
70
  "delete": "Verwijdert"
71
71
  }
72
72
  },
73
+ "markup": {
74
+ "wrap": "Omwikkelen met afkorting",
75
+ "placeholder": "Afkorting, zoals div.card>p",
76
+ "apply": "Omwikkelen",
77
+ "invalid": "Geen geldige afkorting"
78
+ },
73
79
  "navigation": {
74
80
  "unavailable": "Hier niet beschikbaar",
75
81
  "none": "Niets gevonden",
@@ -119,13 +125,30 @@
119
125
  "site": "Aanroep {{current}} van {{total}}",
120
126
  "previousSite": "Vorige aanroep",
121
127
  "nextSite": "Volgende aanroep",
128
+ "typesUnavailable": "Typehiërarchie niet beschikbaar in dit bestand",
129
+ "typesNone": "Hier geen type",
130
+ "typesFailed": "Kon de types niet opzoeken: {{message}}",
131
+ "typesLabel": "Typehiërarchie",
132
+ "supertypes": "Supertypes",
133
+ "subtypes": "Subtypes",
134
+ "noSupertypes": "Geen supertypes",
135
+ "noSubtypes": "Geen subtypes",
122
136
  "announce": {
123
137
  "incoming_one": "{{count}} aanroeper van {{name}}",
124
138
  "incoming_other": "{{count}} aanroepers van {{name}}",
125
139
  "outgoing_one": "{{count}} aangeroepen door {{name}}",
126
- "outgoing_other": "{{count}} aangeroepen door {{name}}"
140
+ "outgoing_other": "{{count}} aangeroepen door {{name}}",
141
+ "supertypes_one": "{{count}} supertype van {{name}}",
142
+ "supertypes_other": "{{count}} supertypes van {{name}}",
143
+ "subtypes_one": "{{count}} subtype van {{name}}",
144
+ "subtypes_other": "{{count}} subtypes van {{name}}"
127
145
  }
128
146
  },
147
+ "colors": {
148
+ "swatch": "Kleur {{color}}",
149
+ "title": "Kleur",
150
+ "other": "Andere kleur kiezen…"
151
+ },
129
152
  "codeVision": {
130
153
  "usagesNone": "Niet gebruikt",
131
154
  "usages_one": "{{formatted}} keer gebruikt",
@@ -192,6 +215,40 @@
192
215
  "history": {
193
216
  "recent": "Recente plekken"
194
217
  },
218
+ "pasteHistory": {
219
+ "title": "Kies wat je plakt",
220
+ "empty": "Er is nog niets gekopieerd"
221
+ },
222
+ "templates": {
223
+ "none": "Geen sjablonen gedefinieerd in deze context",
224
+ "selectToSave": "Selecteer de tekst die je als live sjabloon wilt opslaan"
225
+ },
226
+ "postfix": {
227
+ "expressions": "Expressies"
228
+ },
229
+ "surround": {
230
+ "title": "Omring met",
231
+ "selectTemplate": "Kies een sjabloon",
232
+ "liveTemplates": "Live sjablonen",
233
+ "configure": "Live sjablonen instellen…",
234
+ "comments": "{{construct}}-commentaar",
235
+ "none": "Geen Omring met-varianten gevonden voor de huidige context",
236
+ "noTemplates": "Geen omringende sjablonen gedefinieerd in deze context",
237
+ "unwrap": {
238
+ "title": "Kies het statement om uit te pakken of te verwijderen",
239
+ "if": "'if...' uitpakken",
240
+ "else": "'else...' uitpakken",
241
+ "removeElse": "'else...' verwijderen",
242
+ "for": "'for...' uitpakken",
243
+ "while": "'while...' uitpakken",
244
+ "do": "'do...' uitpakken",
245
+ "try": "'try...' uitpakken",
246
+ "removeCatch": "'catch...' verwijderen",
247
+ "removeFinally": "'finally...' verwijderen",
248
+ "braces": "Accolades uitpakken",
249
+ "tag": "Omringende tag verwijderen: {{name}}"
250
+ }
251
+ },
195
252
  "announce": {
196
253
  "problem": "{{severity}}: {{message}}",
197
254
  "severity": {
@@ -236,10 +293,12 @@
236
293
  "goToTypeDefinition": "Ga naar typedefinitie",
237
294
  "goToImplementation": "Ga naar implementatie",
238
295
  "callHierarchy": "Aanroephiërarchie",
296
+ "typeHierarchy": "Typehiërarchie",
239
297
  "peekReferences": "Bekijk referenties",
240
298
  "renameSymbol": "Symbool hernoemen",
241
299
  "codeActions": "Codeacties",
242
- "formatDocument": "Document formatteren"
300
+ "formatDocument": "Document formatteren",
301
+ "formatSelection": "Selectie formatteren"
243
302
  },
244
303
  "find": {
245
304
  "label": "Zoeken",
@@ -0,0 +1,55 @@
1
+ export type MarkupSyntax = 'html' | 'xml' | 'vue' | 'php';
2
+ export interface OpenElement {
3
+ readonly name: string;
4
+ readonly nameFrom: number;
5
+ }
6
+ export interface TagAt {
7
+ readonly start: number;
8
+ readonly closing: boolean;
9
+ readonly name: string;
10
+ readonly nameFrom: number;
11
+ readonly nameTo: number;
12
+ readonly inValue: boolean;
13
+ }
14
+ export type MarkupPlace = {
15
+ readonly kind: 'text';
16
+ readonly open: readonly OpenElement[];
17
+ } | {
18
+ readonly kind: 'tag';
19
+ readonly tag: TagAt;
20
+ } | {
21
+ readonly kind: 'other';
22
+ };
23
+ export interface TagPair {
24
+ readonly open: {
25
+ readonly from: number;
26
+ readonly to: number;
27
+ };
28
+ readonly close: {
29
+ readonly from: number;
30
+ readonly to: number;
31
+ };
32
+ }
33
+ export interface TagSpan {
34
+ readonly from: number;
35
+ readonly to: number;
36
+ }
37
+ export interface EnclosingElement {
38
+ readonly name: string;
39
+ readonly open: TagSpan;
40
+ readonly close: TagSpan | null;
41
+ }
42
+ export declare const MAX_MARKUP_SCAN = 1000000;
43
+ export declare function markupSyntaxOf(languageId: string): MarkupSyntax | null;
44
+ export declare function isVoidElement(name: string, syntax: MarkupSyntax): boolean;
45
+ export declare function enclosingElements(text: string, offset: number, syntax: MarkupSyntax): EnclosingElement[];
46
+ export interface TextReplacement {
47
+ readonly from: number;
48
+ readonly to: number;
49
+ readonly text: string;
50
+ }
51
+ export declare function lineStartOf(text: string, offset: number): number;
52
+ export declare function lineEndOf(text: string, offset: number): number;
53
+ export declare function removeTagEdits(text: string, element: EnclosingElement, unit: string): TextReplacement[];
54
+ export declare function markupPlaceAt(text: string, offset: number, syntax: MarkupSyntax): MarkupPlace | null;
55
+ export declare function tagPairAt(text: string, offset: number, syntax: MarkupSyntax): TagPair | null;
@@ -0,0 +1,408 @@
1
+ /* Above this a document is not read on a keystroke; the features then do nothing in it. */
2
+ export const MAX_MARKUP_SCAN = 1_000_000;
3
+ const VOID_ELEMENTS = new Set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr']);
4
+ const RAW_ELEMENTS = new Set(['script', 'style', 'textarea', 'title']);
5
+ const NAME_START = /[A-Za-z]/;
6
+ const NAME = /[\w:.-]/;
7
+ export function markupSyntaxOf(languageId) {
8
+ switch (languageId.toLowerCase()) {
9
+ case 'html':
10
+ case 'xhtml':
11
+ return 'html';
12
+ case 'xml':
13
+ case 'svg':
14
+ case 'xsl':
15
+ return 'xml';
16
+ case 'vue':
17
+ return 'vue';
18
+ case 'php':
19
+ return 'php';
20
+ default:
21
+ return null;
22
+ }
23
+ }
24
+ /* Whether an element of this name has no end tag, which only HTML has. */
25
+ export function isVoidElement(name, syntax) {
26
+ return syntax !== 'xml' && VOID_ELEMENTS.has(name.toLowerCase());
27
+ }
28
+ class Stop {
29
+ place;
30
+ constructor(place) {
31
+ this.place = place;
32
+ }
33
+ }
34
+ /*
35
+ * A reader of markup that is no parser: it follows tags, comments, raw elements and the code blocks of
36
+ * PHP and Vue far enough to tell what an offset is in, and pairs a start tag with the end tag that closes it.
37
+ */
38
+ class MarkupScanner {
39
+ pairs = [];
40
+ elements = [];
41
+ text;
42
+ syntax;
43
+ until;
44
+ open = [];
45
+ constructor(text, syntax, until) {
46
+ this.text = text;
47
+ this.syntax = syntax;
48
+ this.until = until;
49
+ }
50
+ run() {
51
+ try {
52
+ this.content();
53
+ return this.textPlace();
54
+ } catch (error) {
55
+ if (error instanceof Stop) {
56
+ return error.place;
57
+ }
58
+ throw error;
59
+ }
60
+ }
61
+ textPlace() {
62
+ return {
63
+ kind: 'text',
64
+ open: this.open.map(({
65
+ name,
66
+ nameFrom
67
+ }) => ({
68
+ name,
69
+ nameFrom
70
+ }))
71
+ };
72
+ }
73
+ /* Leaves the scan with what the offset is in when it lies in `from` to `to`, `to` included where the construct owns its last character. */
74
+ reached(from, to, place) {
75
+ if (from < this.until && this.until <= to) {
76
+ throw new Stop(place());
77
+ }
78
+ }
79
+ content() {
80
+ const {
81
+ text
82
+ } = this;
83
+ let at = 0;
84
+ while (at < text.length) {
85
+ if (at >= this.until) {
86
+ throw new Stop(this.textPlace());
87
+ }
88
+ const char = text[at];
89
+ if (char === '<') {
90
+ at = this.markup(at);
91
+ } else if (this.syntax === 'vue' && char === '{' && text[at + 1] === '{') {
92
+ at = this.skipTo(at, '}}');
93
+ } else {
94
+ at++;
95
+ }
96
+ }
97
+ }
98
+ /* Skips from `from` past `close`, the whole construct counting as something other than text. */
99
+ skipTo(from, close) {
100
+ const end = this.text.indexOf(close, from + 1);
101
+ const after = end === -1 ? this.text.length : end + close.length;
102
+ this.reached(from, end === -1 ? after : after - 1, () => ({
103
+ kind: 'other'
104
+ }));
105
+ return after;
106
+ }
107
+ markup(at) {
108
+ const {
109
+ text
110
+ } = this;
111
+ if (text.startsWith('<!--', at)) {
112
+ return this.skipTo(at, '-->');
113
+ }
114
+ if (text.startsWith('<![CDATA[', at)) {
115
+ return this.skipTo(at, ']]>');
116
+ }
117
+ if (text[at + 1] === '?') {
118
+ return this.skipTo(at, this.syntax === 'php' ? '?>' : '>');
119
+ }
120
+ if (text[at + 1] === '!') {
121
+ return this.skipTo(at, '>');
122
+ }
123
+ const closing = text[at + 1] === '/';
124
+ const nameFrom = at + (closing ? 2 : 1);
125
+ if (!NAME_START.test(text[nameFrom] ?? '')) {
126
+ return at + 1;
127
+ }
128
+ let nameTo = nameFrom;
129
+ while (nameTo < text.length && NAME.test(text[nameTo])) {
130
+ nameTo++;
131
+ }
132
+ const name = text.slice(nameFrom, nameTo);
133
+ const end = this.tagEnd(at, closing, name, nameFrom, nameTo);
134
+ if (closing) {
135
+ this.close(name, nameFrom, nameTo, {
136
+ from: at,
137
+ to: end
138
+ });
139
+ return end;
140
+ }
141
+ const selfClosing = text[end - 2] === '/' && text[end - 1] === '>';
142
+ if (selfClosing || isVoidElement(name, this.syntax)) {
143
+ return end;
144
+ }
145
+ if (this.syntax !== 'xml' && RAW_ELEMENTS.has(name.toLowerCase())) {
146
+ return this.rawContent({
147
+ from: at,
148
+ to: end
149
+ }, name, nameFrom, nameTo);
150
+ }
151
+ this.open.push({
152
+ name,
153
+ nameFrom,
154
+ nameTo,
155
+ tag: {
156
+ from: at,
157
+ to: end
158
+ }
159
+ });
160
+ return end;
161
+ }
162
+ /* Reads the attributes of a tag up to the offset after its `>`, quotes and PHP blocks included. */
163
+ tagEnd(start, closing, name, nameFrom, nameTo) {
164
+ const {
165
+ text
166
+ } = this;
167
+ let at = nameTo;
168
+ let quote = null;
169
+ let valueFrom = -1;
170
+ while (at < text.length) {
171
+ const char = text[at];
172
+ if (this.syntax === 'php' && char === '<' && text[at + 1] === '?') {
173
+ at = this.skipTo(at, '?>');
174
+ continue;
175
+ }
176
+ if (quote !== null) {
177
+ if (char === quote) {
178
+ this.reached(valueFrom, at, () => ({
179
+ kind: 'tag',
180
+ tag: {
181
+ start,
182
+ closing,
183
+ name,
184
+ nameFrom,
185
+ nameTo,
186
+ inValue: true
187
+ }
188
+ }));
189
+ quote = null;
190
+ }
191
+ } else if (char === '"' || char === "'") {
192
+ quote = char;
193
+ valueFrom = at;
194
+ } else if (char === '>') {
195
+ this.reached(start, at, () => ({
196
+ kind: 'tag',
197
+ tag: {
198
+ start,
199
+ closing,
200
+ name,
201
+ nameFrom,
202
+ nameTo,
203
+ inValue: false
204
+ }
205
+ }));
206
+ return at + 1;
207
+ } else if (char === '<') {
208
+ // A tag that never closed ends where the next one starts.
209
+ this.reached(start, at, () => ({
210
+ kind: 'tag',
211
+ tag: {
212
+ start,
213
+ closing,
214
+ name,
215
+ nameFrom,
216
+ nameTo,
217
+ inValue: false
218
+ }
219
+ }));
220
+ return at;
221
+ }
222
+ at++;
223
+ }
224
+ this.reached(start, text.length, () => ({
225
+ kind: 'tag',
226
+ tag: {
227
+ start,
228
+ closing,
229
+ name,
230
+ nameFrom,
231
+ nameTo,
232
+ inValue: quote !== null && this.until > valueFrom
233
+ }
234
+ }));
235
+ return text.length;
236
+ }
237
+ /* The content of `script`, `style` and the like is not markup, up to the end tag of the element. */
238
+ rawContent(tag, name, nameFrom, nameTo) {
239
+ const from = tag.to;
240
+ const pattern = new RegExp(`</${name}(?=[\\s/>]|$)`, 'gi');
241
+ pattern.lastIndex = from;
242
+ const match = pattern.exec(this.text);
243
+ const end = match === null ? this.text.length : match.index;
244
+ this.reached(from - 1, end, () => ({
245
+ kind: 'other'
246
+ }));
247
+ if (match === null) {
248
+ return end;
249
+ }
250
+ const closeFrom = end + 2;
251
+ const closeTo = closeFrom + name.length;
252
+ const after = this.tagEnd(end, true, this.text.slice(closeFrom, closeTo), closeFrom, closeTo);
253
+ this.pairs.push({
254
+ open: {
255
+ from: nameFrom,
256
+ to: nameTo
257
+ },
258
+ close: {
259
+ from: closeFrom,
260
+ to: closeTo
261
+ }
262
+ });
263
+ this.elements.push({
264
+ name,
265
+ open: tag,
266
+ close: {
267
+ from: end,
268
+ to: after
269
+ }
270
+ });
271
+ return after;
272
+ }
273
+ /* An end tag closes the nearest open element of its name and every element left open inside it. */
274
+ close(name, nameFrom, nameTo, tag) {
275
+ const caseless = this.syntax !== 'xml';
276
+ for (let index = this.open.length - 1; index >= 0; index--) {
277
+ const element = this.open[index];
278
+ if (element.name === name || caseless && element.name.toLowerCase() === name.toLowerCase()) {
279
+ this.pairs.push({
280
+ open: {
281
+ from: element.nameFrom,
282
+ to: element.nameTo
283
+ },
284
+ close: {
285
+ from: nameFrom,
286
+ to: nameTo
287
+ }
288
+ });
289
+ this.elements.push({
290
+ name: element.name,
291
+ open: element.tag,
292
+ close: tag
293
+ });
294
+ this.open.length = index;
295
+ return;
296
+ }
297
+ }
298
+ }
299
+ /* The elements still open at the end of the text. */
300
+ unclosed() {
301
+ return this.open.map(element => ({
302
+ name: element.name,
303
+ open: element.tag,
304
+ close: null
305
+ }));
306
+ }
307
+ }
308
+ /*
309
+ * The elements whose tags hold `offset`, innermost first: each with its start tag and its end tag, which an element left
310
+ * open does not have. Empty for a document too large to read on a keystroke.
311
+ */
312
+ export function enclosingElements(text, offset, syntax) {
313
+ if (text.length > MAX_MARKUP_SCAN) {
314
+ return [];
315
+ }
316
+ const scanner = new MarkupScanner(text, syntax, Infinity);
317
+ scanner.run();
318
+ return [...scanner.elements, ...scanner.unclosed()].filter(element => element.open.from <= offset && offset <= (element.close?.to ?? text.length)).sort((left, right) => right.open.from - left.open.from);
319
+ }
320
+ export function lineStartOf(text, offset) {
321
+ let at = offset;
322
+ while (at > 0 && text[at - 1] !== '\n' && text[at - 1] !== '\r') {
323
+ at--;
324
+ }
325
+ return at;
326
+ }
327
+ export function lineEndOf(text, offset) {
328
+ let at = offset;
329
+ while (at < text.length && text[at] !== '\n' && text[at] !== '\r') {
330
+ at++;
331
+ }
332
+ return at;
333
+ }
334
+ function breakLengthAt(text, offset) {
335
+ if (text.startsWith('\r\n', offset)) {
336
+ return 2;
337
+ }
338
+ return text[offset] === '\n' || text[offset] === '\r' ? 1 : 0;
339
+ }
340
+ /* The tag alone on its line takes the line with it, and the break before it where no break follows. */
341
+ function tagReplacement(text, tag) {
342
+ const start = lineStartOf(text, tag.from);
343
+ const end = lineEndOf(text, tag.to);
344
+ if (text.slice(start, tag.from).trim() !== '' || text.slice(tag.to, end).trim() !== '') {
345
+ return {
346
+ from: tag.from,
347
+ to: tag.to,
348
+ text: ''
349
+ };
350
+ }
351
+ const after = breakLengthAt(text, end);
352
+ const before = start > 0 && after === 0 ? text.startsWith('\r\n', start - 2) ? 2 : 1 : 0;
353
+ return {
354
+ from: start - before,
355
+ to: end + after,
356
+ text: ''
357
+ };
358
+ }
359
+ /*
360
+ * The edits that take an element's tags away and keep what is between them: each tag that stands alone on its line
361
+ * goes with its line, and when the start tag does, the lines it enclosed lose one indentation unit. The offsets are
362
+ * those of `text`, ascending and apart.
363
+ */
364
+ export function removeTagEdits(text, element, unit) {
365
+ const open = tagReplacement(text, element.open);
366
+ const edits = [open];
367
+ if (element.close === null) {
368
+ return edits;
369
+ }
370
+ const close = tagReplacement(text, element.close);
371
+ const openAlone = open.from !== element.open.from || open.to !== element.open.to;
372
+ const closeAlone = close.from !== element.close.from || close.to !== element.close.to;
373
+ const indent = unit === '\t' ? /^\t/ : new RegExp(`^ {1,${unit.length}}`);
374
+ const lastLine = lineStartOf(text, element.close.from);
375
+ let line = lineEndOf(text, element.open.to);
376
+ line += breakLengthAt(text, line);
377
+ while (openAlone && line <= lastLine && line < text.length && !(closeAlone && line === lastLine)) {
378
+ const found = indent.exec(text.slice(line, lineEndOf(text, line)));
379
+ if (found !== null) {
380
+ edits.push({
381
+ from: line,
382
+ to: line + found[0].length,
383
+ text: ''
384
+ });
385
+ }
386
+ line = lineEndOf(text, line);
387
+ line += breakLengthAt(text, line);
388
+ }
389
+ edits.push(close);
390
+ return edits;
391
+ }
392
+ /* What `offset` is in; null for a document too large to read on a keystroke. */
393
+ export function markupPlaceAt(text, offset, syntax) {
394
+ if (text.length > MAX_MARKUP_SCAN) {
395
+ return null;
396
+ }
397
+ return new MarkupScanner(text, syntax, offset).run();
398
+ }
399
+ /* The start and end tag names of the element whose name holds `offset`, either one, its edges included. */
400
+ export function tagPairAt(text, offset, syntax) {
401
+ if (text.length > MAX_MARKUP_SCAN) {
402
+ return null;
403
+ }
404
+ const scanner = new MarkupScanner(text, syntax, Infinity);
405
+ scanner.run();
406
+ const holds = range => range.from <= offset && offset <= range.to;
407
+ return scanner.pairs.find(pair => holds(pair.open) || holds(pair.close)) ?? null;
408
+ }
@@ -0,0 +1,39 @@
1
+ import type { EditorPosition } from '@adecore/editor';
2
+ import type { EditorLanguage } from './editor-language.ts';
3
+ export interface MarkupSettings {
4
+ readonly emmet?: boolean;
5
+ readonly closeTags?: boolean;
6
+ readonly linkedTags?: boolean;
7
+ }
8
+ export declare class MarkupFeature {
9
+ private readonly language;
10
+ private readonly syntax;
11
+ private settings;
12
+ private link;
13
+ private wrapping;
14
+ private revision;
15
+ private mirroring;
16
+ constructor(language: EditorLanguage);
17
+ get supported(): boolean;
18
+ configure(settings: MarkupSettings): void;
19
+ expand(): boolean;
20
+ abbreviationAt(): EditorPosition | null;
21
+ private abbreviation;
22
+ startWrap(): boolean;
23
+ submitWrap(abbreviation: string): boolean;
24
+ cancelWrap(): void;
25
+ private key;
26
+ private editable;
27
+ private indent;
28
+ private wrapTarget;
29
+ private wrapLines;
30
+ private insert;
31
+ private apply;
32
+ private edited;
33
+ private follow;
34
+ private mirror;
35
+ private closeTag;
36
+ private completeEndTag;
37
+ private moved;
38
+ private linkAtCaret;
39
+ }