vscode-css-languageservice 6.2.4 → 6.2.6
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/README.md +1 -1
- package/lib/esm/data/webCustomData.js +112 -116
- package/lib/esm/languageFacts/builtinData.js +1 -1
- package/lib/esm/languageFacts/colors.js +128 -6
- package/lib/esm/parser/cssNodes.js +1 -1
- package/lib/esm/parser/cssParser.js +32 -9
- package/lib/esm/parser/lessParser.js +6 -6
- package/lib/esm/parser/scssParser.js +6 -6
- package/lib/esm/services/cssCompletion.js +4 -11
- package/lib/esm/services/cssNavigation.js +6 -3
- package/lib/esm/services/lessCompletion.js +2 -1
- package/lib/esm/services/lint.js +2 -1
- package/lib/esm/services/scssCompletion.js +2 -1
- package/lib/esm/services/selectorPrinting.js +1 -2
- package/lib/umd/data/webCustomData.js +112 -116
- package/lib/umd/languageFacts/builtinData.js +1 -1
- package/lib/umd/languageFacts/colors.js +130 -7
- package/lib/umd/parser/cssNodes.js +1 -1
- package/lib/umd/parser/cssParser.js +32 -9
- package/lib/umd/parser/lessParser.js +6 -6
- package/lib/umd/parser/scssParser.js +6 -6
- package/lib/umd/services/cssCompletion.js +4 -11
- package/lib/umd/services/cssNavigation.js +6 -3
- package/lib/umd/services/lessCompletion.js +1 -1
- package/lib/umd/services/lint.js +1 -1
- package/lib/umd/services/scssCompletion.js +1 -1
- package/lib/umd/services/selectorPrinting.js +1 -2
- package/package.json +8 -8
|
@@ -117,7 +117,7 @@ export const basicShapeFunctions = {
|
|
|
117
117
|
'polygon()': 'Defines a polygon.'
|
|
118
118
|
};
|
|
119
119
|
export const units = {
|
|
120
|
-
'length': ['cap', 'ch', 'cm', 'cqb', 'cqh', 'cqi', 'cqmax', 'cqmin', 'cqw', 'dvb', 'dvh', 'dvi', 'dvw', 'em', 'ex', 'ic', 'in', 'lh', 'lvb', 'lvh', 'lvi', 'lvw', 'mm', 'pc', 'pt', 'px', 'q', 'rem', 'svb', 'svh', 'svi', 'svw', 'vb', 'vh', 'vi', 'vmax', 'vmin', 'vw'],
|
|
120
|
+
'length': ['cap', 'ch', 'cm', 'cqb', 'cqh', 'cqi', 'cqmax', 'cqmin', 'cqw', 'dvb', 'dvh', 'dvi', 'dvw', 'em', 'ex', 'ic', 'in', 'lh', 'lvb', 'lvh', 'lvi', 'lvw', 'mm', 'pc', 'pt', 'px', 'q', 'rcap', 'rch', 'rem', 'rex', 'ric', 'rlh', 'svb', 'svh', 'svi', 'svw', 'vb', 'vh', 'vi', 'vmax', 'vmin', 'vw'],
|
|
121
121
|
'angle': ['deg', 'rad', 'grad', 'turn'],
|
|
122
122
|
'time': ['ms', 's'],
|
|
123
123
|
'frequency': ['Hz', 'kHz'],
|
|
@@ -4,13 +4,130 @@
|
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
import * as nodes from '../parser/cssNodes';
|
|
6
6
|
import * as l10n from '@vscode/l10n';
|
|
7
|
+
const hexColorRegExp = /(^#([0-9A-F]{3}){1,2}$)|(^#([0-9A-F]{4}){1,2}$)/i;
|
|
7
8
|
export const colorFunctions = [
|
|
8
|
-
{
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
{
|
|
10
|
+
label: 'rgb',
|
|
11
|
+
func: 'rgb($red, $green, $blue)',
|
|
12
|
+
insertText: 'rgb(${1:red}, ${2:green}, ${3:blue})',
|
|
13
|
+
desc: l10n.t('Creates a Color from red, green, and blue values.')
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
label: 'rgba',
|
|
17
|
+
func: 'rgba($red, $green, $blue, $alpha)',
|
|
18
|
+
insertText: 'rgba(${1:red}, ${2:green}, ${3:blue}, ${4:alpha})',
|
|
19
|
+
desc: l10n.t('Creates a Color from red, green, blue, and alpha values.')
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
label: 'rgb relative',
|
|
23
|
+
func: 'rgb(from $color $red $green $blue)',
|
|
24
|
+
insertText: 'rgb(from ${1:color} ${2:r} ${3:g} ${4:b})',
|
|
25
|
+
desc: l10n.t('Creates a Color from the red, green, and blue values of another Color.')
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
label: 'hsl',
|
|
29
|
+
func: 'hsl($hue, $saturation, $lightness)',
|
|
30
|
+
insertText: 'hsl(${1:hue}, ${2:saturation}, ${3:lightness})',
|
|
31
|
+
desc: l10n.t('Creates a Color from hue, saturation, and lightness values.')
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
label: 'hsla',
|
|
35
|
+
func: 'hsla($hue, $saturation, $lightness, $alpha)',
|
|
36
|
+
insertText: 'hsla(${1:hue}, ${2:saturation}, ${3:lightness}, ${4:alpha})',
|
|
37
|
+
desc: l10n.t('Creates a Color from hue, saturation, lightness, and alpha values.')
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
label: 'hsl relative',
|
|
41
|
+
func: 'hsl(from $color $hue $saturation $lightness)',
|
|
42
|
+
insertText: 'hsl(from ${1:color} ${2:h} ${3:s} ${4:l})',
|
|
43
|
+
desc: l10n.t('Creates a Color from the hue, saturation, and lightness values of another Color.')
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
label: 'hwb',
|
|
47
|
+
func: 'hwb($hue $white $black)',
|
|
48
|
+
insertText: 'hwb(${1:hue} ${2:white} ${3:black})',
|
|
49
|
+
desc: l10n.t('Creates a Color from hue, white, and black values.')
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
label: 'hwb relative',
|
|
53
|
+
func: 'hwb(from $color $hue $white $black)',
|
|
54
|
+
insertText: 'hwb(from ${1:color} ${2:h} ${3:w} ${4:b})',
|
|
55
|
+
desc: l10n.t('Creates a Color from the hue, white, and black values of another Color.')
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
label: 'lab',
|
|
59
|
+
func: 'lab($lightness $a $b)',
|
|
60
|
+
insertText: 'lab(${1:lightness} ${2:a} ${3:b})',
|
|
61
|
+
desc: l10n.t('Creates a Color from lightness, a, and b values.')
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
label: 'lab relative',
|
|
65
|
+
func: 'lab(from $color $lightness $a $b)',
|
|
66
|
+
insertText: 'lab(from ${1:color} ${2:l} ${3:a} ${4:b})',
|
|
67
|
+
desc: l10n.t('Creates a Color from the lightness, a, and b values of another Color.')
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
label: 'oklab',
|
|
71
|
+
func: 'oklab($lightness $a $b)',
|
|
72
|
+
insertText: 'oklab(${1:lightness} ${2:a} ${3:b})',
|
|
73
|
+
desc: l10n.t('Creates a Color from lightness, a, and b values.')
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
label: 'oklab relative',
|
|
77
|
+
func: 'oklab(from $color $lightness $a $b)',
|
|
78
|
+
insertText: 'oklab(from ${1:color} ${2:l} ${3:a} ${4:b})',
|
|
79
|
+
desc: l10n.t('Creates a Color from the lightness, a, and b values of another Color.')
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
label: 'lch',
|
|
83
|
+
func: 'lch($lightness $chroma $hue)',
|
|
84
|
+
insertText: 'lch(${1:lightness} ${2:chroma} ${3:hue})',
|
|
85
|
+
desc: l10n.t('Creates a Color from lightness, chroma, and hue values.')
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
label: 'lch relative',
|
|
89
|
+
func: 'lch(from $color $lightness $chroma $hue)',
|
|
90
|
+
insertText: 'lch(from ${1:color} ${2:l} ${3:c} ${4:h})',
|
|
91
|
+
desc: l10n.t('Creates a Color from the lightness, chroma, and hue values of another Color.')
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
label: 'oklch',
|
|
95
|
+
func: 'oklch($lightness $chroma $hue)',
|
|
96
|
+
insertText: 'oklch(${1:lightness} ${2:chroma} ${3:hue})',
|
|
97
|
+
desc: l10n.t('Creates a Color from lightness, chroma, and hue values.')
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
label: 'oklch relative',
|
|
101
|
+
func: 'oklch(from $color $lightness $chroma $hue)',
|
|
102
|
+
insertText: 'oklch(from ${1:color} ${2:l} ${3:c} ${4:h})',
|
|
103
|
+
desc: l10n.t('Creates a Color from the lightness, chroma, and hue values of another Color.')
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
label: 'color',
|
|
107
|
+
func: 'color($color-space $red $green $blue)',
|
|
108
|
+
insertText: 'color(${1|srgb,srgb-linear,display-p3,a98-rgb,prophoto-rgb,rec2020,xyx,xyz-d50,xyz-d65|} ${2:red} ${3:green} ${4:blue})',
|
|
109
|
+
desc: l10n.t('Creates a Color in a specific color space from red, green, and blue values.')
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
label: 'color relative',
|
|
113
|
+
func: 'color(from $color $color-space $red $green $blue)',
|
|
114
|
+
insertText: 'color(from ${1:color} ${2|srgb,srgb-linear,display-p3,a98-rgb,prophoto-rgb,rec2020,xyx,xyz-d50,xyz-d65|} ${3:r} ${4:g} ${5:b})',
|
|
115
|
+
desc: l10n.t('Creates a Color in a specific color space from the red, green, and blue values of another Color.')
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
label: 'color-mix',
|
|
119
|
+
func: 'color-mix(in $color-space, $color $percentage, $color $percentage)',
|
|
120
|
+
insertText: 'color-mix(in ${1|srgb,srgb-linear,lab,oklab,xyz,xyz-d50,xyz-d65|}, ${3:color} ${4:percentage}, ${5:color} ${6:percentage})',
|
|
121
|
+
desc: l10n.t('Mix two colors together in a rectangular color space.')
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
label: 'color-mix hue',
|
|
125
|
+
func: 'color-mix(in $color-space $interpolation-method hue, $color $percentage, $color $percentage)',
|
|
126
|
+
insertText: 'color-mix(in ${1|hsl,hwb,lch,oklch|} ${2|shorter hue,longer hue,increasing hue,decreasing hue|}, ${3:color} ${4:percentage}, ${5:color} ${6:percentage})',
|
|
127
|
+
desc: l10n.t('Mix two colors together in a polar color space.')
|
|
128
|
+
},
|
|
13
129
|
];
|
|
130
|
+
const colorFunctionNameRegExp = /^(rgb|rgba|hsl|hsla|hwb)$/i;
|
|
14
131
|
export const colors = {
|
|
15
132
|
aliceblue: '#f0f8ff',
|
|
16
133
|
antiquewhite: '#faebd7',
|
|
@@ -161,10 +278,12 @@ export const colors = {
|
|
|
161
278
|
yellow: '#ffff00',
|
|
162
279
|
yellowgreen: '#9acd32'
|
|
163
280
|
};
|
|
281
|
+
const colorsRegExp = new RegExp(`^(${Object.keys(colors).join('|')})$`, "i");
|
|
164
282
|
export const colorKeywords = {
|
|
165
283
|
'currentColor': 'The value of the \'color\' property. The computed value of the \'currentColor\' keyword is the computed value of the \'color\' property. If the \'currentColor\' keyword is set on the \'color\' property itself, it is treated as \'color:inherit\' at parse time.',
|
|
166
284
|
'transparent': 'Fully transparent. This keyword can be considered a shorthand for rgba(0,0,0,0) which is its computed value.',
|
|
167
285
|
};
|
|
286
|
+
const colorKeywordsRegExp = new RegExp(`^(${Object.keys(colorKeywords).join('|')})$`, "i");
|
|
168
287
|
function getNumericValue(node, factor) {
|
|
169
288
|
const val = node.getText();
|
|
170
289
|
const m = val.match(/^([-+]?[0-9]*\.?[0-9]+)(%?)$/);
|
|
@@ -205,7 +324,10 @@ export function isColorConstructor(node) {
|
|
|
205
324
|
if (!name) {
|
|
206
325
|
return false;
|
|
207
326
|
}
|
|
208
|
-
return
|
|
327
|
+
return colorFunctionNameRegExp.test(name);
|
|
328
|
+
}
|
|
329
|
+
export function isColorString(s) {
|
|
330
|
+
return hexColorRegExp.test(s) || colorsRegExp.test(s) || colorKeywordsRegExp.test(s);
|
|
209
331
|
}
|
|
210
332
|
/**
|
|
211
333
|
* Returns true if the node is a color value - either
|
|
@@ -1197,7 +1197,7 @@ export class MixinContentDeclaration extends BodyDeclaration {
|
|
|
1197
1197
|
super(offset, length);
|
|
1198
1198
|
}
|
|
1199
1199
|
get type() {
|
|
1200
|
-
return NodeType.
|
|
1200
|
+
return NodeType.MixinContentDeclaration;
|
|
1201
1201
|
}
|
|
1202
1202
|
getParameters() {
|
|
1203
1203
|
if (!this.parameters) {
|
|
@@ -271,7 +271,7 @@ export class Parser {
|
|
|
271
271
|
|| this._parseFontFace()
|
|
272
272
|
|| this._parseKeyframe()
|
|
273
273
|
|| this._parseSupports(isNested)
|
|
274
|
-
|| this._parseLayer()
|
|
274
|
+
|| this._parseLayer(isNested)
|
|
275
275
|
|| this._parsePropertyAtRule()
|
|
276
276
|
|| this._parseViewPort()
|
|
277
277
|
|| this._parseNamespace()
|
|
@@ -306,14 +306,20 @@ export class Parser {
|
|
|
306
306
|
return this._parseBody(node, this._parseRuleSetDeclaration.bind(this));
|
|
307
307
|
}
|
|
308
308
|
_parseRuleSetDeclarationAtStatement() {
|
|
309
|
-
return this.
|
|
309
|
+
return this._parseMedia(true)
|
|
310
|
+
|| this._parseSupports(true)
|
|
311
|
+
|| this._parseLayer(true)
|
|
312
|
+
|| this._parseUnknownAtRule();
|
|
310
313
|
}
|
|
311
314
|
_parseRuleSetDeclaration() {
|
|
312
315
|
// https://www.w3.org/TR/css-syntax-3/#consume-a-list-of-declarations
|
|
313
316
|
if (this.peek(TokenType.AtKeyword)) {
|
|
314
317
|
return this._parseRuleSetDeclarationAtStatement();
|
|
315
318
|
}
|
|
316
|
-
|
|
319
|
+
if (!this.peek(TokenType.Ident)) {
|
|
320
|
+
return this._parseRuleset(true);
|
|
321
|
+
}
|
|
322
|
+
return this._tryParseRuleset(true) || this._parseDeclaration();
|
|
317
323
|
}
|
|
318
324
|
_needsSemicolonAfter(node) {
|
|
319
325
|
switch (node.type) {
|
|
@@ -395,9 +401,9 @@ export class Parser {
|
|
|
395
401
|
return hasContent ? this.finish(node) : null;
|
|
396
402
|
}
|
|
397
403
|
_parseDeclaration(stopTokens) {
|
|
398
|
-
const
|
|
399
|
-
if (
|
|
400
|
-
return
|
|
404
|
+
const customProperty = this._tryParseCustomPropertyDeclaration(stopTokens);
|
|
405
|
+
if (customProperty) {
|
|
406
|
+
return customProperty;
|
|
401
407
|
}
|
|
402
408
|
const node = this.create(nodes.Declaration);
|
|
403
409
|
if (!node.setProperty(this._parseProperty())) {
|
|
@@ -732,7 +738,7 @@ export class Parser {
|
|
|
732
738
|
}
|
|
733
739
|
return this._parseBody(node, this._parseDeclaration.bind(this));
|
|
734
740
|
}
|
|
735
|
-
_parseLayer() {
|
|
741
|
+
_parseLayer(isNested = false) {
|
|
736
742
|
// @layer layer-name {rules}
|
|
737
743
|
// @layer layer-name;
|
|
738
744
|
// @layer layer-name, layer-name, layer-name;
|
|
@@ -747,13 +753,22 @@ export class Parser {
|
|
|
747
753
|
node.setNames(names);
|
|
748
754
|
}
|
|
749
755
|
if ((!names || names.getChildren().length === 1) && this.peek(TokenType.CurlyL)) {
|
|
750
|
-
return this._parseBody(node, this.
|
|
756
|
+
return this._parseBody(node, this._parseLayerDeclaration.bind(this, isNested));
|
|
751
757
|
}
|
|
752
758
|
if (!this.accept(TokenType.SemiColon)) {
|
|
753
759
|
return this.finish(node, ParseError.SemiColonExpected);
|
|
754
760
|
}
|
|
755
761
|
return this.finish(node);
|
|
756
762
|
}
|
|
763
|
+
_parseLayerDeclaration(isNested = false) {
|
|
764
|
+
if (isNested) {
|
|
765
|
+
// if nested, the body can contain rulesets, but also declarations
|
|
766
|
+
return this._tryParseRuleset(true)
|
|
767
|
+
|| this._tryToParseDeclaration()
|
|
768
|
+
|| this._parseStylesheetStatement(true);
|
|
769
|
+
}
|
|
770
|
+
return this._parseStylesheetStatement(false);
|
|
771
|
+
}
|
|
757
772
|
_parseLayerNameList() {
|
|
758
773
|
const node = this.createNode(nodes.NodeType.LayerNameList);
|
|
759
774
|
if (!node.addChild(this._parseLayerName())) {
|
|
@@ -1251,7 +1266,7 @@ export class Parser {
|
|
|
1251
1266
|
// : element_name [ HASH | class | attrib | pseudo ]* | [ HASH | class | attrib | pseudo ]+ ;
|
|
1252
1267
|
const node = this.create(nodes.SimpleSelector);
|
|
1253
1268
|
let c = 0;
|
|
1254
|
-
if (node.addChild(this._parseElementName())) {
|
|
1269
|
+
if (node.addChild(this._parseElementName() || this._parseNestingSelector())) {
|
|
1255
1270
|
c++;
|
|
1256
1271
|
}
|
|
1257
1272
|
while ((c === 0 || !this.hasWhitespace()) && node.addChild(this._parseSimpleSelectorBody())) {
|
|
@@ -1259,6 +1274,14 @@ export class Parser {
|
|
|
1259
1274
|
}
|
|
1260
1275
|
return c > 0 ? this.finish(node) : null;
|
|
1261
1276
|
}
|
|
1277
|
+
_parseNestingSelector() {
|
|
1278
|
+
if (this.peekDelim('&')) {
|
|
1279
|
+
const node = this.createNode(nodes.NodeType.SelectorCombinator);
|
|
1280
|
+
this.consumeToken();
|
|
1281
|
+
return this.finish(node);
|
|
1282
|
+
}
|
|
1283
|
+
return null;
|
|
1284
|
+
}
|
|
1262
1285
|
_parseSimpleSelectorBody() {
|
|
1263
1286
|
return this._parsePseudo() || this._parseHash() || this._parseClass() || this._parseAttrib();
|
|
1264
1287
|
}
|
|
@@ -276,14 +276,14 @@ export class LESSParser extends cssParser.Parser {
|
|
|
276
276
|
|| this._parsePropertyAtRule() // @property
|
|
277
277
|
|| this._parseDetachedRuleSetMixin() // less detached ruleset mixin
|
|
278
278
|
|| this._parseVariableDeclaration() // Variable declarations
|
|
279
|
-
||
|
|
279
|
+
|| this._parseRuleSetDeclarationAtStatement();
|
|
280
280
|
}
|
|
281
281
|
return this._tryParseMixinDeclaration()
|
|
282
282
|
|| this._tryParseRuleset(true) // nested ruleset
|
|
283
283
|
|| this._tryParseMixinReference() // less mixin reference
|
|
284
284
|
|| this._parseFunction()
|
|
285
285
|
|| this._parseExtend() // less extend declaration
|
|
286
|
-
||
|
|
286
|
+
|| this._parseDeclaration(); // try css ruleset declaration as the last option
|
|
287
287
|
}
|
|
288
288
|
_parseKeyframeIdent() {
|
|
289
289
|
return this._parseIdent([nodes.ReferenceType.Keyframe]) || this._parseVariable();
|
|
@@ -292,9 +292,9 @@ export class LESSParser extends cssParser.Parser {
|
|
|
292
292
|
return this._parseDetachedRuleSetMixin() // less detached ruleset mixin
|
|
293
293
|
|| super._parseKeyframeSelector();
|
|
294
294
|
}
|
|
295
|
-
_parseSimpleSelectorBody() {
|
|
296
|
-
|
|
297
|
-
}
|
|
295
|
+
// public _parseSimpleSelectorBody(): nodes.Node | null {
|
|
296
|
+
// return this._parseNestingSelector() || super._parseSimpleSelectorBody();
|
|
297
|
+
// }
|
|
298
298
|
_parseSelector(isNested) {
|
|
299
299
|
// CSS Guards
|
|
300
300
|
const node = this.create(nodes.Selector);
|
|
@@ -314,7 +314,7 @@ export class LESSParser extends cssParser.Parser {
|
|
|
314
314
|
}
|
|
315
315
|
return hasContent ? this.finish(node) : null;
|
|
316
316
|
}
|
|
317
|
-
|
|
317
|
+
_parseNestingSelector() {
|
|
318
318
|
if (this.peekDelim('&')) {
|
|
319
319
|
const node = this.createNode(nodes.NodeType.SelectorCombinator);
|
|
320
320
|
this.consumeToken();
|
|
@@ -161,7 +161,7 @@ export class SCSSParser extends cssParser.Parser {
|
|
|
161
161
|
_parseTermExpression() {
|
|
162
162
|
return this._parseModuleMember() ||
|
|
163
163
|
this._parseVariable() ||
|
|
164
|
-
this.
|
|
164
|
+
this._parseNestingSelector() ||
|
|
165
165
|
//this._tryParsePrio() ||
|
|
166
166
|
super._parseTermExpression();
|
|
167
167
|
}
|
|
@@ -169,7 +169,7 @@ export class SCSSParser extends cssParser.Parser {
|
|
|
169
169
|
if (this.peek(scssScanner.InterpolationFunction)) {
|
|
170
170
|
const node = this.create(nodes.Interpolation);
|
|
171
171
|
this.consumeToken();
|
|
172
|
-
if (!node.addChild(this._parseExpr()) && !this.
|
|
172
|
+
if (!node.addChild(this._parseExpr()) && !this._parseNestingSelector()) {
|
|
173
173
|
if (this.accept(TokenType.CurlyR)) {
|
|
174
174
|
return this.finish(node);
|
|
175
175
|
}
|
|
@@ -219,11 +219,11 @@ export class SCSSParser extends cssParser.Parser {
|
|
|
219
219
|
|| this._parseSupports(true) // @supports
|
|
220
220
|
|| this._parseLayer() // @layer
|
|
221
221
|
|| this._parsePropertyAtRule() // @property
|
|
222
|
-
||
|
|
222
|
+
|| this._parseRuleSetDeclarationAtStatement();
|
|
223
223
|
}
|
|
224
224
|
return this._parseVariableDeclaration() // variable declaration
|
|
225
225
|
|| this._tryParseRuleset(true) // nested ruleset
|
|
226
|
-
||
|
|
226
|
+
|| this._parseDeclaration(); // try css ruleset declaration as last so in the error case, the ast will contain a declaration
|
|
227
227
|
}
|
|
228
228
|
_parseDeclaration(stopTokens) {
|
|
229
229
|
const custonProperty = this._tryParseCustomPropertyDeclaration(stopTokens);
|
|
@@ -282,9 +282,9 @@ export class SCSSParser extends cssParser.Parser {
|
|
|
282
282
|
return null;
|
|
283
283
|
}
|
|
284
284
|
_parseSimpleSelectorBody() {
|
|
285
|
-
return this.
|
|
285
|
+
return this._parseSelectorPlaceholder() || super._parseSimpleSelectorBody();
|
|
286
286
|
}
|
|
287
|
-
|
|
287
|
+
_parseNestingSelector() {
|
|
288
288
|
if (this.peekDelim('&')) {
|
|
289
289
|
const node = this.createNode(nodes.NodeType.SelectorCombinator);
|
|
290
290
|
this.consumeToken();
|
|
@@ -404,7 +404,7 @@ export class CSSCompletion {
|
|
|
404
404
|
kind: CompletionItemKind.Variable,
|
|
405
405
|
sortText: SortTexts.Variable
|
|
406
406
|
};
|
|
407
|
-
if (typeof completionItem.documentation === 'string' && isColorString(completionItem.documentation)) {
|
|
407
|
+
if (typeof completionItem.documentation === 'string' && languageFacts.isColorString(completionItem.documentation)) {
|
|
408
408
|
completionItem.kind = CompletionItemKind.Color;
|
|
409
409
|
}
|
|
410
410
|
if (symbol.node.type === nodes.NodeType.FunctionParameter) {
|
|
@@ -429,7 +429,7 @@ export class CSSCompletion {
|
|
|
429
429
|
textEdit: TextEdit.replace(this.getCompletionRange(null), symbol.name),
|
|
430
430
|
kind: CompletionItemKind.Variable
|
|
431
431
|
};
|
|
432
|
-
if (typeof completionItem.documentation === 'string' && isColorString(completionItem.documentation)) {
|
|
432
|
+
if (typeof completionItem.documentation === 'string' && languageFacts.isColorString(completionItem.documentation)) {
|
|
433
433
|
completionItem.kind = CompletionItemKind.Color;
|
|
434
434
|
}
|
|
435
435
|
result.items.push(completionItem);
|
|
@@ -517,14 +517,11 @@ export class CSSCompletion {
|
|
|
517
517
|
});
|
|
518
518
|
}
|
|
519
519
|
for (const p of languageFacts.colorFunctions) {
|
|
520
|
-
let tabStop = 1;
|
|
521
|
-
const replaceFunction = (_match, p1) => '${' + tabStop++ + ':' + p1 + '}';
|
|
522
|
-
const insertText = p.func.replace(/\[?\$(\w+)\]?/g, replaceFunction);
|
|
523
520
|
result.items.push({
|
|
524
|
-
label: p.
|
|
521
|
+
label: p.label,
|
|
525
522
|
detail: p.func,
|
|
526
523
|
documentation: p.desc,
|
|
527
|
-
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), insertText),
|
|
524
|
+
textEdit: TextEdit.replace(this.getCompletionRange(existingNode), p.insertText),
|
|
528
525
|
insertTextFormat: SnippetFormat,
|
|
529
526
|
kind: CompletionItemKind.Function
|
|
530
527
|
});
|
|
@@ -1057,7 +1054,3 @@ function getCurrentWord(document, offset) {
|
|
|
1057
1054
|
}
|
|
1058
1055
|
return text.substring(i + 1, offset);
|
|
1059
1056
|
}
|
|
1060
|
-
function isColorString(s) {
|
|
1061
|
-
// From https://stackoverflow.com/questions/8027423/how-to-check-if-a-string-is-a-valid-hex-color-representation/8027444
|
|
1062
|
-
return (s.toLowerCase() in languageFacts.colors) || /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(s);
|
|
1063
|
-
}
|
|
@@ -173,7 +173,7 @@ export class CSSNavigation {
|
|
|
173
173
|
const addSymbolInformation = (name, kind, symbolNodeOrRange) => {
|
|
174
174
|
const range = symbolNodeOrRange instanceof nodes.Node ? getRange(symbolNodeOrRange, document) : symbolNodeOrRange;
|
|
175
175
|
const entry = {
|
|
176
|
-
name,
|
|
176
|
+
name: name || l10n.t('<undefined>'),
|
|
177
177
|
kind,
|
|
178
178
|
location: Location.create(document.uri, range)
|
|
179
179
|
};
|
|
@@ -187,9 +187,12 @@ export class CSSNavigation {
|
|
|
187
187
|
const parents = [];
|
|
188
188
|
const addDocumentSymbol = (name, kind, symbolNodeOrRange, nameNodeOrRange, bodyNode) => {
|
|
189
189
|
const range = symbolNodeOrRange instanceof nodes.Node ? getRange(symbolNodeOrRange, document) : symbolNodeOrRange;
|
|
190
|
-
|
|
190
|
+
let selectionRange = nameNodeOrRange instanceof nodes.Node ? getRange(nameNodeOrRange, document) : nameNodeOrRange;
|
|
191
|
+
if (!selectionRange || !containsRange(range, selectionRange)) {
|
|
192
|
+
selectionRange = Range.create(range.start, range.start);
|
|
193
|
+
}
|
|
191
194
|
const entry = {
|
|
192
|
-
name,
|
|
195
|
+
name: name || l10n.t('<undefined>'),
|
|
193
196
|
kind,
|
|
194
197
|
range,
|
|
195
198
|
selectionRange
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { CSSCompletion } from './cssCompletion';
|
|
7
7
|
import { CompletionItemKind, InsertTextFormat, TextEdit } from '../cssLanguageTypes';
|
|
8
8
|
import * as l10n from '@vscode/l10n';
|
|
9
|
-
|
|
9
|
+
class LESSCompletion extends CSSCompletion {
|
|
10
10
|
constructor(lsOptions, cssDataManager) {
|
|
11
11
|
super('@', lsOptions, cssDataManager);
|
|
12
12
|
}
|
|
@@ -375,3 +375,4 @@ LESSCompletion.colorProposals = [
|
|
|
375
375
|
'example': 'negation(@color1, @color2);'
|
|
376
376
|
}
|
|
377
377
|
];
|
|
378
|
+
export { LESSCompletion };
|
package/lib/esm/services/lint.js
CHANGED
|
@@ -25,7 +25,7 @@ class NodesByRootMap {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
-
|
|
28
|
+
class LintVisitor {
|
|
29
29
|
static entries(node, document, settings, cssDataManager, entryFilter) {
|
|
30
30
|
const visitor = new LintVisitor(document, settings, cssDataManager);
|
|
31
31
|
node.acceptVisitor(visitor);
|
|
@@ -562,3 +562,4 @@ LintVisitor.prefixes = [
|
|
|
562
562
|
'-ms-', '-moz-', '-o-', '-webkit-', // Quite common
|
|
563
563
|
// '-xv-', '-atsc-', '-wap-', '-khtml-', 'mso-', 'prince-', '-ah-', '-hp-', '-ro-', '-rim-', '-tc-' // Quite un-common
|
|
564
564
|
];
|
|
565
|
+
export { LintVisitor };
|
|
@@ -8,7 +8,7 @@ import * as nodes from '../parser/cssNodes';
|
|
|
8
8
|
import { CompletionItemKind, TextEdit, InsertTextFormat } from '../cssLanguageTypes';
|
|
9
9
|
import * as l10n from '@vscode/l10n';
|
|
10
10
|
const sassDocumentationName = l10n.t('Sass documentation');
|
|
11
|
-
|
|
11
|
+
class SCSSCompletion extends CSSCompletion {
|
|
12
12
|
constructor(lsServiceOptions, cssDataManager) {
|
|
13
13
|
super('$', lsServiceOptions, cssDataManager);
|
|
14
14
|
addReferencesToDocumentation(SCSSCompletion.scssModuleLoaders);
|
|
@@ -333,6 +333,7 @@ SCSSCompletion.scssModuleBuiltIns = [
|
|
|
333
333
|
references: [{ name: sassDocumentationName, url: 'https://sass-lang.com/documentation/modules/meta' }]
|
|
334
334
|
},
|
|
335
335
|
];
|
|
336
|
+
export { SCSSCompletion };
|
|
336
337
|
/**
|
|
337
338
|
* Todo @Pine: Remove this and do it through custom data
|
|
338
339
|
*/
|
|
@@ -402,8 +402,7 @@ export class SelectorPrinting {
|
|
|
402
402
|
return specificity;
|
|
403
403
|
};
|
|
404
404
|
const specificity = calculateScore(node);
|
|
405
|
-
|
|
406
|
-
return l10n.t("[Selector Specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity): ({0}, {1}, {2})", specificity.id, specificity.attr, specificity.tag);
|
|
405
|
+
return `[${l10n.t("Selector Specificity")}](https://developer.mozilla.org/docs/Web/CSS/Specificity): (${specificity.id}, ${specificity.attr}, ${specificity.tag})`;
|
|
407
406
|
}
|
|
408
407
|
}
|
|
409
408
|
class SelectorElementBuilder {
|