vscode-css-languageservice 5.4.2 → 6.0.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 (84) hide show
  1. package/CHANGELOG.md +5 -1
  2. package/lib/esm/cssLanguageService.d.ts +37 -37
  3. package/lib/esm/cssLanguageService.js +72 -75
  4. package/lib/esm/cssLanguageTypes.d.ts +238 -238
  5. package/lib/esm/cssLanguageTypes.js +42 -42
  6. package/lib/esm/data/webCustomData.js +21965 -21965
  7. package/lib/esm/languageFacts/builtinData.js +142 -142
  8. package/lib/esm/languageFacts/colors.js +469 -472
  9. package/lib/esm/languageFacts/dataManager.js +88 -92
  10. package/lib/esm/languageFacts/dataProvider.js +73 -79
  11. package/lib/esm/languageFacts/entry.js +137 -138
  12. package/lib/esm/languageFacts/facts.js +8 -8
  13. package/lib/esm/parser/cssErrors.js +48 -50
  14. package/lib/esm/parser/cssNodes.js +1502 -2019
  15. package/lib/esm/parser/cssParser.js +1534 -1563
  16. package/lib/esm/parser/cssScanner.js +592 -599
  17. package/lib/esm/parser/cssSymbolScope.js +311 -341
  18. package/lib/esm/parser/lessParser.js +714 -740
  19. package/lib/esm/parser/lessScanner.js +57 -78
  20. package/lib/esm/parser/scssErrors.js +18 -20
  21. package/lib/esm/parser/scssParser.js +796 -818
  22. package/lib/esm/parser/scssScanner.js +95 -116
  23. package/lib/esm/services/cssCodeActions.js +77 -81
  24. package/lib/esm/services/cssCompletion.js +1054 -1149
  25. package/lib/esm/services/cssFolding.js +190 -193
  26. package/lib/esm/services/cssFormatter.js +136 -136
  27. package/lib/esm/services/cssHover.js +148 -151
  28. package/lib/esm/services/cssNavigation.js +378 -470
  29. package/lib/esm/services/cssSelectionRange.js +47 -47
  30. package/lib/esm/services/cssValidation.js +41 -44
  31. package/lib/esm/services/lessCompletion.js +378 -397
  32. package/lib/esm/services/lint.js +518 -532
  33. package/lib/esm/services/lintRules.js +76 -83
  34. package/lib/esm/services/lintUtil.js +196 -205
  35. package/lib/esm/services/pathCompletion.js +157 -231
  36. package/lib/esm/services/scssCompletion.js +354 -378
  37. package/lib/esm/services/scssNavigation.js +82 -154
  38. package/lib/esm/services/selectorPrinting.js +492 -536
  39. package/lib/esm/utils/arrays.js +40 -46
  40. package/lib/esm/utils/objects.js +11 -11
  41. package/lib/esm/utils/resources.js +11 -24
  42. package/lib/esm/utils/strings.js +102 -104
  43. package/lib/umd/cssLanguageService.d.ts +37 -37
  44. package/lib/umd/cssLanguageService.js +99 -102
  45. package/lib/umd/cssLanguageTypes.d.ts +238 -238
  46. package/lib/umd/cssLanguageTypes.js +89 -88
  47. package/lib/umd/data/webCustomData.js +21978 -21978
  48. package/lib/umd/languageFacts/builtinData.js +154 -154
  49. package/lib/umd/languageFacts/colors.js +492 -495
  50. package/lib/umd/languageFacts/dataManager.js +101 -104
  51. package/lib/umd/languageFacts/dataProvider.js +86 -91
  52. package/lib/umd/languageFacts/entry.js +152 -153
  53. package/lib/umd/languageFacts/facts.js +29 -29
  54. package/lib/umd/parser/cssErrors.js +61 -62
  55. package/lib/umd/parser/cssNodes.js +1587 -2034
  56. package/lib/umd/parser/cssParser.js +1547 -1575
  57. package/lib/umd/parser/cssScanner.js +606 -611
  58. package/lib/umd/parser/cssSymbolScope.js +328 -353
  59. package/lib/umd/parser/lessParser.js +727 -752
  60. package/lib/umd/parser/lessScanner.js +70 -90
  61. package/lib/umd/parser/scssErrors.js +31 -32
  62. package/lib/umd/parser/scssParser.js +809 -830
  63. package/lib/umd/parser/scssScanner.js +108 -128
  64. package/lib/umd/services/cssCodeActions.js +90 -93
  65. package/lib/umd/services/cssCompletion.js +1067 -1161
  66. package/lib/umd/services/cssFolding.js +203 -206
  67. package/lib/umd/services/cssFormatter.js +150 -150
  68. package/lib/umd/services/cssHover.js +161 -163
  69. package/lib/umd/services/cssNavigation.js +391 -482
  70. package/lib/umd/services/cssSelectionRange.js +60 -60
  71. package/lib/umd/services/cssValidation.js +54 -56
  72. package/lib/umd/services/lessCompletion.js +391 -409
  73. package/lib/umd/services/lint.js +531 -544
  74. package/lib/umd/services/lintRules.js +91 -95
  75. package/lib/umd/services/lintUtil.js +210 -218
  76. package/lib/umd/services/pathCompletion.js +171 -244
  77. package/lib/umd/services/scssCompletion.js +367 -390
  78. package/lib/umd/services/scssNavigation.js +95 -166
  79. package/lib/umd/services/selectorPrinting.js +510 -550
  80. package/lib/umd/utils/arrays.js +55 -61
  81. package/lib/umd/utils/objects.js +25 -25
  82. package/lib/umd/utils/resources.js +26 -39
  83. package/lib/umd/utils/strings.js +120 -122
  84. package/package.json +10 -10
@@ -1,470 +1,378 @@
1
- /*---------------------------------------------------------------------------------------------
2
- * Copyright (c) Microsoft Corporation. All rights reserved.
3
- * Licensed under the MIT License. See License.txt in the project root for license information.
4
- *--------------------------------------------------------------------------------------------*/
5
- 'use strict';
6
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
7
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
8
- return new (P || (P = Promise))(function (resolve, reject) {
9
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
10
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
11
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
12
- step((generator = generator.apply(thisArg, _arguments || [])).next());
13
- });
14
- };
15
- var __generator = (this && this.__generator) || function (thisArg, body) {
16
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
17
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
18
- function verb(n) { return function (v) { return step([n, v]); }; }
19
- function step(op) {
20
- if (f) throw new TypeError("Generator is already executing.");
21
- while (_) try {
22
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
23
- if (y = 0, t) op = [op[0] & 2, t.value];
24
- switch (op[0]) {
25
- case 0: case 1: t = op; break;
26
- case 4: _.label++; return { value: op[1], done: false };
27
- case 5: _.label++; y = op[1]; op = [0]; continue;
28
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
29
- default:
30
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
31
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
32
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
33
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
34
- if (t[2]) _.ops.pop();
35
- _.trys.pop(); continue;
36
- }
37
- op = body.call(thisArg, _);
38
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
39
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
40
- }
41
- };
42
- import { DocumentHighlightKind, Location, Range, SymbolKind, TextEdit, FileType } from '../cssLanguageTypes';
43
- import * as nls from 'vscode-nls';
44
- import * as nodes from '../parser/cssNodes';
45
- import { Symbols } from '../parser/cssSymbolScope';
46
- import { getColorValue, hslFromColor, hwbFromColor } from '../languageFacts/facts';
47
- import { startsWith } from '../utils/strings';
48
- import { dirname, joinPath } from '../utils/resources';
49
- var localize = nls.loadMessageBundle();
50
- var startsWithSchemeRegex = /^\w+:\/\//;
51
- var startsWithData = /^data:/;
52
- var CSSNavigation = /** @class */ (function () {
53
- function CSSNavigation(fileSystemProvider, resolveModuleReferences) {
54
- this.fileSystemProvider = fileSystemProvider;
55
- this.resolveModuleReferences = resolveModuleReferences;
56
- }
57
- CSSNavigation.prototype.findDefinition = function (document, position, stylesheet) {
58
- var symbols = new Symbols(stylesheet);
59
- var offset = document.offsetAt(position);
60
- var node = nodes.getNodeAtOffset(stylesheet, offset);
61
- if (!node) {
62
- return null;
63
- }
64
- var symbol = symbols.findSymbolFromNode(node);
65
- if (!symbol) {
66
- return null;
67
- }
68
- return {
69
- uri: document.uri,
70
- range: getRange(symbol.node, document)
71
- };
72
- };
73
- CSSNavigation.prototype.findReferences = function (document, position, stylesheet) {
74
- var highlights = this.findDocumentHighlights(document, position, stylesheet);
75
- return highlights.map(function (h) {
76
- return {
77
- uri: document.uri,
78
- range: h.range
79
- };
80
- });
81
- };
82
- CSSNavigation.prototype.findDocumentHighlights = function (document, position, stylesheet) {
83
- var result = [];
84
- var offset = document.offsetAt(position);
85
- var node = nodes.getNodeAtOffset(stylesheet, offset);
86
- if (!node || node.type === nodes.NodeType.Stylesheet || node.type === nodes.NodeType.Declarations) {
87
- return result;
88
- }
89
- if (node.type === nodes.NodeType.Identifier && node.parent && node.parent.type === nodes.NodeType.ClassSelector) {
90
- node = node.parent;
91
- }
92
- var symbols = new Symbols(stylesheet);
93
- var symbol = symbols.findSymbolFromNode(node);
94
- var name = node.getText();
95
- stylesheet.accept(function (candidate) {
96
- if (symbol) {
97
- if (symbols.matchesSymbol(candidate, symbol)) {
98
- result.push({
99
- kind: getHighlightKind(candidate),
100
- range: getRange(candidate, document)
101
- });
102
- return false;
103
- }
104
- }
105
- else if (node && node.type === candidate.type && candidate.matches(name)) {
106
- // Same node type and data
107
- result.push({
108
- kind: getHighlightKind(candidate),
109
- range: getRange(candidate, document)
110
- });
111
- }
112
- return true;
113
- });
114
- return result;
115
- };
116
- CSSNavigation.prototype.isRawStringDocumentLinkNode = function (node) {
117
- return node.type === nodes.NodeType.Import;
118
- };
119
- CSSNavigation.prototype.findDocumentLinks = function (document, stylesheet, documentContext) {
120
- var linkData = this.findUnresolvedLinks(document, stylesheet);
121
- var resolvedLinks = [];
122
- for (var _i = 0, linkData_1 = linkData; _i < linkData_1.length; _i++) {
123
- var data = linkData_1[_i];
124
- var link = data.link;
125
- var target = link.target;
126
- if (!target || startsWithData.test(target)) {
127
- // no links for data:
128
- }
129
- else if (startsWithSchemeRegex.test(target)) {
130
- resolvedLinks.push(link);
131
- }
132
- else {
133
- var resolved = documentContext.resolveReference(target, document.uri);
134
- if (resolved) {
135
- link.target = resolved;
136
- }
137
- resolvedLinks.push(link);
138
- }
139
- }
140
- return resolvedLinks;
141
- };
142
- CSSNavigation.prototype.findDocumentLinks2 = function (document, stylesheet, documentContext) {
143
- return __awaiter(this, void 0, void 0, function () {
144
- var linkData, resolvedLinks, _i, linkData_2, data, link, target, resolvedTarget;
145
- return __generator(this, function (_a) {
146
- switch (_a.label) {
147
- case 0:
148
- linkData = this.findUnresolvedLinks(document, stylesheet);
149
- resolvedLinks = [];
150
- _i = 0, linkData_2 = linkData;
151
- _a.label = 1;
152
- case 1:
153
- if (!(_i < linkData_2.length)) return [3 /*break*/, 6];
154
- data = linkData_2[_i];
155
- link = data.link;
156
- target = link.target;
157
- if (!(!target || startsWithData.test(target))) return [3 /*break*/, 2];
158
- return [3 /*break*/, 5];
159
- case 2:
160
- if (!startsWithSchemeRegex.test(target)) return [3 /*break*/, 3];
161
- resolvedLinks.push(link);
162
- return [3 /*break*/, 5];
163
- case 3: return [4 /*yield*/, this.resolveRelativeReference(target, document.uri, documentContext, data.isRawLink)];
164
- case 4:
165
- resolvedTarget = _a.sent();
166
- if (resolvedTarget !== undefined) {
167
- link.target = resolvedTarget;
168
- resolvedLinks.push(link);
169
- }
170
- _a.label = 5;
171
- case 5:
172
- _i++;
173
- return [3 /*break*/, 1];
174
- case 6: return [2 /*return*/, resolvedLinks];
175
- }
176
- });
177
- });
178
- };
179
- CSSNavigation.prototype.findUnresolvedLinks = function (document, stylesheet) {
180
- var _this = this;
181
- var result = [];
182
- var collect = function (uriStringNode) {
183
- var rawUri = uriStringNode.getText();
184
- var range = getRange(uriStringNode, document);
185
- // Make sure the range is not empty
186
- if (range.start.line === range.end.line && range.start.character === range.end.character) {
187
- return;
188
- }
189
- if (startsWith(rawUri, "'") || startsWith(rawUri, "\"")) {
190
- rawUri = rawUri.slice(1, -1);
191
- }
192
- var isRawLink = uriStringNode.parent ? _this.isRawStringDocumentLinkNode(uriStringNode.parent) : false;
193
- result.push({ link: { target: rawUri, range: range }, isRawLink: isRawLink });
194
- };
195
- stylesheet.accept(function (candidate) {
196
- if (candidate.type === nodes.NodeType.URILiteral) {
197
- var first = candidate.getChild(0);
198
- if (first) {
199
- collect(first);
200
- }
201
- return false;
202
- }
203
- /**
204
- * In @import, it is possible to include links that do not use `url()`
205
- * For example, `@import 'foo.css';`
206
- */
207
- if (candidate.parent && _this.isRawStringDocumentLinkNode(candidate.parent)) {
208
- var rawText = candidate.getText();
209
- if (startsWith(rawText, "'") || startsWith(rawText, "\"")) {
210
- collect(candidate);
211
- }
212
- return false;
213
- }
214
- return true;
215
- });
216
- return result;
217
- };
218
- CSSNavigation.prototype.findDocumentSymbols = function (document, stylesheet) {
219
- var result = [];
220
- stylesheet.accept(function (node) {
221
- var entry = {
222
- name: null,
223
- kind: SymbolKind.Class,
224
- location: null
225
- };
226
- var locationNode = node;
227
- if (node instanceof nodes.Selector) {
228
- entry.name = node.getText();
229
- locationNode = node.findAParent(nodes.NodeType.Ruleset, nodes.NodeType.ExtendsReference);
230
- if (locationNode) {
231
- entry.location = Location.create(document.uri, getRange(locationNode, document));
232
- result.push(entry);
233
- }
234
- return false;
235
- }
236
- else if (node instanceof nodes.VariableDeclaration) {
237
- entry.name = node.getName();
238
- entry.kind = SymbolKind.Variable;
239
- }
240
- else if (node instanceof nodes.MixinDeclaration) {
241
- entry.name = node.getName();
242
- entry.kind = SymbolKind.Method;
243
- }
244
- else if (node instanceof nodes.FunctionDeclaration) {
245
- entry.name = node.getName();
246
- entry.kind = SymbolKind.Function;
247
- }
248
- else if (node instanceof nodes.Keyframe) {
249
- entry.name = localize('literal.keyframes', "@keyframes {0}", node.getName());
250
- }
251
- else if (node instanceof nodes.FontFace) {
252
- entry.name = localize('literal.fontface', "@font-face");
253
- }
254
- else if (node instanceof nodes.Media) {
255
- var mediaList = node.getChild(0);
256
- if (mediaList instanceof nodes.Medialist) {
257
- entry.name = '@media ' + mediaList.getText();
258
- entry.kind = SymbolKind.Module;
259
- }
260
- }
261
- if (entry.name) {
262
- entry.location = Location.create(document.uri, getRange(locationNode, document));
263
- result.push(entry);
264
- }
265
- return true;
266
- });
267
- return result;
268
- };
269
- CSSNavigation.prototype.findDocumentColors = function (document, stylesheet) {
270
- var result = [];
271
- stylesheet.accept(function (node) {
272
- var colorInfo = getColorInformation(node, document);
273
- if (colorInfo) {
274
- result.push(colorInfo);
275
- }
276
- return true;
277
- });
278
- return result;
279
- };
280
- CSSNavigation.prototype.getColorPresentations = function (document, stylesheet, color, range) {
281
- var result = [];
282
- var red256 = Math.round(color.red * 255), green256 = Math.round(color.green * 255), blue256 = Math.round(color.blue * 255);
283
- var label;
284
- if (color.alpha === 1) {
285
- label = "rgb(".concat(red256, ", ").concat(green256, ", ").concat(blue256, ")");
286
- }
287
- else {
288
- label = "rgba(".concat(red256, ", ").concat(green256, ", ").concat(blue256, ", ").concat(color.alpha, ")");
289
- }
290
- result.push({ label: label, textEdit: TextEdit.replace(range, label) });
291
- if (color.alpha === 1) {
292
- label = "#".concat(toTwoDigitHex(red256)).concat(toTwoDigitHex(green256)).concat(toTwoDigitHex(blue256));
293
- }
294
- else {
295
- label = "#".concat(toTwoDigitHex(red256)).concat(toTwoDigitHex(green256)).concat(toTwoDigitHex(blue256)).concat(toTwoDigitHex(Math.round(color.alpha * 255)));
296
- }
297
- result.push({ label: label, textEdit: TextEdit.replace(range, label) });
298
- var hsl = hslFromColor(color);
299
- if (hsl.a === 1) {
300
- label = "hsl(".concat(hsl.h, ", ").concat(Math.round(hsl.s * 100), "%, ").concat(Math.round(hsl.l * 100), "%)");
301
- }
302
- else {
303
- label = "hsla(".concat(hsl.h, ", ").concat(Math.round(hsl.s * 100), "%, ").concat(Math.round(hsl.l * 100), "%, ").concat(hsl.a, ")");
304
- }
305
- result.push({ label: label, textEdit: TextEdit.replace(range, label) });
306
- var hwb = hwbFromColor(color);
307
- if (hwb.a === 1) {
308
- label = "hwb(".concat(hwb.h, " ").concat(Math.round(hwb.w * 100), "% ").concat(Math.round(hwb.b * 100), "%)");
309
- }
310
- else {
311
- label = "hwb(".concat(hwb.h, " ").concat(Math.round(hwb.w * 100), "% ").concat(Math.round(hwb.b * 100), "% / ").concat(hwb.a, ")");
312
- }
313
- result.push({ label: label, textEdit: TextEdit.replace(range, label) });
314
- return result;
315
- };
316
- CSSNavigation.prototype.doRename = function (document, position, newName, stylesheet) {
317
- var _a;
318
- var highlights = this.findDocumentHighlights(document, position, stylesheet);
319
- var edits = highlights.map(function (h) { return TextEdit.replace(h.range, newName); });
320
- return {
321
- changes: (_a = {}, _a[document.uri] = edits, _a)
322
- };
323
- };
324
- CSSNavigation.prototype.resolveModuleReference = function (ref, documentUri, documentContext) {
325
- return __awaiter(this, void 0, void 0, function () {
326
- var moduleName, rootFolderUri, documentFolderUri, modulePath, pathWithinModule;
327
- return __generator(this, function (_a) {
328
- switch (_a.label) {
329
- case 0:
330
- if (!startsWith(documentUri, 'file://')) return [3 /*break*/, 2];
331
- moduleName = getModuleNameFromPath(ref);
332
- rootFolderUri = documentContext.resolveReference('/', documentUri);
333
- documentFolderUri = dirname(documentUri);
334
- return [4 /*yield*/, this.resolvePathToModule(moduleName, documentFolderUri, rootFolderUri)];
335
- case 1:
336
- modulePath = _a.sent();
337
- if (modulePath) {
338
- pathWithinModule = ref.substring(moduleName.length + 1);
339
- return [2 /*return*/, joinPath(modulePath, pathWithinModule)];
340
- }
341
- _a.label = 2;
342
- case 2: return [2 /*return*/, undefined];
343
- }
344
- });
345
- });
346
- };
347
- CSSNavigation.prototype.resolveRelativeReference = function (ref, documentUri, documentContext, isRawLink) {
348
- return __awaiter(this, void 0, void 0, function () {
349
- var relativeReference, _a;
350
- return __generator(this, function (_b) {
351
- switch (_b.label) {
352
- case 0:
353
- relativeReference = documentContext.resolveReference(ref, documentUri);
354
- if (!(ref[0] === '~' && ref[1] !== '/' && this.fileSystemProvider)) return [3 /*break*/, 2];
355
- ref = ref.substring(1);
356
- return [4 /*yield*/, this.resolveModuleReference(ref, documentUri, documentContext)];
357
- case 1: return [2 /*return*/, (_b.sent()) || relativeReference];
358
- case 2:
359
- if (!this.resolveModuleReferences) return [3 /*break*/, 7];
360
- _a = relativeReference;
361
- if (!_a) return [3 /*break*/, 4];
362
- return [4 /*yield*/, this.fileExists(relativeReference)];
363
- case 3:
364
- _a = (_b.sent());
365
- _b.label = 4;
366
- case 4:
367
- if (!_a) return [3 /*break*/, 5];
368
- return [2 /*return*/, relativeReference];
369
- case 5: return [4 /*yield*/, this.resolveModuleReference(ref, documentUri, documentContext)];
370
- case 6: return [2 /*return*/, (_b.sent()) || relativeReference];
371
- case 7: return [2 /*return*/, relativeReference];
372
- }
373
- });
374
- });
375
- };
376
- CSSNavigation.prototype.resolvePathToModule = function (_moduleName, documentFolderUri, rootFolderUri) {
377
- return __awaiter(this, void 0, void 0, function () {
378
- var packPath;
379
- return __generator(this, function (_a) {
380
- switch (_a.label) {
381
- case 0:
382
- packPath = joinPath(documentFolderUri, 'node_modules', _moduleName, 'package.json');
383
- return [4 /*yield*/, this.fileExists(packPath)];
384
- case 1:
385
- if (_a.sent()) {
386
- return [2 /*return*/, dirname(packPath)];
387
- }
388
- else if (rootFolderUri && documentFolderUri.startsWith(rootFolderUri) && (documentFolderUri.length !== rootFolderUri.length)) {
389
- return [2 /*return*/, this.resolvePathToModule(_moduleName, dirname(documentFolderUri), rootFolderUri)];
390
- }
391
- return [2 /*return*/, undefined];
392
- }
393
- });
394
- });
395
- };
396
- CSSNavigation.prototype.fileExists = function (uri) {
397
- return __awaiter(this, void 0, void 0, function () {
398
- var stat, err_1;
399
- return __generator(this, function (_a) {
400
- switch (_a.label) {
401
- case 0:
402
- if (!this.fileSystemProvider) {
403
- return [2 /*return*/, false];
404
- }
405
- _a.label = 1;
406
- case 1:
407
- _a.trys.push([1, 3, , 4]);
408
- return [4 /*yield*/, this.fileSystemProvider.stat(uri)];
409
- case 2:
410
- stat = _a.sent();
411
- if (stat.type === FileType.Unknown && stat.size === -1) {
412
- return [2 /*return*/, false];
413
- }
414
- return [2 /*return*/, true];
415
- case 3:
416
- err_1 = _a.sent();
417
- return [2 /*return*/, false];
418
- case 4: return [2 /*return*/];
419
- }
420
- });
421
- });
422
- };
423
- return CSSNavigation;
424
- }());
425
- export { CSSNavigation };
426
- function getColorInformation(node, document) {
427
- var color = getColorValue(node);
428
- if (color) {
429
- var range = getRange(node, document);
430
- return { color: color, range: range };
431
- }
432
- return null;
433
- }
434
- function getRange(node, document) {
435
- return Range.create(document.positionAt(node.offset), document.positionAt(node.end));
436
- }
437
- function getHighlightKind(node) {
438
- if (node.type === nodes.NodeType.Selector) {
439
- return DocumentHighlightKind.Write;
440
- }
441
- if (node instanceof nodes.Identifier) {
442
- if (node.parent && node.parent instanceof nodes.Property) {
443
- if (node.isCustomProperty) {
444
- return DocumentHighlightKind.Write;
445
- }
446
- }
447
- }
448
- if (node.parent) {
449
- switch (node.parent.type) {
450
- case nodes.NodeType.FunctionDeclaration:
451
- case nodes.NodeType.MixinDeclaration:
452
- case nodes.NodeType.Keyframe:
453
- case nodes.NodeType.VariableDeclaration:
454
- case nodes.NodeType.FunctionParameter:
455
- return DocumentHighlightKind.Write;
456
- }
457
- }
458
- return DocumentHighlightKind.Read;
459
- }
460
- function toTwoDigitHex(n) {
461
- var r = n.toString(16);
462
- return r.length !== 2 ? '0' + r : r;
463
- }
464
- function getModuleNameFromPath(path) {
465
- // If a scoped module (starts with @) then get up until second instance of '/', otherwise get until first instance of '/'
466
- if (path[0] === '@') {
467
- return path.substring(0, path.indexOf('/', path.indexOf('/') + 1));
468
- }
469
- return path.substring(0, path.indexOf('/'));
470
- }
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License. See License.txt in the project root for license information.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ 'use strict';
6
+ import { DocumentHighlightKind, Location, Range, SymbolKind, TextEdit, FileType } from '../cssLanguageTypes';
7
+ import * as nls from 'vscode-nls';
8
+ import * as nodes from '../parser/cssNodes';
9
+ import { Symbols } from '../parser/cssSymbolScope';
10
+ import { getColorValue, hslFromColor, hwbFromColor } from '../languageFacts/facts';
11
+ import { startsWith } from '../utils/strings';
12
+ import { dirname, joinPath } from '../utils/resources';
13
+ const localize = nls.loadMessageBundle();
14
+ const startsWithSchemeRegex = /^\w+:\/\//;
15
+ const startsWithData = /^data:/;
16
+ export class CSSNavigation {
17
+ constructor(fileSystemProvider, resolveModuleReferences) {
18
+ this.fileSystemProvider = fileSystemProvider;
19
+ this.resolveModuleReferences = resolveModuleReferences;
20
+ }
21
+ findDefinition(document, position, stylesheet) {
22
+ const symbols = new Symbols(stylesheet);
23
+ const offset = document.offsetAt(position);
24
+ const node = nodes.getNodeAtOffset(stylesheet, offset);
25
+ if (!node) {
26
+ return null;
27
+ }
28
+ const symbol = symbols.findSymbolFromNode(node);
29
+ if (!symbol) {
30
+ return null;
31
+ }
32
+ return {
33
+ uri: document.uri,
34
+ range: getRange(symbol.node, document)
35
+ };
36
+ }
37
+ findReferences(document, position, stylesheet) {
38
+ const highlights = this.findDocumentHighlights(document, position, stylesheet);
39
+ return highlights.map(h => {
40
+ return {
41
+ uri: document.uri,
42
+ range: h.range
43
+ };
44
+ });
45
+ }
46
+ findDocumentHighlights(document, position, stylesheet) {
47
+ const result = [];
48
+ const offset = document.offsetAt(position);
49
+ let node = nodes.getNodeAtOffset(stylesheet, offset);
50
+ if (!node || node.type === nodes.NodeType.Stylesheet || node.type === nodes.NodeType.Declarations) {
51
+ return result;
52
+ }
53
+ if (node.type === nodes.NodeType.Identifier && node.parent && node.parent.type === nodes.NodeType.ClassSelector) {
54
+ node = node.parent;
55
+ }
56
+ const symbols = new Symbols(stylesheet);
57
+ const symbol = symbols.findSymbolFromNode(node);
58
+ const name = node.getText();
59
+ stylesheet.accept(candidate => {
60
+ if (symbol) {
61
+ if (symbols.matchesSymbol(candidate, symbol)) {
62
+ result.push({
63
+ kind: getHighlightKind(candidate),
64
+ range: getRange(candidate, document)
65
+ });
66
+ return false;
67
+ }
68
+ }
69
+ else if (node && node.type === candidate.type && candidate.matches(name)) {
70
+ // Same node type and data
71
+ result.push({
72
+ kind: getHighlightKind(candidate),
73
+ range: getRange(candidate, document)
74
+ });
75
+ }
76
+ return true;
77
+ });
78
+ return result;
79
+ }
80
+ isRawStringDocumentLinkNode(node) {
81
+ return node.type === nodes.NodeType.Import;
82
+ }
83
+ findDocumentLinks(document, stylesheet, documentContext) {
84
+ const linkData = this.findUnresolvedLinks(document, stylesheet);
85
+ const resolvedLinks = [];
86
+ for (let data of linkData) {
87
+ const link = data.link;
88
+ const target = link.target;
89
+ if (!target || startsWithData.test(target)) {
90
+ // no links for data:
91
+ }
92
+ else if (startsWithSchemeRegex.test(target)) {
93
+ resolvedLinks.push(link);
94
+ }
95
+ else {
96
+ const resolved = documentContext.resolveReference(target, document.uri);
97
+ if (resolved) {
98
+ link.target = resolved;
99
+ }
100
+ resolvedLinks.push(link);
101
+ }
102
+ }
103
+ return resolvedLinks;
104
+ }
105
+ async findDocumentLinks2(document, stylesheet, documentContext) {
106
+ const linkData = this.findUnresolvedLinks(document, stylesheet);
107
+ const resolvedLinks = [];
108
+ for (let data of linkData) {
109
+ const link = data.link;
110
+ const target = link.target;
111
+ if (!target || startsWithData.test(target)) {
112
+ // no links for data:
113
+ }
114
+ else if (startsWithSchemeRegex.test(target)) {
115
+ resolvedLinks.push(link);
116
+ }
117
+ else {
118
+ const resolvedTarget = await this.resolveRelativeReference(target, document.uri, documentContext, data.isRawLink);
119
+ if (resolvedTarget !== undefined) {
120
+ link.target = resolvedTarget;
121
+ resolvedLinks.push(link);
122
+ }
123
+ }
124
+ }
125
+ return resolvedLinks;
126
+ }
127
+ findUnresolvedLinks(document, stylesheet) {
128
+ const result = [];
129
+ const collect = (uriStringNode) => {
130
+ let rawUri = uriStringNode.getText();
131
+ const range = getRange(uriStringNode, document);
132
+ // Make sure the range is not empty
133
+ if (range.start.line === range.end.line && range.start.character === range.end.character) {
134
+ return;
135
+ }
136
+ if (startsWith(rawUri, `'`) || startsWith(rawUri, `"`)) {
137
+ rawUri = rawUri.slice(1, -1);
138
+ }
139
+ const isRawLink = uriStringNode.parent ? this.isRawStringDocumentLinkNode(uriStringNode.parent) : false;
140
+ result.push({ link: { target: rawUri, range }, isRawLink });
141
+ };
142
+ stylesheet.accept(candidate => {
143
+ if (candidate.type === nodes.NodeType.URILiteral) {
144
+ const first = candidate.getChild(0);
145
+ if (first) {
146
+ collect(first);
147
+ }
148
+ return false;
149
+ }
150
+ /**
151
+ * In @import, it is possible to include links that do not use `url()`
152
+ * For example, `@import 'foo.css';`
153
+ */
154
+ if (candidate.parent && this.isRawStringDocumentLinkNode(candidate.parent)) {
155
+ const rawText = candidate.getText();
156
+ if (startsWith(rawText, `'`) || startsWith(rawText, `"`)) {
157
+ collect(candidate);
158
+ }
159
+ return false;
160
+ }
161
+ return true;
162
+ });
163
+ return result;
164
+ }
165
+ findDocumentSymbols(document, stylesheet) {
166
+ const result = [];
167
+ stylesheet.accept((node) => {
168
+ const entry = {
169
+ name: null,
170
+ kind: SymbolKind.Class,
171
+ location: null
172
+ };
173
+ let locationNode = node;
174
+ if (node instanceof nodes.Selector) {
175
+ entry.name = node.getText();
176
+ locationNode = node.findAParent(nodes.NodeType.Ruleset, nodes.NodeType.ExtendsReference);
177
+ if (locationNode) {
178
+ entry.location = Location.create(document.uri, getRange(locationNode, document));
179
+ result.push(entry);
180
+ }
181
+ return false;
182
+ }
183
+ else if (node instanceof nodes.VariableDeclaration) {
184
+ entry.name = node.getName();
185
+ entry.kind = SymbolKind.Variable;
186
+ }
187
+ else if (node instanceof nodes.MixinDeclaration) {
188
+ entry.name = node.getName();
189
+ entry.kind = SymbolKind.Method;
190
+ }
191
+ else if (node instanceof nodes.FunctionDeclaration) {
192
+ entry.name = node.getName();
193
+ entry.kind = SymbolKind.Function;
194
+ }
195
+ else if (node instanceof nodes.Keyframe) {
196
+ entry.name = localize('literal.keyframes', "@keyframes {0}", node.getName());
197
+ }
198
+ else if (node instanceof nodes.FontFace) {
199
+ entry.name = localize('literal.fontface', "@font-face");
200
+ }
201
+ else if (node instanceof nodes.Media) {
202
+ const mediaList = node.getChild(0);
203
+ if (mediaList instanceof nodes.Medialist) {
204
+ entry.name = '@media ' + mediaList.getText();
205
+ entry.kind = SymbolKind.Module;
206
+ }
207
+ }
208
+ if (entry.name) {
209
+ entry.location = Location.create(document.uri, getRange(locationNode, document));
210
+ result.push(entry);
211
+ }
212
+ return true;
213
+ });
214
+ return result;
215
+ }
216
+ findDocumentColors(document, stylesheet) {
217
+ const result = [];
218
+ stylesheet.accept((node) => {
219
+ const colorInfo = getColorInformation(node, document);
220
+ if (colorInfo) {
221
+ result.push(colorInfo);
222
+ }
223
+ return true;
224
+ });
225
+ return result;
226
+ }
227
+ getColorPresentations(document, stylesheet, color, range) {
228
+ const result = [];
229
+ const red256 = Math.round(color.red * 255), green256 = Math.round(color.green * 255), blue256 = Math.round(color.blue * 255);
230
+ let label;
231
+ if (color.alpha === 1) {
232
+ label = `rgb(${red256}, ${green256}, ${blue256})`;
233
+ }
234
+ else {
235
+ label = `rgba(${red256}, ${green256}, ${blue256}, ${color.alpha})`;
236
+ }
237
+ result.push({ label: label, textEdit: TextEdit.replace(range, label) });
238
+ if (color.alpha === 1) {
239
+ label = `#${toTwoDigitHex(red256)}${toTwoDigitHex(green256)}${toTwoDigitHex(blue256)}`;
240
+ }
241
+ else {
242
+ label = `#${toTwoDigitHex(red256)}${toTwoDigitHex(green256)}${toTwoDigitHex(blue256)}${toTwoDigitHex(Math.round(color.alpha * 255))}`;
243
+ }
244
+ result.push({ label: label, textEdit: TextEdit.replace(range, label) });
245
+ const hsl = hslFromColor(color);
246
+ if (hsl.a === 1) {
247
+ label = `hsl(${hsl.h}, ${Math.round(hsl.s * 100)}%, ${Math.round(hsl.l * 100)}%)`;
248
+ }
249
+ else {
250
+ label = `hsla(${hsl.h}, ${Math.round(hsl.s * 100)}%, ${Math.round(hsl.l * 100)}%, ${hsl.a})`;
251
+ }
252
+ result.push({ label: label, textEdit: TextEdit.replace(range, label) });
253
+ const hwb = hwbFromColor(color);
254
+ if (hwb.a === 1) {
255
+ label = `hwb(${hwb.h} ${Math.round(hwb.w * 100)}% ${Math.round(hwb.b * 100)}%)`;
256
+ }
257
+ else {
258
+ label = `hwb(${hwb.h} ${Math.round(hwb.w * 100)}% ${Math.round(hwb.b * 100)}% / ${hwb.a})`;
259
+ }
260
+ result.push({ label: label, textEdit: TextEdit.replace(range, label) });
261
+ return result;
262
+ }
263
+ doRename(document, position, newName, stylesheet) {
264
+ const highlights = this.findDocumentHighlights(document, position, stylesheet);
265
+ const edits = highlights.map(h => TextEdit.replace(h.range, newName));
266
+ return {
267
+ changes: { [document.uri]: edits }
268
+ };
269
+ }
270
+ async resolveModuleReference(ref, documentUri, documentContext) {
271
+ if (startsWith(documentUri, 'file://')) {
272
+ const moduleName = getModuleNameFromPath(ref);
273
+ const rootFolderUri = documentContext.resolveReference('/', documentUri);
274
+ const documentFolderUri = dirname(documentUri);
275
+ const modulePath = await this.resolvePathToModule(moduleName, documentFolderUri, rootFolderUri);
276
+ if (modulePath) {
277
+ const pathWithinModule = ref.substring(moduleName.length + 1);
278
+ return joinPath(modulePath, pathWithinModule);
279
+ }
280
+ }
281
+ return undefined;
282
+ }
283
+ async resolveRelativeReference(ref, documentUri, documentContext, isRawLink) {
284
+ const relativeReference = documentContext.resolveReference(ref, documentUri);
285
+ // Following [css-loader](https://github.com/webpack-contrib/css-loader#url)
286
+ // and [sass-loader's](https://github.com/webpack-contrib/sass-loader#imports)
287
+ // convention, if an import path starts with ~ then use node module resolution
288
+ // *unless* it starts with "~/" as this refers to the user's home directory.
289
+ if (ref[0] === '~' && ref[1] !== '/' && this.fileSystemProvider) {
290
+ ref = ref.substring(1);
291
+ return await this.resolveModuleReference(ref, documentUri, documentContext) || relativeReference;
292
+ }
293
+ // Following [less-loader](https://github.com/webpack-contrib/less-loader#imports)
294
+ // and [sass-loader's](https://github.com/webpack-contrib/sass-loader#resolving-import-at-rules)
295
+ // new resolving import at-rules (~ is deprecated). The loader will first try to resolve @import as a relative path. If it cannot be resolved,
296
+ // then the loader will try to resolve @import inside node_modules.
297
+ if (this.resolveModuleReferences) {
298
+ if (relativeReference && await this.fileExists(relativeReference)) {
299
+ return relativeReference;
300
+ }
301
+ else {
302
+ return await this.resolveModuleReference(ref, documentUri, documentContext) || relativeReference;
303
+ }
304
+ }
305
+ return relativeReference;
306
+ }
307
+ async resolvePathToModule(_moduleName, documentFolderUri, rootFolderUri) {
308
+ // resolve the module relative to the document. We can't use `require` here as the code is webpacked.
309
+ const packPath = joinPath(documentFolderUri, 'node_modules', _moduleName, 'package.json');
310
+ if (await this.fileExists(packPath)) {
311
+ return dirname(packPath);
312
+ }
313
+ else if (rootFolderUri && documentFolderUri.startsWith(rootFolderUri) && (documentFolderUri.length !== rootFolderUri.length)) {
314
+ return this.resolvePathToModule(_moduleName, dirname(documentFolderUri), rootFolderUri);
315
+ }
316
+ return undefined;
317
+ }
318
+ async fileExists(uri) {
319
+ if (!this.fileSystemProvider) {
320
+ return false;
321
+ }
322
+ try {
323
+ const stat = await this.fileSystemProvider.stat(uri);
324
+ if (stat.type === FileType.Unknown && stat.size === -1) {
325
+ return false;
326
+ }
327
+ return true;
328
+ }
329
+ catch (err) {
330
+ return false;
331
+ }
332
+ }
333
+ }
334
+ function getColorInformation(node, document) {
335
+ const color = getColorValue(node);
336
+ if (color) {
337
+ const range = getRange(node, document);
338
+ return { color, range };
339
+ }
340
+ return null;
341
+ }
342
+ function getRange(node, document) {
343
+ return Range.create(document.positionAt(node.offset), document.positionAt(node.end));
344
+ }
345
+ function getHighlightKind(node) {
346
+ if (node.type === nodes.NodeType.Selector) {
347
+ return DocumentHighlightKind.Write;
348
+ }
349
+ if (node instanceof nodes.Identifier) {
350
+ if (node.parent && node.parent instanceof nodes.Property) {
351
+ if (node.isCustomProperty) {
352
+ return DocumentHighlightKind.Write;
353
+ }
354
+ }
355
+ }
356
+ if (node.parent) {
357
+ switch (node.parent.type) {
358
+ case nodes.NodeType.FunctionDeclaration:
359
+ case nodes.NodeType.MixinDeclaration:
360
+ case nodes.NodeType.Keyframe:
361
+ case nodes.NodeType.VariableDeclaration:
362
+ case nodes.NodeType.FunctionParameter:
363
+ return DocumentHighlightKind.Write;
364
+ }
365
+ }
366
+ return DocumentHighlightKind.Read;
367
+ }
368
+ function toTwoDigitHex(n) {
369
+ const r = n.toString(16);
370
+ return r.length !== 2 ? '0' + r : r;
371
+ }
372
+ function getModuleNameFromPath(path) {
373
+ // If a scoped module (starts with @) then get up until second instance of '/', otherwise get until first instance of '/'
374
+ if (path[0] === '@') {
375
+ return path.substring(0, path.indexOf('/', path.indexOf('/') + 1));
376
+ }
377
+ return path.substring(0, path.indexOf('/'));
378
+ }