vscode-css-languageservice 5.3.0 → 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.
- package/CHANGELOG.md +9 -0
- package/README.md +1 -0
- package/lib/esm/beautify/beautify-css.js +57 -15
- package/lib/esm/cssLanguageService.d.ts +37 -37
- package/lib/esm/cssLanguageService.js +72 -75
- package/lib/esm/cssLanguageTypes.d.ts +238 -228
- package/lib/esm/cssLanguageTypes.js +42 -42
- package/lib/esm/data/webCustomData.js +21965 -21959
- package/lib/esm/languageFacts/builtinData.js +142 -142
- package/lib/esm/languageFacts/colors.js +469 -472
- package/lib/esm/languageFacts/dataManager.js +88 -92
- package/lib/esm/languageFacts/dataProvider.js +73 -79
- package/lib/esm/languageFacts/entry.js +137 -138
- package/lib/esm/languageFacts/facts.js +8 -8
- package/lib/esm/parser/cssErrors.js +48 -50
- package/lib/esm/parser/cssNodes.js +1502 -2019
- package/lib/esm/parser/cssParser.js +1534 -1566
- package/lib/esm/parser/cssScanner.js +592 -599
- package/lib/esm/parser/cssSymbolScope.js +311 -341
- package/lib/esm/parser/lessParser.js +714 -740
- package/lib/esm/parser/lessScanner.js +57 -78
- package/lib/esm/parser/scssErrors.js +18 -20
- package/lib/esm/parser/scssParser.js +796 -818
- package/lib/esm/parser/scssScanner.js +95 -116
- package/lib/esm/services/cssCodeActions.js +77 -81
- package/lib/esm/services/cssCompletion.js +1054 -1149
- package/lib/esm/services/cssFolding.js +190 -193
- package/lib/esm/services/cssFormatter.js +136 -117
- package/lib/esm/services/cssHover.js +148 -151
- package/lib/esm/services/cssNavigation.js +378 -470
- package/lib/esm/services/cssSelectionRange.js +47 -47
- package/lib/esm/services/cssValidation.js +41 -44
- package/lib/esm/services/lessCompletion.js +378 -397
- package/lib/esm/services/lint.js +518 -532
- package/lib/esm/services/lintRules.js +76 -83
- package/lib/esm/services/lintUtil.js +196 -205
- package/lib/esm/services/pathCompletion.js +157 -231
- package/lib/esm/services/scssCompletion.js +354 -378
- package/lib/esm/services/scssNavigation.js +82 -154
- package/lib/esm/services/selectorPrinting.js +492 -536
- package/lib/esm/utils/arrays.js +40 -46
- package/lib/esm/utils/objects.js +11 -11
- package/lib/esm/utils/resources.js +11 -24
- package/lib/esm/utils/strings.js +102 -104
- package/lib/umd/beautify/beautify-css.js +57 -15
- package/lib/umd/cssLanguageService.d.ts +37 -37
- package/lib/umd/cssLanguageService.js +99 -102
- package/lib/umd/cssLanguageTypes.d.ts +238 -228
- package/lib/umd/cssLanguageTypes.js +89 -88
- package/lib/umd/data/webCustomData.js +21978 -21972
- package/lib/umd/languageFacts/builtinData.js +154 -154
- package/lib/umd/languageFacts/colors.js +492 -495
- package/lib/umd/languageFacts/dataManager.js +101 -104
- package/lib/umd/languageFacts/dataProvider.js +86 -91
- package/lib/umd/languageFacts/entry.js +152 -153
- package/lib/umd/languageFacts/facts.js +29 -29
- package/lib/umd/parser/cssErrors.js +61 -62
- package/lib/umd/parser/cssNodes.js +1587 -2034
- package/lib/umd/parser/cssParser.js +1547 -1578
- package/lib/umd/parser/cssScanner.js +606 -611
- package/lib/umd/parser/cssSymbolScope.js +328 -353
- package/lib/umd/parser/lessParser.js +727 -752
- package/lib/umd/parser/lessScanner.js +70 -90
- package/lib/umd/parser/scssErrors.js +31 -32
- package/lib/umd/parser/scssParser.js +809 -830
- package/lib/umd/parser/scssScanner.js +108 -128
- package/lib/umd/services/cssCodeActions.js +90 -93
- package/lib/umd/services/cssCompletion.js +1067 -1161
- package/lib/umd/services/cssFolding.js +203 -206
- package/lib/umd/services/cssFormatter.js +150 -131
- package/lib/umd/services/cssHover.js +161 -163
- package/lib/umd/services/cssNavigation.js +391 -482
- package/lib/umd/services/cssSelectionRange.js +60 -60
- package/lib/umd/services/cssValidation.js +54 -56
- package/lib/umd/services/lessCompletion.js +391 -409
- package/lib/umd/services/lint.js +531 -544
- package/lib/umd/services/lintRules.js +91 -95
- package/lib/umd/services/lintUtil.js +210 -218
- package/lib/umd/services/pathCompletion.js +171 -244
- package/lib/umd/services/scssCompletion.js +367 -390
- package/lib/umd/services/scssNavigation.js +95 -166
- package/lib/umd/services/selectorPrinting.js +510 -550
- package/lib/umd/utils/arrays.js +55 -61
- package/lib/umd/utils/objects.js +25 -25
- package/lib/umd/utils/resources.js +26 -39
- package/lib/umd/utils/strings.js +120 -122
- package/package.json +11 -11
|
@@ -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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
return
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
return
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
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
|
+
}
|