@elice/material-exercise 1.220913.0 → 1.220920.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 (91) hide show
  1. package/cjs/components/material-exercise/MaterialExercise.styled.js +1 -1
  2. package/cjs/components/material-exercise/exercise-menu/ExerciseMenuDropdown.js +9 -1
  3. package/cjs/components/material-exercise/exercise-runner/ExerciseRunner.js +5 -1
  4. package/cjs/components/shared/monaco-editor/MonacoEditor.js +9 -9
  5. package/cjs/components/shared/monaco-editor/editor-hooks/useMonacoMarkers.js +3 -3
  6. package/cjs/components/shared/monaco-editor/editor-languages/css/index.d.ts +4 -0
  7. package/cjs/components/shared/monaco-editor/editor-languages/css/index.js +12 -0
  8. package/cjs/components/shared/monaco-editor/editor-languages/html/index.d.ts +4 -0
  9. package/cjs/components/shared/monaco-editor/editor-languages/html/index.js +10 -0
  10. package/cjs/components/shared/monaco-editor/editor-languages/index.js +2 -2
  11. package/cjs/components/shared/monaco-editor/editor-languages/typescript/index.d.ts +4 -0
  12. package/cjs/components/shared/monaco-editor/editor-languages/typescript/index.js +10 -0
  13. package/cjs/components/shared/monaco-editor/utils/emmet/abbreviationActions.d.ts +6 -0
  14. package/cjs/components/shared/monaco-editor/utils/emmet/abbreviationActions.js +65 -0
  15. package/cjs/components/shared/monaco-editor/utils/emmet/emmet.d.ts +13 -0
  16. package/cjs/components/shared/monaco-editor/utils/emmet/emmet.js +31 -0
  17. package/cjs/components/shared/monaco-editor/utils/emmet/index.d.ts +1 -0
  18. package/cjs/components/shared/monaco-editor/utils/emmet/registerProvider.d.ts +5 -0
  19. package/cjs/components/shared/monaco-editor/utils/emmet/registerProvider.js +27 -0
  20. package/cjs/components/shared/monaco-editor/utils/grammar/index.js +2 -2
  21. package/cjs/components/shared/monaco-editor/utils/prettier/index.js +6 -2
  22. package/cjs/components/shared/monaco-editor/vendors/vscode-emmet-helper/configCompat.d.ts +15 -0
  23. package/cjs/components/shared/monaco-editor/vendors/vscode-emmet-helper/configCompat.js +15 -0
  24. package/cjs/components/shared/monaco-editor/vendors/vscode-emmet-helper/data.d.ts +6 -0
  25. package/cjs/components/shared/monaco-editor/vendors/vscode-emmet-helper/data.js +22 -0
  26. package/cjs/components/shared/monaco-editor/vendors/vscode-emmet-helper/emmetHelper.d.ts +92 -0
  27. package/cjs/components/shared/monaco-editor/vendors/vscode-emmet-helper/emmetHelper.js +896 -0
  28. package/cjs/components/shared/monaco-editor/vendors/vscode-emmet-helper/index.d.ts +2 -0
  29. package/cjs/components/shared/monaco-editor/vendors/vscode-emmet-helper/utils.d.ts +17 -0
  30. package/cjs/components/shared/monaco-editor/vendors/vscode-emmet-helper/utils.js +48 -0
  31. package/cjs/components/shared/xterm/Xterm.js +10 -3
  32. package/es/components/material-exercise/MaterialExercise.styled.js +1 -1
  33. package/es/components/material-exercise/exercise-menu/ExerciseMenuDropdown.js +10 -2
  34. package/es/components/material-exercise/exercise-runner/ExerciseRunner.js +5 -1
  35. package/es/components/shared/monaco-editor/MonacoEditor.js +11 -11
  36. package/es/components/shared/monaco-editor/editor-hooks/useMonacoMarkers.js +3 -3
  37. package/es/components/shared/monaco-editor/editor-languages/css/index.d.ts +4 -0
  38. package/es/components/shared/monaco-editor/editor-languages/css/index.js +12 -1
  39. package/es/components/shared/monaco-editor/editor-languages/html/index.d.ts +4 -0
  40. package/es/components/shared/monaco-editor/editor-languages/html/index.js +10 -1
  41. package/es/components/shared/monaco-editor/editor-languages/index.js +2 -2
  42. package/es/components/shared/monaco-editor/editor-languages/typescript/index.d.ts +4 -0
  43. package/es/components/shared/monaco-editor/editor-languages/typescript/index.js +10 -1
  44. package/es/components/shared/monaco-editor/utils/emmet/abbreviationActions.d.ts +6 -0
  45. package/es/components/shared/monaco-editor/utils/emmet/abbreviationActions.js +61 -0
  46. package/es/components/shared/monaco-editor/utils/emmet/emmet.d.ts +13 -0
  47. package/es/components/shared/monaco-editor/utils/emmet/emmet.js +25 -0
  48. package/es/components/shared/monaco-editor/utils/emmet/index.d.ts +1 -0
  49. package/es/components/shared/monaco-editor/utils/emmet/registerProvider.d.ts +5 -0
  50. package/es/components/shared/monaco-editor/utils/emmet/registerProvider.js +23 -0
  51. package/es/components/shared/monaco-editor/utils/grammar/index.js +2 -2
  52. package/es/components/shared/monaco-editor/utils/prettier/index.js +6 -2
  53. package/es/components/shared/monaco-editor/vendors/vscode-emmet-helper/configCompat.d.ts +15 -0
  54. package/es/components/shared/monaco-editor/vendors/vscode-emmet-helper/configCompat.js +11 -0
  55. package/es/components/shared/monaco-editor/vendors/vscode-emmet-helper/data.d.ts +6 -0
  56. package/es/components/shared/monaco-editor/vendors/vscode-emmet-helper/data.js +17 -0
  57. package/es/components/shared/monaco-editor/vendors/vscode-emmet-helper/emmetHelper.d.ts +92 -0
  58. package/es/components/shared/monaco-editor/vendors/vscode-emmet-helper/emmetHelper.js +879 -0
  59. package/es/components/shared/monaco-editor/vendors/vscode-emmet-helper/index.d.ts +2 -0
  60. package/es/components/shared/monaco-editor/vendors/vscode-emmet-helper/utils.d.ts +17 -0
  61. package/es/components/shared/monaco-editor/vendors/vscode-emmet-helper/utils.js +42 -0
  62. package/es/components/shared/xterm/Xterm.js +10 -3
  63. package/package.json +7 -6
  64. /package/cjs/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/OnDisposed.d.ts +0 -0
  65. /package/cjs/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteCursor.d.ts +0 -0
  66. /package/cjs/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteCursor.js +0 -0
  67. /package/cjs/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteCursorManager.d.ts +0 -0
  68. /package/cjs/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteCursorManager.js +0 -0
  69. /package/cjs/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteCursorWidget.d.ts +0 -0
  70. /package/cjs/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteCursorWidget.js +0 -0
  71. /package/cjs/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteSelection.d.ts +0 -0
  72. /package/cjs/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteSelection.js +0 -0
  73. /package/cjs/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteSelectionManager.d.ts +0 -0
  74. /package/cjs/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteSelectionManager.js +0 -0
  75. /package/cjs/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/index.d.ts +0 -0
  76. /package/cjs/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/styles.d.ts +0 -0
  77. /package/cjs/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/styles.js +0 -0
  78. /package/es/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/OnDisposed.d.ts +0 -0
  79. /package/es/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteCursor.d.ts +0 -0
  80. /package/es/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteCursor.js +0 -0
  81. /package/es/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteCursorManager.d.ts +0 -0
  82. /package/es/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteCursorManager.js +0 -0
  83. /package/es/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteCursorWidget.d.ts +0 -0
  84. /package/es/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteCursorWidget.js +0 -0
  85. /package/es/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteSelection.d.ts +0 -0
  86. /package/es/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteSelection.js +0 -0
  87. /package/es/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteSelectionManager.d.ts +0 -0
  88. /package/es/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/RemoteSelectionManager.js +0 -0
  89. /package/es/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/index.d.ts +0 -0
  90. /package/es/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/styles.d.ts +0 -0
  91. /package/es/components/shared/monaco-editor/{utils/remoteMarker → vendors/monaco-collab-ext}/styles.js +0 -0
@@ -0,0 +1,879 @@
1
+ import expand, { resolveConfig, extract } from 'emmet';
2
+ import { cssData, htmlData } from './data.js';
3
+ import { syntaxes } from './configCompat.js';
4
+
5
+ /* ====================================================================================================
6
+ * These codes forked and modified from `microsoft/vscode-emmet-helper`
7
+ * under the terms of the MIT license.
8
+ * Make sure to check the original project if any issue exists.
9
+ * - project: https://github.com/microsoft/vscode-emmet-helper
10
+ * - codes: https://github.com/microsoft/vscode-emmet-helper/blob/e64481648451f0189216794979ce2ace82ee8148/src/emmetHelper.ts
11
+ * ==================================================================================================== */
12
+ // @emmetio/extract-abbreviation has a cjs that uses a default export
13
+ // */
14
+ // const extract = typeof _extractAbbreviation === 'function' ? _extractAbbreviation : _extractAbbreviation.default;
15
+
16
+ const snippetKeyCache = new Map();
17
+ let markupSnippetKeys;
18
+ const stylesheetCustomSnippetsKeyCache = new Map();
19
+ const htmlAbbreviationStartRegex = /^[a-z,A-Z,!,(,[,#,\.\{]/; // take off { for jsx because it interferes with the language
20
+
21
+ const jsxAbbreviationStartRegex = /^[a-z,A-Z,!,(,[,#,\.]/;
22
+ const cssAbbreviationRegex = /^-?[a-z,A-Z,!,@,#]/;
23
+ const htmlAbbreviationRegex = /[a-z,A-Z\.]/;
24
+ const commonlyUsedTags = [...htmlData.tags, 'lorem'];
25
+ const bemFilterSuffix = 'bem';
26
+ const filterDelimitor = '|';
27
+ const trimFilterSuffix = 't';
28
+ const commentFilterSuffix = 'c';
29
+ const maxFilters = 3;
30
+ /**
31
+ * Returns all applicable emmet expansions for abbreviation at given position in a CompletionList
32
+ */
33
+
34
+ function doComplete(_monaco, model, position, syntax, emmetConfig) {
35
+ var _a, _b;
36
+
37
+ if (emmetConfig.showExpandedAbbreviation === 'never' || !getEmmetMode(syntax, emmetConfig.excludeLanguages)) {
38
+ return;
39
+ }
40
+
41
+ const isStyleSheetRes = isStyleSheet(syntax); // Fetch markupSnippets so that we can provide possible abbreviation completions
42
+ // For example, when text at position is `a`, completions should return `a:blank`, `a:link`, `acr` etc.
43
+
44
+ if (!isStyleSheetRes) {
45
+ if (!snippetKeyCache.has(syntax)) {
46
+ const registry = (_a = customSnippetsRegistry[syntax]) !== null && _a !== void 0 ? _a : getDefaultSnippets(syntax);
47
+ snippetKeyCache.set(syntax, Object.keys(registry));
48
+ }
49
+
50
+ markupSnippetKeys = (_b = snippetKeyCache.get(syntax)) !== null && _b !== void 0 ? _b : [];
51
+ }
52
+
53
+ const extractOptions = {
54
+ lookAhead: !isStyleSheetRes,
55
+ type: isStyleSheetRes ? 'stylesheet' : 'markup'
56
+ };
57
+ const extractedValue = extractAbbreviation(_monaco, model, position, extractOptions);
58
+
59
+ if (!extractedValue) {
60
+ return;
61
+ }
62
+
63
+ const {
64
+ abbreviationRange,
65
+ abbreviation,
66
+ filter
67
+ } = extractedValue;
68
+ const currentLineTillPosition = getCurrentLine(model, position).substr(0, position.column - 1);
69
+ const currentWord = getCurrentWord(currentLineTillPosition); // Don't attempt to expand open tags
70
+
71
+ if (currentWord === abbreviation && currentLineTillPosition.endsWith(`<${abbreviation}`) && syntaxes.markup.includes(syntax)) {
72
+ return;
73
+ }
74
+
75
+ const expandOptions = getExpandOptions(syntax, emmetConfig, filter);
76
+ let expandedText = "";
77
+ let expandedAbbr;
78
+ let completionItems = []; // Create completion item after expanding given abbreviation
79
+ // if abbreviation is valid and expanded value is not noise
80
+
81
+ const createExpandedAbbr = (syntax, abbr) => {
82
+ if (!isAbbreviationValid(syntax, abbreviation)) {
83
+ return;
84
+ }
85
+
86
+ try {
87
+ expandedText = expand(abbr, expandOptions); // manually patch https://github.com/microsoft/vscode/issues/120245 for now
88
+
89
+ if (isStyleSheetRes && '!important'.startsWith(abbr)) {
90
+ expandedText = '!important';
91
+ }
92
+ } catch (e) {}
93
+
94
+ if (!expandedText || isExpandedTextNoise(syntax, abbr, expandedText, expandOptions.options)) {
95
+ return;
96
+ }
97
+
98
+ expandedAbbr = {
99
+ kind: _monaco.languages.CompletionItemKind.Property,
100
+ label: abbreviation + (filter ? '|' + filter.replace(',', '|') : ''),
101
+ documentation: replaceTabStopsWithCursors(expandedText),
102
+ detail: 'Emmet abbreviation',
103
+ insertTextRules: _monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
104
+ range: abbreviationRange,
105
+ insertText: escapeNonTabStopDollar(addFinalTabStop(expandedText))
106
+ };
107
+ completionItems = [expandedAbbr];
108
+ };
109
+
110
+ if (isStyleSheet(syntax)) {
111
+ createExpandedAbbr(syntax, abbreviation); // When abbr is longer than usual emmet snippets and matches better with existing css property, then no emmet
112
+
113
+ if (abbreviation.length > 4 && cssData.properties.find(x => x.startsWith(abbreviation))) {
114
+ return {
115
+ suggestions: [],
116
+ incomplete: true
117
+ };
118
+ }
119
+
120
+ if (expandedAbbr && expandedText.length) {
121
+ expandedAbbr.range = abbreviationRange;
122
+ expandedAbbr.insertText = escapeNonTabStopDollar(addFinalTabStop(expandedText));
123
+ expandedAbbr.documentation = replaceTabStopsWithCursors(expandedText);
124
+ expandedAbbr.label = removeTabStops(expandedText);
125
+ expandedAbbr.filterText = abbreviation; // Custom snippets should show up in completions if abbreviation is a prefix
126
+
127
+ const stylesheetCustomSnippetsKeys = stylesheetCustomSnippetsKeyCache.has(syntax) ? stylesheetCustomSnippetsKeyCache.get(syntax) : stylesheetCustomSnippetsKeyCache.get('css');
128
+ completionItems = makeSnippetSuggestion(_monaco, stylesheetCustomSnippetsKeys !== null && stylesheetCustomSnippetsKeys !== void 0 ? stylesheetCustomSnippetsKeys : [], abbreviation, abbreviation, abbreviationRange, expandOptions, 'Emmet Custom Snippet', false);
129
+
130
+ if (!completionItems.find(x => x.insertText === (expandedAbbr === null || expandedAbbr === void 0 ? void 0 : expandedAbbr.insertText))) {
131
+ // Fix for https://github.com/Microsoft/vscode/issues/28933#issuecomment-309236902
132
+ // When user types in propertyname, emmet uses it to match with snippet names, resulting in width -> widows or font-family -> font: family
133
+ // Filter out those cases here.
134
+ const abbrRegex = new RegExp('.*' + abbreviation.split('').map(x => x === '$' || x === '+' ? '\\' + x : x).join('.*') + '.*', 'i');
135
+
136
+ if (/\d/.test(abbreviation) || abbrRegex.test(expandedAbbr.label)) {
137
+ completionItems.push(expandedAbbr);
138
+ }
139
+ }
140
+ }
141
+ } else {
142
+ createExpandedAbbr(syntax, abbreviation);
143
+ let tagToFindMoreSuggestionsFor = abbreviation;
144
+ const newTagMatches = /(>|\+)([\w:-]+)$/.exec(abbreviation);
145
+
146
+ if (newTagMatches && newTagMatches.length === 3) {
147
+ tagToFindMoreSuggestionsFor = newTagMatches[2];
148
+ }
149
+
150
+ if (syntax !== 'xml') {
151
+ const commonlyUsedTagSuggestions = makeSnippetSuggestion(_monaco, commonlyUsedTags, tagToFindMoreSuggestionsFor, abbreviation, abbreviationRange, expandOptions, 'Emmet Abbreviation');
152
+ completionItems = completionItems.concat(commonlyUsedTagSuggestions);
153
+ }
154
+
155
+ if (emmetConfig.showAbbreviationSuggestions === true) {
156
+ const abbreviationSuggestions = makeSnippetSuggestion(_monaco, markupSnippetKeys.filter(x => !commonlyUsedTags.includes(x)), tagToFindMoreSuggestionsFor, abbreviation, abbreviationRange, expandOptions, 'Emmet Abbreviation'); // Workaround for the main expanded abbr not appearing before the snippet suggestions
157
+
158
+ if (expandedAbbr && abbreviationSuggestions.length > 0 && tagToFindMoreSuggestionsFor !== abbreviation) {
159
+ expandedAbbr.sortText = '0' + expandedAbbr.label;
160
+ abbreviationSuggestions.forEach(item => {
161
+ // Workaround for snippet suggestions items getting filtered out as the complete abbr does not start with snippetKey
162
+ item.filterText = abbreviation; // Workaround for the main expanded abbr not appearing before the snippet suggestions
163
+
164
+ item.sortText = '9' + abbreviation;
165
+ });
166
+ }
167
+
168
+ completionItems = completionItems.concat(abbreviationSuggestions);
169
+ } // https://github.com/microsoft/vscode/issues/66680
170
+
171
+
172
+ if (syntax === 'html' && completionItems.length >= 2 && abbreviation.includes(":") && (expandedAbbr === null || expandedAbbr === void 0 ? void 0 : expandedAbbr.insertText) === `<${abbreviation}>\${0}</${abbreviation}>`) {
173
+ completionItems = completionItems.filter(item => item.label !== abbreviation);
174
+ }
175
+ }
176
+
177
+ if (emmetConfig.showSuggestionsAsSnippets === true) {
178
+ completionItems.forEach(x => x.kind = _monaco.languages.CompletionItemKind.Snippet);
179
+ }
180
+
181
+ return completionItems.length ? {
182
+ suggestions: completionItems,
183
+ incomplete: true
184
+ } : undefined;
185
+ }
186
+ /**
187
+ * Create & return snippets for snippet keys that start with given prefix
188
+ */
189
+
190
+ function makeSnippetSuggestion(_monaco, snippetKeys, prefix, abbreviation, abbreviationRange, expandOptions, snippetDetail, skipFullMatch = true) {
191
+ if (!prefix || !snippetKeys) {
192
+ return [];
193
+ }
194
+
195
+ const snippetCompletions = [];
196
+ snippetKeys.forEach(snippetKey => {
197
+ if (!snippetKey.startsWith(prefix.toLowerCase()) || skipFullMatch && snippetKey === prefix.toLowerCase()) {
198
+ return;
199
+ }
200
+
201
+ const currentAbbr = abbreviation + snippetKey.substr(prefix.length);
202
+ let expandedAbbr;
203
+
204
+ try {
205
+ expandedAbbr = expand(currentAbbr, expandOptions);
206
+ } catch (e) {}
207
+
208
+ if (!expandedAbbr) {
209
+ return;
210
+ }
211
+
212
+ const item = {
213
+ kind: _monaco.languages.CompletionItemKind.Property,
214
+ label: prefix + snippetKey.substr(prefix.length),
215
+ documentation: replaceTabStopsWithCursors(expandedAbbr),
216
+ detail: snippetDetail,
217
+ insertTextRules: _monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
218
+ range: abbreviationRange,
219
+ insertText: escapeNonTabStopDollar(addFinalTabStop(expandedAbbr))
220
+ };
221
+ snippetCompletions.push(item);
222
+ });
223
+ return snippetCompletions;
224
+ }
225
+
226
+ function getCurrentWord(currentLineTillPosition) {
227
+ if (currentLineTillPosition) {
228
+ const matches = /[\w,:,-,\.]*$/.exec(currentLineTillPosition);
229
+
230
+ if (matches) {
231
+ return matches[0];
232
+ }
233
+ }
234
+ }
235
+
236
+ function replaceTabStopsWithCursors(expandedWord) {
237
+ return expandedWord.replace(/([^\\])\$\{\d+\}/g, '$1|').replace(/\$\{\d+:([^\}]+)\}/g, '$1');
238
+ }
239
+
240
+ function removeTabStops(expandedWord) {
241
+ return expandedWord.replace(/([^\\])\$\{\d+\}/g, '$1').replace(/\$\{\d+:([^\}]+)\}/g, '$1');
242
+ }
243
+
244
+ function escapeNonTabStopDollar(text) {
245
+ return text ? text.replace(/([^\\])(\$)([^\{])/g, '$1\\$2$3') : text;
246
+ }
247
+
248
+ function addFinalTabStop(text) {
249
+ if (!text || !text.trim()) {
250
+ return text;
251
+ }
252
+
253
+ let maxTabStop = -1;
254
+ let maxTabStopRanges = [];
255
+ let foundLastStop = false;
256
+ let replaceWithLastStop = false;
257
+ let i = 0;
258
+ const n = text.length;
259
+
260
+ try {
261
+ while (i < n && !foundLastStop) {
262
+ // Look for ${
263
+ if (text[i++] != '$' || text[i++] != '{') {
264
+ continue;
265
+ } // Find tabstop
266
+
267
+
268
+ let numberStart = -1;
269
+ let numberEnd = -1;
270
+
271
+ while (i < n && /\d/.test(text[i])) {
272
+ numberStart = numberStart < 0 ? i : numberStart;
273
+ numberEnd = i + 1;
274
+ i++;
275
+ } // If ${ was not followed by a number and either } or :, then its not a tabstop
276
+
277
+
278
+ if (numberStart === -1 || numberEnd === -1 || i >= n || text[i] != '}' && text[i] != ':') {
279
+ continue;
280
+ } // If ${0} was found, then break
281
+
282
+
283
+ const currentTabStop = text.substring(numberStart, numberEnd);
284
+ foundLastStop = currentTabStop === '0';
285
+
286
+ if (foundLastStop) {
287
+ break;
288
+ }
289
+
290
+ let foundPlaceholder = false;
291
+
292
+ if (text[i++] == ':') {
293
+ // TODO: Nested placeholders may break here
294
+ while (i < n) {
295
+ if (text[i] == '}') {
296
+ foundPlaceholder = true;
297
+ break;
298
+ }
299
+
300
+ i++;
301
+ }
302
+ } // Decide to replace currentTabStop with ${0} only if its the max among all tabstops and is not a placeholder
303
+
304
+
305
+ if (Number(currentTabStop) > Number(maxTabStop)) {
306
+ maxTabStop = Number(currentTabStop);
307
+ maxTabStopRanges = [{
308
+ numberStart,
309
+ numberEnd
310
+ }];
311
+ replaceWithLastStop = !foundPlaceholder;
312
+ } else if (Number(currentTabStop) === maxTabStop) {
313
+ maxTabStopRanges.push({
314
+ numberStart,
315
+ numberEnd
316
+ });
317
+ }
318
+ }
319
+ } catch (e) {}
320
+
321
+ if (replaceWithLastStop && !foundLastStop) {
322
+ for (let i = 0; i < maxTabStopRanges.length; i++) {
323
+ const rangeStart = maxTabStopRanges[i].numberStart;
324
+ const rangeEnd = maxTabStopRanges[i].numberEnd;
325
+ text = text.substr(0, rangeStart) + '0' + text.substr(rangeEnd);
326
+ }
327
+ }
328
+
329
+ return text;
330
+ }
331
+
332
+ function getCurrentLine(model, position) {
333
+ const currentLine = model.getLineContent(position.lineNumber);
334
+ return currentLine;
335
+ }
336
+
337
+ let customSnippetsRegistry = {};
338
+ let variablesFromFile = {};
339
+ let profilesFromFile = {};
340
+ const emmetSnippetField = (index, placeholder) => `\${${index}${placeholder ? ':' + placeholder : ''}}`;
341
+ /** Returns whether or not syntax is a supported stylesheet syntax, like CSS */
342
+
343
+ function isStyleSheet(syntax) {
344
+ return syntaxes.stylesheet.includes(syntax);
345
+ }
346
+ /** Returns the syntax type, either markup (e.g. for HTML) or stylesheet (e.g. for CSS) */
347
+
348
+ function getSyntaxType(syntax) {
349
+ return isStyleSheet(syntax) ? 'stylesheet' : 'markup';
350
+ }
351
+ /** Returns the default syntax (html or css) to use for the snippets registry */
352
+
353
+ function getDefaultSyntax(syntax) {
354
+ return isStyleSheet(syntax) ? 'css' : 'html';
355
+ }
356
+ /** Returns the default snippets that Emmet suggests */
357
+
358
+ function getDefaultSnippets(syntax) {
359
+ const syntaxType = getSyntaxType(syntax);
360
+ const emptyUserConfig = {
361
+ type: syntaxType,
362
+ syntax
363
+ };
364
+ const resolvedConfig = resolveConfig(emptyUserConfig); // https://github.com/microsoft/vscode/issues/97632
365
+ // don't return markup (HTML) snippets for XML
366
+
367
+ return syntax === 'xml' ? {} : resolvedConfig.snippets;
368
+ }
369
+
370
+ function getFilters(text, pos) {
371
+ let filter;
372
+
373
+ for (let i = 0; i < maxFilters; i++) {
374
+ if (text.endsWith(`${filterDelimitor}${bemFilterSuffix}`, pos)) {
375
+ pos -= bemFilterSuffix.length + 1;
376
+ filter = filter ? bemFilterSuffix + ',' + filter : bemFilterSuffix;
377
+ } else if (text.endsWith(`${filterDelimitor}${commentFilterSuffix}`, pos)) {
378
+ pos -= commentFilterSuffix.length + 1;
379
+ filter = filter ? commentFilterSuffix + ',' + filter : commentFilterSuffix;
380
+ } else if (text.endsWith(`${filterDelimitor}${trimFilterSuffix}`, pos)) {
381
+ pos -= trimFilterSuffix.length + 1;
382
+ filter = filter ? trimFilterSuffix + ',' + filter : trimFilterSuffix;
383
+ } else {
384
+ break;
385
+ }
386
+ }
387
+
388
+ return {
389
+ pos: pos,
390
+ filter: filter
391
+ };
392
+ }
393
+ /**
394
+ * Extracts abbreviation from the given position in the given document
395
+ */
396
+
397
+
398
+ function extractAbbreviation(_monaco, model, position, options) {
399
+ const currentLine = model.getLineContent(position.lineNumber);
400
+ const currentLineTillPosition = currentLine.substr(0, position.column - 1);
401
+ const {
402
+ pos,
403
+ filter
404
+ } = getFilters(currentLineTillPosition, position.column - 1);
405
+ const lengthOccupiedByFilter = filter ? filter.length + 1 : 0;
406
+ const result = extract(currentLine, pos, options);
407
+
408
+ if (!result) {
409
+ return;
410
+ }
411
+
412
+ const rangeToReplace = new _monaco.Range(position.lineNumber, result.location + 1, position.lineNumber, result.location + result.abbreviation.length + lengthOccupiedByFilter + 1);
413
+ return {
414
+ abbreviationRange: rangeToReplace,
415
+ abbreviation: result.abbreviation,
416
+ filter
417
+ };
418
+ }
419
+ /**
420
+ * Returns a boolean denoting validity of given abbreviation in the context of given syntax
421
+ * Not needed once https://github.com/emmetio/atom-plugin/issues/22 is fixed
422
+ * @param syntax string
423
+ * @param abbreviation string
424
+ */
425
+
426
+ function isAbbreviationValid(syntax, abbreviation) {
427
+ if (!abbreviation) {
428
+ return false;
429
+ }
430
+
431
+ if (isStyleSheet(syntax)) {
432
+ if (abbreviation.includes('#')) {
433
+ if (abbreviation.startsWith('#')) {
434
+ const hexColorRegex = /^#[\d,a-f,A-F]{1,6}$/;
435
+ return hexColorRegex.test(abbreviation);
436
+ } else if (commonlyUsedTags.includes(abbreviation.substring(0, abbreviation.indexOf('#')))) {
437
+ return false;
438
+ }
439
+ }
440
+
441
+ return cssAbbreviationRegex.test(abbreviation);
442
+ }
443
+
444
+ if (abbreviation.startsWith('!')) {
445
+ return !/[^!]/.test(abbreviation);
446
+ } // Its common for users to type (sometextinsidebrackets), this should not be treated as an abbreviation
447
+ // Grouping in abbreviation is valid only if it's inside a text node or preceeded/succeeded with one of the symbols for nesting, sibling, repeater or climb up
448
+
449
+
450
+ if ((/\(/.test(abbreviation) || /\)/.test(abbreviation)) && !/\{[^\}\{]*[\(\)]+[^\}\{]*\}(?:[>\+\*\^]|$)/.test(abbreviation) && !/\(.*\)[>\+\*\^]/.test(abbreviation) && !/[>\+\*\^]\(.*\)/.test(abbreviation)) {
451
+ return false;
452
+ }
453
+
454
+ if (syntax === 'jsx') {
455
+ return jsxAbbreviationStartRegex.test(abbreviation) && htmlAbbreviationRegex.test(abbreviation);
456
+ }
457
+
458
+ return htmlAbbreviationStartRegex.test(abbreviation) && htmlAbbreviationRegex.test(abbreviation);
459
+ }
460
+
461
+ function isExpandedTextNoise(syntax, abbreviation, expandedText, options) {
462
+ var _a, _b; // Unresolved css abbreviations get expanded to a blank property value
463
+ // Eg: abc -> abc: ; or abc:d -> abc: d; which is noise if it gets suggested for every word typed
464
+
465
+
466
+ if (isStyleSheet(syntax) && options) {
467
+ const between = (_a = options['stylesheet.between']) !== null && _a !== void 0 ? _a : ': ';
468
+ const after = (_b = options['stylesheet.after']) !== null && _b !== void 0 ? _b : ';'; // Remove overlapping between `abbreviation` and `between`, if any
469
+
470
+ let endPrefixIndex = abbreviation.indexOf(between[0], Math.max(abbreviation.length - between.length, 0));
471
+ endPrefixIndex = endPrefixIndex >= 0 ? endPrefixIndex : abbreviation.length;
472
+ const abbr = abbreviation.substring(0, endPrefixIndex);
473
+ return expandedText === `${abbr}${between}\${0}${after}` || expandedText.replace(/\s/g, '') === abbreviation.replace(/\s/g, '') + after;
474
+ } // we don't want common html tags suggested for xml
475
+
476
+
477
+ if (syntax === 'xml' && commonlyUsedTags.some(tag => tag.startsWith(abbreviation.toLowerCase()))) {
478
+ return true;
479
+ }
480
+
481
+ if (commonlyUsedTags.includes(abbreviation.toLowerCase()) || markupSnippetKeys.includes(abbreviation)) {
482
+ return false;
483
+ } // Custom tags can have - or :
484
+
485
+
486
+ if (/[-,:]/.test(abbreviation) && !/--|::/.test(abbreviation) && !abbreviation.endsWith(':')) {
487
+ return false;
488
+ } // Its common for users to type some text and end it with period, this should not be treated as an abbreviation
489
+ // Else it becomes noise.
490
+ // When user just types '.', return the expansion
491
+ // Otherwise emmet loses change to participate later
492
+ // For example in `.foo`. See https://github.com/Microsoft/vscode/issues/66013
493
+
494
+
495
+ if (abbreviation === '.') {
496
+ return false;
497
+ }
498
+
499
+ const dotMatches = /^([a-z,A-Z,\d]*)\.$/.exec(abbreviation);
500
+
501
+ if (dotMatches) {
502
+ // Valid html tags such as `div.`
503
+ if (dotMatches[1] && htmlData.tags.includes(dotMatches[1])) {
504
+ return false;
505
+ }
506
+
507
+ return true;
508
+ } // Fix for https://github.com/microsoft/vscode/issues/89746
509
+ // PascalCase tags are common in jsx code, which should not be treated as noise.
510
+ // Eg: MyAwesomComponent -> <MyAwesomComponent></MyAwesomComponent>
511
+
512
+
513
+ if (syntax === 'jsx' && /^([A-Z][A-Za-z0-9]*)+$/.test(abbreviation)) {
514
+ return false;
515
+ } // Unresolved html abbreviations get expanded as if it were a tag
516
+ // Eg: abc -> <abc></abc> which is noise if it gets suggested for every word typed
517
+
518
+
519
+ return expandedText.toLowerCase() === `<${abbreviation.toLowerCase()}>\${1}</${abbreviation.toLowerCase()}>`;
520
+ }
521
+ /**
522
+ * Returns options to be used by emmet
523
+ */
524
+
525
+
526
+ function getExpandOptions(syntax, emmetConfig, filter) {
527
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
528
+
529
+ emmetConfig = emmetConfig !== null && emmetConfig !== void 0 ? emmetConfig : {};
530
+ emmetConfig['preferences'] = (_a = emmetConfig['preferences']) !== null && _a !== void 0 ? _a : {};
531
+ const preferences = emmetConfig['preferences'];
532
+ const stylesheetSyntax = isStyleSheet(syntax) ? syntax : 'css'; // Fetch Profile
533
+
534
+ const profile = getProfile(syntax, (_b = emmetConfig['syntaxProfiles']) !== null && _b !== void 0 ? _b : {});
535
+ const filtersFromProfile = profile && profile['filters'] ? profile['filters'].split(',') : [];
536
+ const trimmedFilters = filtersFromProfile.map(filterFromProfile => filterFromProfile.trim());
537
+ const bemEnabled = filter && filter.split(',').some(x => x.trim() === 'bem') || trimmedFilters.includes('bem');
538
+ const commentEnabled = filter && filter.split(',').some(x => x.trim() === 'c') || trimmedFilters.includes('c'); // Fetch formatters
539
+
540
+ const formatters = getFormatters(syntax, emmetConfig['preferences']);
541
+ const unitAliases = (formatters === null || formatters === void 0 ? void 0 : formatters.stylesheet) && formatters.stylesheet['unitAliases'] || {}; // These options are the default values provided by vscode for
542
+ // extension preferences
543
+
544
+ const defaultVSCodeOptions = {
545
+ // inlineElements: string[],
546
+ // 'output.indent': string,
547
+ // 'output.baseIndent': string,
548
+ // 'output.newline': string,
549
+ // 'output.tagCase': profile['tagCase'],
550
+ // 'output.attributeCase': profile['attributeCase'],
551
+ // 'output.attributeQuotes': profile['attributeQuotes'],
552
+ // 'output.format': profile['format'] ?? true,
553
+ // 'output.formatLeafNode': boolean,
554
+ 'output.formatSkip': ['html'],
555
+ 'output.formatForce': ['body'],
556
+ 'output.inlineBreak': 0,
557
+ 'output.compactBoolean': false,
558
+ // 'output.booleanAttributes': string[],
559
+ 'output.reverseAttributes': false,
560
+ // 'output.selfClosingStyle': profile['selfClosingStyle'],
561
+ 'output.field': emmetSnippetField,
562
+ // 'output.text': TextOutput,
563
+ 'markup.href': true,
564
+ 'comment.enabled': false,
565
+ 'comment.trigger': ['id', 'class'],
566
+ 'comment.before': '',
567
+ 'comment.after': '\n<!-- /[#ID][.CLASS] -->',
568
+ 'bem.enabled': false,
569
+ 'bem.element': '__',
570
+ 'bem.modifier': '_',
571
+ 'jsx.enabled': syntax === 'jsx',
572
+ // 'stylesheet.keywords': string[],
573
+ // 'stylesheet.unitless': string[],
574
+ 'stylesheet.shortHex': true,
575
+ 'stylesheet.between': syntax === 'stylus' ? ' ' : ': ',
576
+ 'stylesheet.after': syntax === 'sass' || syntax === 'stylus' ? '' : ';',
577
+ 'stylesheet.intUnit': 'px',
578
+ 'stylesheet.floatUnit': 'em',
579
+ 'stylesheet.unitAliases': {
580
+ e: 'em',
581
+ p: '%',
582
+ x: 'ex',
583
+ r: 'rem'
584
+ },
585
+ // 'stylesheet.json': boolean,
586
+ // 'stylesheet.jsonDoubleQuotes': boolean,
587
+ 'stylesheet.fuzzySearchMinScore': 0.3
588
+ }; // These options come from user prefs in the vscode repo
589
+
590
+ const userPreferenceOptions = {
591
+ // inlineElements: string[],
592
+ // 'output.indent': string,
593
+ // 'output.baseIndent': string,
594
+ // 'output.newline': string,
595
+ 'output.tagCase': profile['tagCase'],
596
+ 'output.attributeCase': profile['attributeCase'],
597
+ 'output.attributeQuotes': profile['attributeQuotes'],
598
+ 'output.format': (_c = profile['format']) !== null && _c !== void 0 ? _c : true,
599
+ // 'output.formatLeafNode': boolean,
600
+ 'output.formatSkip': preferences['format.noIndentTags'],
601
+ 'output.formatForce': preferences['format.forceIndentationForTags'],
602
+ 'output.inlineBreak': (_d = profile['inlineBreak']) !== null && _d !== void 0 ? _d : preferences['output.inlineBreak'],
603
+ 'output.compactBoolean': (_e = profile['compactBooleanAttributes']) !== null && _e !== void 0 ? _e : preferences['profile.allowCompactBoolean'],
604
+ // 'output.booleanAttributes': string[],
605
+ 'output.reverseAttributes': preferences['output.reverseAttributes'],
606
+ 'output.selfClosingStyle': (_g = (_f = profile['selfClosingStyle']) !== null && _f !== void 0 ? _f : preferences['output.selfClosingStyle']) !== null && _g !== void 0 ? _g : getClosingStyle(syntax),
607
+ 'output.field': emmetSnippetField,
608
+ // 'output.text': TextOutput,
609
+ // 'markup.href': boolean,
610
+ 'comment.enabled': commentEnabled,
611
+ 'comment.trigger': preferences['filter.commentTrigger'],
612
+ 'comment.before': preferences['filter.commentBefore'],
613
+ 'comment.after': preferences['filter.commentAfter'],
614
+ 'bem.enabled': bemEnabled,
615
+ 'bem.element': (_h = preferences['bem.elementSeparator']) !== null && _h !== void 0 ? _h : '__',
616
+ 'bem.modifier': (_j = preferences['bem.modifierSeparator']) !== null && _j !== void 0 ? _j : '_',
617
+ 'jsx.enabled': syntax === 'jsx',
618
+ // 'stylesheet.keywords': string[],
619
+ // 'stylesheet.unitless': string[],
620
+ 'stylesheet.shortHex': preferences['css.color.short'],
621
+ 'stylesheet.between': preferences[`${stylesheetSyntax}.valueSeparator`],
622
+ 'stylesheet.after': preferences[`${stylesheetSyntax}.propertyEnd`],
623
+ 'stylesheet.intUnit': preferences['css.intUnit'],
624
+ 'stylesheet.floatUnit': preferences['css.floatUnit'],
625
+ 'stylesheet.unitAliases': unitAliases,
626
+ // 'stylesheet.json': boolean,
627
+ // 'stylesheet.jsonDoubleQuotes': boolean,
628
+ 'stylesheet.fuzzySearchMinScore': preferences['css.fuzzySearchMinScore']
629
+ };
630
+ const combinedOptions = {};
631
+ [...Object.keys(defaultVSCodeOptions), ...Object.keys(userPreferenceOptions)].forEach(key => {
632
+ var _a;
633
+
634
+ const castKey = key;
635
+ combinedOptions[castKey] = (_a = userPreferenceOptions[castKey]) !== null && _a !== void 0 ? _a : defaultVSCodeOptions[castKey];
636
+ });
637
+ const mergedAliases = Object.assign(Object.assign({}, defaultVSCodeOptions['stylesheet.unitAliases']), userPreferenceOptions['stylesheet.unitAliases']);
638
+ combinedOptions['stylesheet.unitAliases'] = mergedAliases;
639
+ const type = getSyntaxType(syntax);
640
+ const variables = getVariables(emmetConfig['variables']);
641
+ const baseSyntax = getDefaultSyntax(syntax);
642
+ const snippets = type === 'stylesheet' ? (_k = customSnippetsRegistry[syntax]) !== null && _k !== void 0 ? _k : customSnippetsRegistry[baseSyntax] : customSnippetsRegistry[syntax];
643
+ return {
644
+ type,
645
+ options: combinedOptions,
646
+ variables,
647
+ snippets,
648
+ syntax,
649
+ // context: null,
650
+ text: undefined,
651
+ maxRepeat: 1000 // cache: null
652
+
653
+ };
654
+ }
655
+
656
+ function getClosingStyle(syntax) {
657
+ switch (syntax) {
658
+ case 'xhtml':
659
+ return 'xhtml';
660
+
661
+ case 'xml':
662
+ return 'xml';
663
+
664
+ case 'xsl':
665
+ return 'xml';
666
+
667
+ case 'jsx':
668
+ return 'xhtml';
669
+
670
+ default:
671
+ return 'html';
672
+ }
673
+ }
674
+ /**
675
+ * Maps and returns syntaxProfiles of previous format to ones compatible with new emmet modules
676
+ * @param syntax
677
+ */
678
+
679
+ function getProfile(syntax, profilesFromSettings) {
680
+ if (!profilesFromSettings) {
681
+ profilesFromSettings = {};
682
+ }
683
+
684
+ const profilesConfig = Object.assign({}, profilesFromFile, profilesFromSettings);
685
+ const options = profilesConfig[syntax];
686
+
687
+ if (!options || typeof options === 'string') {
688
+ if (options === 'xhtml') {
689
+ return {
690
+ selfClosingStyle: 'xhtml'
691
+ };
692
+ }
693
+
694
+ return {};
695
+ }
696
+
697
+ const newOptions = {};
698
+
699
+ for (const key in options) {
700
+ switch (key) {
701
+ case 'tag_case':
702
+ newOptions['tagCase'] = options[key] === 'lower' || options[key] === 'upper' ? options[key] : '';
703
+ break;
704
+
705
+ case 'attr_case':
706
+ newOptions['attributeCase'] = options[key] === 'lower' || options[key] === 'upper' ? options[key] : '';
707
+ break;
708
+
709
+ case 'attr_quotes':
710
+ newOptions['attributeQuotes'] = options[key];
711
+ break;
712
+
713
+ case 'tag_nl':
714
+ newOptions['format'] = options[key] === true || options[key] === false ? options[key] : true;
715
+ break;
716
+
717
+ case 'inline_break':
718
+ newOptions['inlineBreak'] = options[key];
719
+ break;
720
+
721
+ case 'self_closing_tag':
722
+ if (options[key] === true) {
723
+ newOptions['selfClosingStyle'] = 'xml';
724
+ break;
725
+ }
726
+
727
+ if (options[key] === false) {
728
+ newOptions['selfClosingStyle'] = 'html';
729
+ break;
730
+ }
731
+
732
+ newOptions['selfClosingStyle'] = options[key];
733
+ break;
734
+
735
+ case 'compact_bool':
736
+ newOptions['compactBooleanAttributes'] = options[key];
737
+ break;
738
+
739
+ default:
740
+ newOptions[key] = options[key];
741
+ break;
742
+ }
743
+ }
744
+
745
+ return newOptions;
746
+ }
747
+ /**
748
+ * Returns variables to be used while expanding snippets
749
+ */
750
+
751
+
752
+ function getVariables(variablesFromSettings) {
753
+ if (!variablesFromSettings) {
754
+ return variablesFromFile;
755
+ }
756
+
757
+ return Object.assign({}, variablesFromFile, variablesFromSettings);
758
+ }
759
+
760
+ function getFormatters(syntax, preferences) {
761
+ if (!preferences || typeof preferences !== 'object') {
762
+ return {};
763
+ }
764
+
765
+ if (!isStyleSheet(syntax)) {
766
+ const commentFormatter = {};
767
+
768
+ for (const key in preferences) {
769
+ switch (key) {
770
+ case 'filter.commentAfter':
771
+ commentFormatter['after'] = preferences[key];
772
+ break;
773
+
774
+ case 'filter.commentBefore':
775
+ commentFormatter['before'] = preferences[key];
776
+ break;
777
+
778
+ case 'filter.commentTrigger':
779
+ commentFormatter['trigger'] = preferences[key];
780
+ break;
781
+ }
782
+ }
783
+
784
+ return {
785
+ comment: commentFormatter
786
+ };
787
+ }
788
+
789
+ let fuzzySearchMinScore = typeof (preferences === null || preferences === void 0 ? void 0 : preferences['css.fuzzySearchMinScore']) === 'number' ? preferences['css.fuzzySearchMinScore'] : 0.3;
790
+
791
+ if (fuzzySearchMinScore > 1) {
792
+ fuzzySearchMinScore = 1;
793
+ } else if (fuzzySearchMinScore < 0) {
794
+ fuzzySearchMinScore = 0;
795
+ }
796
+
797
+ const stylesheetFormatter = {
798
+ 'fuzzySearchMinScore': fuzzySearchMinScore
799
+ };
800
+
801
+ for (const key in preferences) {
802
+ switch (key) {
803
+ case 'css.floatUnit':
804
+ stylesheetFormatter['floatUnit'] = preferences[key];
805
+ break;
806
+
807
+ case 'css.intUnit':
808
+ stylesheetFormatter['intUnit'] = preferences[key];
809
+ break;
810
+
811
+ case 'css.unitAliases':
812
+ const unitAliases = {};
813
+ preferences[key].split(',').forEach(alias => {
814
+ if (!alias || !alias.trim() || !alias.includes(':')) {
815
+ return;
816
+ }
817
+
818
+ const aliasName = alias.substr(0, alias.indexOf(':'));
819
+ const aliasValue = alias.substr(aliasName.length + 1);
820
+
821
+ if (!aliasName.trim() || !aliasValue) {
822
+ return;
823
+ }
824
+
825
+ unitAliases[aliasName.trim()] = aliasValue;
826
+ });
827
+ stylesheetFormatter['unitAliases'] = unitAliases;
828
+ break;
829
+
830
+ case `${syntax}.valueSeparator`:
831
+ stylesheetFormatter['between'] = preferences[key];
832
+ break;
833
+
834
+ case `${syntax}.propertyEnd`:
835
+ stylesheetFormatter['after'] = preferences[key];
836
+ break;
837
+ }
838
+ }
839
+
840
+ return {
841
+ stylesheet: stylesheetFormatter
842
+ };
843
+ }
844
+ /**
845
+ * Get the corresponding emmet mode for given vscode language mode
846
+ * Eg: jsx for typescriptreact/javascriptreact or pug for jade
847
+ * If the language is not supported by emmet or has been exlcuded via `exlcudeLanguages` setting,
848
+ * then nothing is returned
849
+ *
850
+ * @param language
851
+ * @param exlcudedLanguages Array of language ids that user has chosen to exlcude for emmet
852
+ */
853
+
854
+
855
+ function getEmmetMode(language, excludedLanguages = []) {
856
+ if (!language || excludedLanguages.includes(language)) {
857
+ return;
858
+ }
859
+
860
+ if (/\b(typescriptreact|javascriptreact|jsx-tags)\b/.test(language)) {
861
+ // treat tsx like jsx
862
+ return 'jsx';
863
+ }
864
+
865
+ if (language === 'sass-indented') {
866
+ // map sass-indented to sass
867
+ return 'sass';
868
+ }
869
+
870
+ if (language === 'jade') {
871
+ return 'pug';
872
+ }
873
+
874
+ if (syntaxes.markup.includes(language) || syntaxes.stylesheet.includes(language)) {
875
+ return language;
876
+ }
877
+ }
878
+
879
+ export { doComplete, emmetSnippetField, extractAbbreviation, getDefaultSnippets, getDefaultSyntax, getEmmetMode, getExpandOptions, getSyntaxType, isAbbreviationValid, isStyleSheet };