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