vscode-css-languageservice 5.4.1 → 6.0.1
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 +5 -1
- package/README.md +1 -0
- package/lib/esm/beautify/beautify-css.js +50 -8
- package/lib/esm/cssLanguageService.d.ts +37 -37
- package/lib/esm/cssLanguageService.js +72 -75
- package/lib/esm/cssLanguageTypes.d.ts +238 -238
- package/lib/esm/cssLanguageTypes.js +42 -42
- package/lib/esm/data/webCustomData.js +21959 -21965
- 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 -136
- 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 +50 -8
- package/lib/umd/cssLanguageService.d.ts +37 -37
- package/lib/umd/cssLanguageService.js +99 -102
- package/lib/umd/cssLanguageTypes.d.ts +238 -238
- package/lib/umd/cssLanguageTypes.js +89 -88
- package/lib/umd/data/webCustomData.js +21972 -21978
- 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 -150
- 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,536 +1,492 @@
|
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
else {
|
|
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
|
-
if (
|
|
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
|
-
|
|
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
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
continue elementLoop;
|
|
392
|
-
}
|
|
393
|
-
//
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
selectorChild.type === nodes.NodeType.SelectorCombinatorAllSiblings) {
|
|
494
|
-
this.prev = selectorChild;
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
};
|
|
498
|
-
return SelectorElementBuilder;
|
|
499
|
-
}());
|
|
500
|
-
function isNewSelectorContext(node) {
|
|
501
|
-
switch (node.type) {
|
|
502
|
-
case nodes.NodeType.MixinDeclaration:
|
|
503
|
-
case nodes.NodeType.Stylesheet:
|
|
504
|
-
return true;
|
|
505
|
-
}
|
|
506
|
-
return false;
|
|
507
|
-
}
|
|
508
|
-
export function selectorToElement(node) {
|
|
509
|
-
if (node.matches('@at-root')) {
|
|
510
|
-
return null;
|
|
511
|
-
}
|
|
512
|
-
var root = new RootElement();
|
|
513
|
-
var parentRuleSets = [];
|
|
514
|
-
var ruleSet = node.getParent();
|
|
515
|
-
if (ruleSet instanceof nodes.RuleSet) {
|
|
516
|
-
var parent = ruleSet.getParent(); // parent of the selector's ruleset
|
|
517
|
-
while (parent && !isNewSelectorContext(parent)) {
|
|
518
|
-
if (parent instanceof nodes.RuleSet) {
|
|
519
|
-
if (parent.getSelectors().matches('@at-root')) {
|
|
520
|
-
break;
|
|
521
|
-
}
|
|
522
|
-
parentRuleSets.push(parent);
|
|
523
|
-
}
|
|
524
|
-
parent = parent.getParent();
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
var builder = new SelectorElementBuilder(root);
|
|
528
|
-
for (var i = parentRuleSets.length - 1; i >= 0; i--) {
|
|
529
|
-
var selector = parentRuleSets[i].getSelectors().getChild(0);
|
|
530
|
-
if (selector) {
|
|
531
|
-
builder.processSelector(selector);
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
builder.processSelector(node);
|
|
535
|
-
return root;
|
|
536
|
-
}
|
|
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 * as nodes from '../parser/cssNodes';
|
|
7
|
+
import { Scanner } from '../parser/cssScanner';
|
|
8
|
+
import * as nls from 'vscode-nls';
|
|
9
|
+
const localize = nls.loadMessageBundle();
|
|
10
|
+
export class Element {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.parent = null;
|
|
13
|
+
this.children = null;
|
|
14
|
+
this.attributes = null;
|
|
15
|
+
}
|
|
16
|
+
findAttribute(name) {
|
|
17
|
+
if (this.attributes) {
|
|
18
|
+
for (const attribute of this.attributes) {
|
|
19
|
+
if (attribute.name === name) {
|
|
20
|
+
return attribute.value;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
addChild(child) {
|
|
27
|
+
if (child instanceof Element) {
|
|
28
|
+
child.parent = this;
|
|
29
|
+
}
|
|
30
|
+
if (!this.children) {
|
|
31
|
+
this.children = [];
|
|
32
|
+
}
|
|
33
|
+
this.children.push(child);
|
|
34
|
+
}
|
|
35
|
+
append(text) {
|
|
36
|
+
if (this.attributes) {
|
|
37
|
+
const last = this.attributes[this.attributes.length - 1];
|
|
38
|
+
last.value = last.value + text;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
prepend(text) {
|
|
42
|
+
if (this.attributes) {
|
|
43
|
+
const first = this.attributes[0];
|
|
44
|
+
first.value = text + first.value;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
findRoot() {
|
|
48
|
+
let curr = this;
|
|
49
|
+
while (curr.parent && !(curr.parent instanceof RootElement)) {
|
|
50
|
+
curr = curr.parent;
|
|
51
|
+
}
|
|
52
|
+
return curr;
|
|
53
|
+
}
|
|
54
|
+
removeChild(child) {
|
|
55
|
+
if (this.children) {
|
|
56
|
+
const index = this.children.indexOf(child);
|
|
57
|
+
if (index !== -1) {
|
|
58
|
+
this.children.splice(index, 1);
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
addAttr(name, value) {
|
|
65
|
+
if (!this.attributes) {
|
|
66
|
+
this.attributes = [];
|
|
67
|
+
}
|
|
68
|
+
for (const attribute of this.attributes) {
|
|
69
|
+
if (attribute.name === name) {
|
|
70
|
+
attribute.value += ' ' + value;
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
this.attributes.push({ name, value });
|
|
75
|
+
}
|
|
76
|
+
clone(cloneChildren = true) {
|
|
77
|
+
const elem = new Element();
|
|
78
|
+
if (this.attributes) {
|
|
79
|
+
elem.attributes = [];
|
|
80
|
+
for (const attribute of this.attributes) {
|
|
81
|
+
elem.addAttr(attribute.name, attribute.value);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (cloneChildren && this.children) {
|
|
85
|
+
elem.children = [];
|
|
86
|
+
for (let index = 0; index < this.children.length; index++) {
|
|
87
|
+
elem.addChild(this.children[index].clone());
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return elem;
|
|
91
|
+
}
|
|
92
|
+
cloneWithParent() {
|
|
93
|
+
const clone = this.clone(false);
|
|
94
|
+
if (this.parent && !(this.parent instanceof RootElement)) {
|
|
95
|
+
const parentClone = this.parent.cloneWithParent();
|
|
96
|
+
parentClone.addChild(clone);
|
|
97
|
+
}
|
|
98
|
+
return clone;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
export class RootElement extends Element {
|
|
102
|
+
}
|
|
103
|
+
export class LabelElement extends Element {
|
|
104
|
+
constructor(label) {
|
|
105
|
+
super();
|
|
106
|
+
this.addAttr('name', label);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
class MarkedStringPrinter {
|
|
110
|
+
constructor(quote) {
|
|
111
|
+
this.quote = quote;
|
|
112
|
+
this.result = [];
|
|
113
|
+
// empty
|
|
114
|
+
}
|
|
115
|
+
print(element) {
|
|
116
|
+
this.result = [];
|
|
117
|
+
if (element instanceof RootElement) {
|
|
118
|
+
if (element.children) {
|
|
119
|
+
this.doPrint(element.children, 0);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
this.doPrint([element], 0);
|
|
124
|
+
}
|
|
125
|
+
const value = this.result.join('\n');
|
|
126
|
+
return [{ language: 'html', value }];
|
|
127
|
+
}
|
|
128
|
+
doPrint(elements, indent) {
|
|
129
|
+
for (const element of elements) {
|
|
130
|
+
this.doPrintElement(element, indent);
|
|
131
|
+
if (element.children) {
|
|
132
|
+
this.doPrint(element.children, indent + 1);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
writeLine(level, content) {
|
|
137
|
+
const indent = new Array(level + 1).join(' ');
|
|
138
|
+
this.result.push(indent + content);
|
|
139
|
+
}
|
|
140
|
+
doPrintElement(element, indent) {
|
|
141
|
+
const name = element.findAttribute('name');
|
|
142
|
+
// special case: a simple label
|
|
143
|
+
if (element instanceof LabelElement || name === '\u2026') {
|
|
144
|
+
this.writeLine(indent, name);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
// the real deal
|
|
148
|
+
const content = ['<'];
|
|
149
|
+
// element name
|
|
150
|
+
if (name) {
|
|
151
|
+
content.push(name);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
content.push('element');
|
|
155
|
+
}
|
|
156
|
+
// attributes
|
|
157
|
+
if (element.attributes) {
|
|
158
|
+
for (const attr of element.attributes) {
|
|
159
|
+
if (attr.name !== 'name') {
|
|
160
|
+
content.push(' ');
|
|
161
|
+
content.push(attr.name);
|
|
162
|
+
const value = attr.value;
|
|
163
|
+
if (value) {
|
|
164
|
+
content.push('=');
|
|
165
|
+
content.push(quotes.ensure(value, this.quote));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
content.push('>');
|
|
171
|
+
this.writeLine(indent, content.join(''));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
var quotes;
|
|
175
|
+
(function (quotes) {
|
|
176
|
+
function ensure(value, which) {
|
|
177
|
+
return which + remove(value) + which;
|
|
178
|
+
}
|
|
179
|
+
quotes.ensure = ensure;
|
|
180
|
+
function remove(value) {
|
|
181
|
+
const match = value.match(/^['"](.*)["']$/);
|
|
182
|
+
if (match) {
|
|
183
|
+
return match[1];
|
|
184
|
+
}
|
|
185
|
+
return value;
|
|
186
|
+
}
|
|
187
|
+
quotes.remove = remove;
|
|
188
|
+
})(quotes || (quotes = {}));
|
|
189
|
+
class Specificity {
|
|
190
|
+
constructor() {
|
|
191
|
+
/** Count of identifiers (e.g., `#app`) */
|
|
192
|
+
this.id = 0;
|
|
193
|
+
/** Count of attributes (`[type="number"]`), classes (`.container-fluid`), and pseudo-classes (`:hover`) */
|
|
194
|
+
this.attr = 0;
|
|
195
|
+
/** Count of tag names (`div`), and pseudo-elements (`::before`) */
|
|
196
|
+
this.tag = 0;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
export function toElement(node, parentElement) {
|
|
200
|
+
let result = new Element();
|
|
201
|
+
for (const child of node.getChildren()) {
|
|
202
|
+
switch (child.type) {
|
|
203
|
+
case nodes.NodeType.SelectorCombinator:
|
|
204
|
+
if (parentElement) {
|
|
205
|
+
const segments = child.getText().split('&');
|
|
206
|
+
if (segments.length === 1) {
|
|
207
|
+
// should not happen
|
|
208
|
+
result.addAttr('name', segments[0]);
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
result = parentElement.cloneWithParent();
|
|
212
|
+
if (segments[0]) {
|
|
213
|
+
const root = result.findRoot();
|
|
214
|
+
root.prepend(segments[0]);
|
|
215
|
+
}
|
|
216
|
+
for (let i = 1; i < segments.length; i++) {
|
|
217
|
+
if (i > 1) {
|
|
218
|
+
const clone = parentElement.cloneWithParent();
|
|
219
|
+
result.addChild(clone.findRoot());
|
|
220
|
+
result = clone;
|
|
221
|
+
}
|
|
222
|
+
result.append(segments[i]);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
break;
|
|
226
|
+
case nodes.NodeType.SelectorPlaceholder:
|
|
227
|
+
if (child.matches('@at-root')) {
|
|
228
|
+
return result;
|
|
229
|
+
}
|
|
230
|
+
// fall through
|
|
231
|
+
case nodes.NodeType.ElementNameSelector:
|
|
232
|
+
const text = child.getText();
|
|
233
|
+
result.addAttr('name', text === '*' ? 'element' : unescape(text));
|
|
234
|
+
break;
|
|
235
|
+
case nodes.NodeType.ClassSelector:
|
|
236
|
+
result.addAttr('class', unescape(child.getText().substring(1)));
|
|
237
|
+
break;
|
|
238
|
+
case nodes.NodeType.IdentifierSelector:
|
|
239
|
+
result.addAttr('id', unescape(child.getText().substring(1)));
|
|
240
|
+
break;
|
|
241
|
+
case nodes.NodeType.MixinDeclaration:
|
|
242
|
+
result.addAttr('class', child.getName());
|
|
243
|
+
break;
|
|
244
|
+
case nodes.NodeType.PseudoSelector:
|
|
245
|
+
result.addAttr(unescape(child.getText()), '');
|
|
246
|
+
break;
|
|
247
|
+
case nodes.NodeType.AttributeSelector:
|
|
248
|
+
const selector = child;
|
|
249
|
+
const identifier = selector.getIdentifier();
|
|
250
|
+
if (identifier) {
|
|
251
|
+
const expression = selector.getValue();
|
|
252
|
+
const operator = selector.getOperator();
|
|
253
|
+
let value;
|
|
254
|
+
if (expression && operator) {
|
|
255
|
+
switch (unescape(operator.getText())) {
|
|
256
|
+
case '|=':
|
|
257
|
+
// excatly or followed by -words
|
|
258
|
+
value = `${quotes.remove(unescape(expression.getText()))}-\u2026`;
|
|
259
|
+
break;
|
|
260
|
+
case '^=':
|
|
261
|
+
// prefix
|
|
262
|
+
value = `${quotes.remove(unescape(expression.getText()))}\u2026`;
|
|
263
|
+
break;
|
|
264
|
+
case '$=':
|
|
265
|
+
// suffix
|
|
266
|
+
value = `\u2026${quotes.remove(unescape(expression.getText()))}`;
|
|
267
|
+
break;
|
|
268
|
+
case '~=':
|
|
269
|
+
// one of a list of words
|
|
270
|
+
value = ` \u2026 ${quotes.remove(unescape(expression.getText()))} \u2026 `;
|
|
271
|
+
break;
|
|
272
|
+
case '*=':
|
|
273
|
+
// substring
|
|
274
|
+
value = `\u2026${quotes.remove(unescape(expression.getText()))}\u2026`;
|
|
275
|
+
break;
|
|
276
|
+
default:
|
|
277
|
+
value = quotes.remove(unescape(expression.getText()));
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
result.addAttr(unescape(identifier.getText()), value);
|
|
282
|
+
}
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return result;
|
|
287
|
+
}
|
|
288
|
+
function unescape(content) {
|
|
289
|
+
const scanner = new Scanner();
|
|
290
|
+
scanner.setSource(content);
|
|
291
|
+
const token = scanner.scanUnquotedString();
|
|
292
|
+
if (token) {
|
|
293
|
+
return token.text;
|
|
294
|
+
}
|
|
295
|
+
return content;
|
|
296
|
+
}
|
|
297
|
+
export class SelectorPrinting {
|
|
298
|
+
constructor(cssDataManager) {
|
|
299
|
+
this.cssDataManager = cssDataManager;
|
|
300
|
+
}
|
|
301
|
+
selectorToMarkedString(node) {
|
|
302
|
+
const root = selectorToElement(node);
|
|
303
|
+
if (root) {
|
|
304
|
+
const markedStrings = new MarkedStringPrinter('"').print(root);
|
|
305
|
+
markedStrings.push(this.selectorToSpecificityMarkedString(node));
|
|
306
|
+
return markedStrings;
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
return [];
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
simpleSelectorToMarkedString(node) {
|
|
313
|
+
const element = toElement(node);
|
|
314
|
+
const markedStrings = new MarkedStringPrinter('"').print(element);
|
|
315
|
+
markedStrings.push(this.selectorToSpecificityMarkedString(node));
|
|
316
|
+
return markedStrings;
|
|
317
|
+
}
|
|
318
|
+
isPseudoElementIdentifier(text) {
|
|
319
|
+
const match = text.match(/^::?([\w-]+)/);
|
|
320
|
+
if (!match) {
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
return !!this.cssDataManager.getPseudoElement("::" + match[1]);
|
|
324
|
+
}
|
|
325
|
+
selectorToSpecificityMarkedString(node) {
|
|
326
|
+
//https://www.w3.org/TR/selectors-3/#specificity
|
|
327
|
+
const calculateScore = (node) => {
|
|
328
|
+
const specificity = new Specificity();
|
|
329
|
+
elementLoop: for (const element of node.getChildren()) {
|
|
330
|
+
switch (element.type) {
|
|
331
|
+
case nodes.NodeType.IdentifierSelector:
|
|
332
|
+
specificity.id++;
|
|
333
|
+
break;
|
|
334
|
+
case nodes.NodeType.ClassSelector:
|
|
335
|
+
case nodes.NodeType.AttributeSelector:
|
|
336
|
+
specificity.attr++;
|
|
337
|
+
break;
|
|
338
|
+
case nodes.NodeType.ElementNameSelector:
|
|
339
|
+
//ignore universal selector
|
|
340
|
+
if (element.matches("*")) {
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
specificity.tag++;
|
|
344
|
+
break;
|
|
345
|
+
case nodes.NodeType.PseudoSelector:
|
|
346
|
+
const text = element.getText();
|
|
347
|
+
if (this.isPseudoElementIdentifier(text)) {
|
|
348
|
+
specificity.tag++; // pseudo element
|
|
349
|
+
continue elementLoop;
|
|
350
|
+
}
|
|
351
|
+
// where and child selectors have zero specificity
|
|
352
|
+
if (text.match(/^:where/i)) {
|
|
353
|
+
continue elementLoop;
|
|
354
|
+
}
|
|
355
|
+
// the most specific child selector
|
|
356
|
+
if (text.match(/^:(not|has|is)/i) && element.getChildren().length > 0) {
|
|
357
|
+
let mostSpecificListItem = new Specificity();
|
|
358
|
+
for (const containerElement of element.getChildren()) {
|
|
359
|
+
let list;
|
|
360
|
+
if (containerElement.type === nodes.NodeType.Undefined) { // containerElement is a list of selectors
|
|
361
|
+
list = containerElement.getChildren();
|
|
362
|
+
}
|
|
363
|
+
else { // containerElement is a selector
|
|
364
|
+
list = [containerElement];
|
|
365
|
+
}
|
|
366
|
+
for (const childElement of containerElement.getChildren()) {
|
|
367
|
+
const itemSpecificity = calculateScore(childElement);
|
|
368
|
+
if (itemSpecificity.id > mostSpecificListItem.id) {
|
|
369
|
+
mostSpecificListItem = itemSpecificity;
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
else if (itemSpecificity.id < mostSpecificListItem.id) {
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
if (itemSpecificity.attr > mostSpecificListItem.attr) {
|
|
376
|
+
mostSpecificListItem = itemSpecificity;
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
else if (itemSpecificity.attr < mostSpecificListItem.attr) {
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
if (itemSpecificity.tag > mostSpecificListItem.tag) {
|
|
383
|
+
mostSpecificListItem = itemSpecificity;
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
specificity.id += mostSpecificListItem.id;
|
|
389
|
+
specificity.attr += mostSpecificListItem.attr;
|
|
390
|
+
specificity.tag += mostSpecificListItem.tag;
|
|
391
|
+
continue elementLoop;
|
|
392
|
+
}
|
|
393
|
+
specificity.attr++; //pseudo class
|
|
394
|
+
continue elementLoop;
|
|
395
|
+
}
|
|
396
|
+
if (element.getChildren().length > 0) {
|
|
397
|
+
const itemSpecificity = calculateScore(element);
|
|
398
|
+
specificity.id += itemSpecificity.id;
|
|
399
|
+
specificity.attr += itemSpecificity.attr;
|
|
400
|
+
specificity.tag += itemSpecificity.tag;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return specificity;
|
|
404
|
+
};
|
|
405
|
+
const specificity = calculateScore(node);
|
|
406
|
+
;
|
|
407
|
+
return localize('specificity', "[Selector Specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity): ({0}, {1}, {2})", specificity.id, specificity.attr, specificity.tag);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
class SelectorElementBuilder {
|
|
411
|
+
constructor(element) {
|
|
412
|
+
this.prev = null;
|
|
413
|
+
this.element = element;
|
|
414
|
+
}
|
|
415
|
+
processSelector(selector) {
|
|
416
|
+
let parentElement = null;
|
|
417
|
+
if (!(this.element instanceof RootElement)) {
|
|
418
|
+
if (selector.getChildren().some((c) => c.hasChildren() && c.getChild(0).type === nodes.NodeType.SelectorCombinator)) {
|
|
419
|
+
const curr = this.element.findRoot();
|
|
420
|
+
if (curr.parent instanceof RootElement) {
|
|
421
|
+
parentElement = this.element;
|
|
422
|
+
this.element = curr.parent;
|
|
423
|
+
this.element.removeChild(curr);
|
|
424
|
+
this.prev = null;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
for (const selectorChild of selector.getChildren()) {
|
|
429
|
+
if (selectorChild instanceof nodes.SimpleSelector) {
|
|
430
|
+
if (this.prev instanceof nodes.SimpleSelector) {
|
|
431
|
+
const labelElement = new LabelElement('\u2026');
|
|
432
|
+
this.element.addChild(labelElement);
|
|
433
|
+
this.element = labelElement;
|
|
434
|
+
}
|
|
435
|
+
else if (this.prev && (this.prev.matches('+') || this.prev.matches('~')) && this.element.parent) {
|
|
436
|
+
this.element = this.element.parent;
|
|
437
|
+
}
|
|
438
|
+
if (this.prev && this.prev.matches('~')) {
|
|
439
|
+
this.element.addChild(new LabelElement('\u22EE'));
|
|
440
|
+
}
|
|
441
|
+
const thisElement = toElement(selectorChild, parentElement);
|
|
442
|
+
const root = thisElement.findRoot();
|
|
443
|
+
this.element.addChild(root);
|
|
444
|
+
this.element = thisElement;
|
|
445
|
+
}
|
|
446
|
+
if (selectorChild instanceof nodes.SimpleSelector ||
|
|
447
|
+
selectorChild.type === nodes.NodeType.SelectorCombinatorParent ||
|
|
448
|
+
selectorChild.type === nodes.NodeType.SelectorCombinatorShadowPiercingDescendant ||
|
|
449
|
+
selectorChild.type === nodes.NodeType.SelectorCombinatorSibling ||
|
|
450
|
+
selectorChild.type === nodes.NodeType.SelectorCombinatorAllSiblings) {
|
|
451
|
+
this.prev = selectorChild;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
function isNewSelectorContext(node) {
|
|
457
|
+
switch (node.type) {
|
|
458
|
+
case nodes.NodeType.MixinDeclaration:
|
|
459
|
+
case nodes.NodeType.Stylesheet:
|
|
460
|
+
return true;
|
|
461
|
+
}
|
|
462
|
+
return false;
|
|
463
|
+
}
|
|
464
|
+
export function selectorToElement(node) {
|
|
465
|
+
if (node.matches('@at-root')) {
|
|
466
|
+
return null;
|
|
467
|
+
}
|
|
468
|
+
const root = new RootElement();
|
|
469
|
+
const parentRuleSets = [];
|
|
470
|
+
const ruleSet = node.getParent();
|
|
471
|
+
if (ruleSet instanceof nodes.RuleSet) {
|
|
472
|
+
let parent = ruleSet.getParent(); // parent of the selector's ruleset
|
|
473
|
+
while (parent && !isNewSelectorContext(parent)) {
|
|
474
|
+
if (parent instanceof nodes.RuleSet) {
|
|
475
|
+
if (parent.getSelectors().matches('@at-root')) {
|
|
476
|
+
break;
|
|
477
|
+
}
|
|
478
|
+
parentRuleSets.push(parent);
|
|
479
|
+
}
|
|
480
|
+
parent = parent.getParent();
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
const builder = new SelectorElementBuilder(root);
|
|
484
|
+
for (let i = parentRuleSets.length - 1; i >= 0; i--) {
|
|
485
|
+
const selector = parentRuleSets[i].getSelectors().getChild(0);
|
|
486
|
+
if (selector) {
|
|
487
|
+
builder.processSelector(selector);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
builder.processSelector(node);
|
|
491
|
+
return root;
|
|
492
|
+
}
|