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