vscode-css-languageservice 6.2.5 → 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/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 +23 -9
- package/lib/esm/services/cssCompletion.js +4 -11
- 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 +23 -9
- package/lib/umd/services/cssCompletion.js +4 -11
- package/package.json +6 -6
|
@@ -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,15 +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
|
-
|
|
317
|
-
|
|
319
|
+
if (!this.peek(TokenType.Ident)) {
|
|
320
|
+
return this._parseRuleset(true);
|
|
321
|
+
}
|
|
322
|
+
return this._tryParseRuleset(true) || this._parseDeclaration();
|
|
318
323
|
}
|
|
319
324
|
_needsSemicolonAfter(node) {
|
|
320
325
|
switch (node.type) {
|
|
@@ -396,9 +401,9 @@ export class Parser {
|
|
|
396
401
|
return hasContent ? this.finish(node) : null;
|
|
397
402
|
}
|
|
398
403
|
_parseDeclaration(stopTokens) {
|
|
399
|
-
const
|
|
400
|
-
if (
|
|
401
|
-
return
|
|
404
|
+
const customProperty = this._tryParseCustomPropertyDeclaration(stopTokens);
|
|
405
|
+
if (customProperty) {
|
|
406
|
+
return customProperty;
|
|
402
407
|
}
|
|
403
408
|
const node = this.create(nodes.Declaration);
|
|
404
409
|
if (!node.setProperty(this._parseProperty())) {
|
|
@@ -733,7 +738,7 @@ export class Parser {
|
|
|
733
738
|
}
|
|
734
739
|
return this._parseBody(node, this._parseDeclaration.bind(this));
|
|
735
740
|
}
|
|
736
|
-
_parseLayer() {
|
|
741
|
+
_parseLayer(isNested = false) {
|
|
737
742
|
// @layer layer-name {rules}
|
|
738
743
|
// @layer layer-name;
|
|
739
744
|
// @layer layer-name, layer-name, layer-name;
|
|
@@ -748,13 +753,22 @@ export class Parser {
|
|
|
748
753
|
node.setNames(names);
|
|
749
754
|
}
|
|
750
755
|
if ((!names || names.getChildren().length === 1) && this.peek(TokenType.CurlyL)) {
|
|
751
|
-
return this._parseBody(node, this.
|
|
756
|
+
return this._parseBody(node, this._parseLayerDeclaration.bind(this, isNested));
|
|
752
757
|
}
|
|
753
758
|
if (!this.accept(TokenType.SemiColon)) {
|
|
754
759
|
return this.finish(node, ParseError.SemiColonExpected);
|
|
755
760
|
}
|
|
756
761
|
return this.finish(node);
|
|
757
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
|
+
}
|
|
758
772
|
_parseLayerNameList() {
|
|
759
773
|
const node = this.createNode(nodes.NodeType.LayerNameList);
|
|
760
774
|
if (!node.addChild(this._parseLayerName())) {
|
|
@@ -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
|
-
}
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
'polygon()': 'Defines a polygon.'
|
|
129
129
|
};
|
|
130
130
|
exports.units = {
|
|
131
|
-
'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'],
|
|
131
|
+
'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'],
|
|
132
132
|
'angle': ['deg', 'rad', 'grad', 'turn'],
|
|
133
133
|
'time': ['ms', 's'],
|
|
134
134
|
'frequency': ['Hz', 'kHz'],
|
|
@@ -13,16 +13,133 @@
|
|
|
13
13
|
})(function (require, exports) {
|
|
14
14
|
"use strict";
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.getColorValue = exports.hwbFromColor = exports.colorFromHWB = exports.hslFromColor = exports.colorFromHSL = exports.colorFrom256RGB = exports.colorFromHex = exports.hexDigit = exports.isColorValue = exports.isColorConstructor = exports.colorKeywords = exports.colors = exports.colorFunctions = void 0;
|
|
16
|
+
exports.getColorValue = exports.hwbFromColor = exports.colorFromHWB = exports.hslFromColor = exports.colorFromHSL = exports.colorFrom256RGB = exports.colorFromHex = exports.hexDigit = exports.isColorValue = exports.isColorString = exports.isColorConstructor = exports.colorKeywords = exports.colors = exports.colorFunctions = void 0;
|
|
17
17
|
const nodes = require("../parser/cssNodes");
|
|
18
18
|
const l10n = require("@vscode/l10n");
|
|
19
|
+
const hexColorRegExp = /(^#([0-9A-F]{3}){1,2}$)|(^#([0-9A-F]{4}){1,2}$)/i;
|
|
19
20
|
exports.colorFunctions = [
|
|
20
|
-
{
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
{
|
|
22
|
+
label: 'rgb',
|
|
23
|
+
func: 'rgb($red, $green, $blue)',
|
|
24
|
+
insertText: 'rgb(${1:red}, ${2:green}, ${3:blue})',
|
|
25
|
+
desc: l10n.t('Creates a Color from red, green, and blue values.')
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
label: 'rgba',
|
|
29
|
+
func: 'rgba($red, $green, $blue, $alpha)',
|
|
30
|
+
insertText: 'rgba(${1:red}, ${2:green}, ${3:blue}, ${4:alpha})',
|
|
31
|
+
desc: l10n.t('Creates a Color from red, green, blue, and alpha values.')
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
label: 'rgb relative',
|
|
35
|
+
func: 'rgb(from $color $red $green $blue)',
|
|
36
|
+
insertText: 'rgb(from ${1:color} ${2:r} ${3:g} ${4:b})',
|
|
37
|
+
desc: l10n.t('Creates a Color from the red, green, and blue values of another Color.')
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
label: 'hsl',
|
|
41
|
+
func: 'hsl($hue, $saturation, $lightness)',
|
|
42
|
+
insertText: 'hsl(${1:hue}, ${2:saturation}, ${3:lightness})',
|
|
43
|
+
desc: l10n.t('Creates a Color from hue, saturation, and lightness values.')
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
label: 'hsla',
|
|
47
|
+
func: 'hsla($hue, $saturation, $lightness, $alpha)',
|
|
48
|
+
insertText: 'hsla(${1:hue}, ${2:saturation}, ${3:lightness}, ${4:alpha})',
|
|
49
|
+
desc: l10n.t('Creates a Color from hue, saturation, lightness, and alpha values.')
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
label: 'hsl relative',
|
|
53
|
+
func: 'hsl(from $color $hue $saturation $lightness)',
|
|
54
|
+
insertText: 'hsl(from ${1:color} ${2:h} ${3:s} ${4:l})',
|
|
55
|
+
desc: l10n.t('Creates a Color from the hue, saturation, and lightness values of another Color.')
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
label: 'hwb',
|
|
59
|
+
func: 'hwb($hue $white $black)',
|
|
60
|
+
insertText: 'hwb(${1:hue} ${2:white} ${3:black})',
|
|
61
|
+
desc: l10n.t('Creates a Color from hue, white, and black values.')
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
label: 'hwb relative',
|
|
65
|
+
func: 'hwb(from $color $hue $white $black)',
|
|
66
|
+
insertText: 'hwb(from ${1:color} ${2:h} ${3:w} ${4:b})',
|
|
67
|
+
desc: l10n.t('Creates a Color from the hue, white, and black values of another Color.')
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
label: 'lab',
|
|
71
|
+
func: 'lab($lightness $a $b)',
|
|
72
|
+
insertText: 'lab(${1:lightness} ${2:a} ${3:b})',
|
|
73
|
+
desc: l10n.t('Creates a Color from lightness, a, and b values.')
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
label: 'lab relative',
|
|
77
|
+
func: 'lab(from $color $lightness $a $b)',
|
|
78
|
+
insertText: 'lab(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: 'oklab',
|
|
83
|
+
func: 'oklab($lightness $a $b)',
|
|
84
|
+
insertText: 'oklab(${1:lightness} ${2:a} ${3:b})',
|
|
85
|
+
desc: l10n.t('Creates a Color from lightness, a, and b values.')
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
label: 'oklab relative',
|
|
89
|
+
func: 'oklab(from $color $lightness $a $b)',
|
|
90
|
+
insertText: 'oklab(from ${1:color} ${2:l} ${3:a} ${4:b})',
|
|
91
|
+
desc: l10n.t('Creates a Color from the lightness, a, and b values of another Color.')
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
label: 'lch',
|
|
95
|
+
func: 'lch($lightness $chroma $hue)',
|
|
96
|
+
insertText: 'lch(${1:lightness} ${2:chroma} ${3:hue})',
|
|
97
|
+
desc: l10n.t('Creates a Color from lightness, chroma, and hue values.')
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
label: 'lch relative',
|
|
101
|
+
func: 'lch(from $color $lightness $chroma $hue)',
|
|
102
|
+
insertText: 'lch(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: 'oklch',
|
|
107
|
+
func: 'oklch($lightness $chroma $hue)',
|
|
108
|
+
insertText: 'oklch(${1:lightness} ${2:chroma} ${3:hue})',
|
|
109
|
+
desc: l10n.t('Creates a Color from lightness, chroma, and hue values.')
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
label: 'oklch relative',
|
|
113
|
+
func: 'oklch(from $color $lightness $chroma $hue)',
|
|
114
|
+
insertText: 'oklch(from ${1:color} ${2:l} ${3:c} ${4:h})',
|
|
115
|
+
desc: l10n.t('Creates a Color from the lightness, chroma, and hue values of another Color.')
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
label: 'color',
|
|
119
|
+
func: 'color($color-space $red $green $blue)',
|
|
120
|
+
insertText: 'color(${1|srgb,srgb-linear,display-p3,a98-rgb,prophoto-rgb,rec2020,xyx,xyz-d50,xyz-d65|} ${2:red} ${3:green} ${4:blue})',
|
|
121
|
+
desc: l10n.t('Creates a Color in a specific color space from red, green, and blue values.')
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
label: 'color relative',
|
|
125
|
+
func: 'color(from $color $color-space $red $green $blue)',
|
|
126
|
+
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})',
|
|
127
|
+
desc: l10n.t('Creates a Color in a specific color space from the red, green, and blue values of another Color.')
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
label: 'color-mix',
|
|
131
|
+
func: 'color-mix(in $color-space, $color $percentage, $color $percentage)',
|
|
132
|
+
insertText: 'color-mix(in ${1|srgb,srgb-linear,lab,oklab,xyz,xyz-d50,xyz-d65|}, ${3:color} ${4:percentage}, ${5:color} ${6:percentage})',
|
|
133
|
+
desc: l10n.t('Mix two colors together in a rectangular color space.')
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
label: 'color-mix hue',
|
|
137
|
+
func: 'color-mix(in $color-space $interpolation-method hue, $color $percentage, $color $percentage)',
|
|
138
|
+
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})',
|
|
139
|
+
desc: l10n.t('Mix two colors together in a polar color space.')
|
|
140
|
+
},
|
|
25
141
|
];
|
|
142
|
+
const colorFunctionNameRegExp = /^(rgb|rgba|hsl|hsla|hwb)$/i;
|
|
26
143
|
exports.colors = {
|
|
27
144
|
aliceblue: '#f0f8ff',
|
|
28
145
|
antiquewhite: '#faebd7',
|
|
@@ -173,10 +290,12 @@
|
|
|
173
290
|
yellow: '#ffff00',
|
|
174
291
|
yellowgreen: '#9acd32'
|
|
175
292
|
};
|
|
293
|
+
const colorsRegExp = new RegExp(`^(${Object.keys(exports.colors).join('|')})$`, "i");
|
|
176
294
|
exports.colorKeywords = {
|
|
177
295
|
'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.',
|
|
178
296
|
'transparent': 'Fully transparent. This keyword can be considered a shorthand for rgba(0,0,0,0) which is its computed value.',
|
|
179
297
|
};
|
|
298
|
+
const colorKeywordsRegExp = new RegExp(`^(${Object.keys(exports.colorKeywords).join('|')})$`, "i");
|
|
180
299
|
function getNumericValue(node, factor) {
|
|
181
300
|
const val = node.getText();
|
|
182
301
|
const m = val.match(/^([-+]?[0-9]*\.?[0-9]+)(%?)$/);
|
|
@@ -217,9 +336,13 @@
|
|
|
217
336
|
if (!name) {
|
|
218
337
|
return false;
|
|
219
338
|
}
|
|
220
|
-
return
|
|
339
|
+
return colorFunctionNameRegExp.test(name);
|
|
221
340
|
}
|
|
222
341
|
exports.isColorConstructor = isColorConstructor;
|
|
342
|
+
function isColorString(s) {
|
|
343
|
+
return hexColorRegExp.test(s) || colorsRegExp.test(s) || colorKeywordsRegExp.test(s);
|
|
344
|
+
}
|
|
345
|
+
exports.isColorString = isColorString;
|
|
223
346
|
/**
|
|
224
347
|
* Returns true if the node is a color value - either
|
|
225
348
|
* defined a hex number, as rgb or rgba function, or
|
|
@@ -282,7 +282,7 @@
|
|
|
282
282
|
|| this._parseFontFace()
|
|
283
283
|
|| this._parseKeyframe()
|
|
284
284
|
|| this._parseSupports(isNested)
|
|
285
|
-
|| this._parseLayer()
|
|
285
|
+
|| this._parseLayer(isNested)
|
|
286
286
|
|| this._parsePropertyAtRule()
|
|
287
287
|
|| this._parseViewPort()
|
|
288
288
|
|| this._parseNamespace()
|
|
@@ -317,15 +317,20 @@
|
|
|
317
317
|
return this._parseBody(node, this._parseRuleSetDeclaration.bind(this));
|
|
318
318
|
}
|
|
319
319
|
_parseRuleSetDeclarationAtStatement() {
|
|
320
|
-
return this.
|
|
320
|
+
return this._parseMedia(true)
|
|
321
|
+
|| this._parseSupports(true)
|
|
322
|
+
|| this._parseLayer(true)
|
|
323
|
+
|| this._parseUnknownAtRule();
|
|
321
324
|
}
|
|
322
325
|
_parseRuleSetDeclaration() {
|
|
323
326
|
// https://www.w3.org/TR/css-syntax-3/#consume-a-list-of-declarations
|
|
324
327
|
if (this.peek(cssScanner_1.TokenType.AtKeyword)) {
|
|
325
328
|
return this._parseRuleSetDeclarationAtStatement();
|
|
326
329
|
}
|
|
327
|
-
|
|
328
|
-
|
|
330
|
+
if (!this.peek(cssScanner_1.TokenType.Ident)) {
|
|
331
|
+
return this._parseRuleset(true);
|
|
332
|
+
}
|
|
333
|
+
return this._tryParseRuleset(true) || this._parseDeclaration();
|
|
329
334
|
}
|
|
330
335
|
_needsSemicolonAfter(node) {
|
|
331
336
|
switch (node.type) {
|
|
@@ -407,9 +412,9 @@
|
|
|
407
412
|
return hasContent ? this.finish(node) : null;
|
|
408
413
|
}
|
|
409
414
|
_parseDeclaration(stopTokens) {
|
|
410
|
-
const
|
|
411
|
-
if (
|
|
412
|
-
return
|
|
415
|
+
const customProperty = this._tryParseCustomPropertyDeclaration(stopTokens);
|
|
416
|
+
if (customProperty) {
|
|
417
|
+
return customProperty;
|
|
413
418
|
}
|
|
414
419
|
const node = this.create(nodes.Declaration);
|
|
415
420
|
if (!node.setProperty(this._parseProperty())) {
|
|
@@ -744,7 +749,7 @@
|
|
|
744
749
|
}
|
|
745
750
|
return this._parseBody(node, this._parseDeclaration.bind(this));
|
|
746
751
|
}
|
|
747
|
-
_parseLayer() {
|
|
752
|
+
_parseLayer(isNested = false) {
|
|
748
753
|
// @layer layer-name {rules}
|
|
749
754
|
// @layer layer-name;
|
|
750
755
|
// @layer layer-name, layer-name, layer-name;
|
|
@@ -759,13 +764,22 @@
|
|
|
759
764
|
node.setNames(names);
|
|
760
765
|
}
|
|
761
766
|
if ((!names || names.getChildren().length === 1) && this.peek(cssScanner_1.TokenType.CurlyL)) {
|
|
762
|
-
return this._parseBody(node, this.
|
|
767
|
+
return this._parseBody(node, this._parseLayerDeclaration.bind(this, isNested));
|
|
763
768
|
}
|
|
764
769
|
if (!this.accept(cssScanner_1.TokenType.SemiColon)) {
|
|
765
770
|
return this.finish(node, cssErrors_1.ParseError.SemiColonExpected);
|
|
766
771
|
}
|
|
767
772
|
return this.finish(node);
|
|
768
773
|
}
|
|
774
|
+
_parseLayerDeclaration(isNested = false) {
|
|
775
|
+
if (isNested) {
|
|
776
|
+
// if nested, the body can contain rulesets, but also declarations
|
|
777
|
+
return this._tryParseRuleset(true)
|
|
778
|
+
|| this._tryToParseDeclaration()
|
|
779
|
+
|| this._parseStylesheetStatement(true);
|
|
780
|
+
}
|
|
781
|
+
return this._parseStylesheetStatement(false);
|
|
782
|
+
}
|
|
769
783
|
_parseLayerNameList() {
|
|
770
784
|
const node = this.createNode(nodes.NodeType.LayerNameList);
|
|
771
785
|
if (!node.addChild(this._parseLayerName())) {
|
|
@@ -415,7 +415,7 @@
|
|
|
415
415
|
kind: cssLanguageTypes_1.CompletionItemKind.Variable,
|
|
416
416
|
sortText: SortTexts.Variable
|
|
417
417
|
};
|
|
418
|
-
if (typeof completionItem.documentation === 'string' && isColorString(completionItem.documentation)) {
|
|
418
|
+
if (typeof completionItem.documentation === 'string' && languageFacts.isColorString(completionItem.documentation)) {
|
|
419
419
|
completionItem.kind = cssLanguageTypes_1.CompletionItemKind.Color;
|
|
420
420
|
}
|
|
421
421
|
if (symbol.node.type === nodes.NodeType.FunctionParameter) {
|
|
@@ -440,7 +440,7 @@
|
|
|
440
440
|
textEdit: cssLanguageTypes_1.TextEdit.replace(this.getCompletionRange(null), symbol.name),
|
|
441
441
|
kind: cssLanguageTypes_1.CompletionItemKind.Variable
|
|
442
442
|
};
|
|
443
|
-
if (typeof completionItem.documentation === 'string' && isColorString(completionItem.documentation)) {
|
|
443
|
+
if (typeof completionItem.documentation === 'string' && languageFacts.isColorString(completionItem.documentation)) {
|
|
444
444
|
completionItem.kind = cssLanguageTypes_1.CompletionItemKind.Color;
|
|
445
445
|
}
|
|
446
446
|
result.items.push(completionItem);
|
|
@@ -528,14 +528,11 @@
|
|
|
528
528
|
});
|
|
529
529
|
}
|
|
530
530
|
for (const p of languageFacts.colorFunctions) {
|
|
531
|
-
let tabStop = 1;
|
|
532
|
-
const replaceFunction = (_match, p1) => '${' + tabStop++ + ':' + p1 + '}';
|
|
533
|
-
const insertText = p.func.replace(/\[?\$(\w+)\]?/g, replaceFunction);
|
|
534
531
|
result.items.push({
|
|
535
|
-
label: p.
|
|
532
|
+
label: p.label,
|
|
536
533
|
detail: p.func,
|
|
537
534
|
documentation: p.desc,
|
|
538
|
-
textEdit: cssLanguageTypes_1.TextEdit.replace(this.getCompletionRange(existingNode), insertText),
|
|
535
|
+
textEdit: cssLanguageTypes_1.TextEdit.replace(this.getCompletionRange(existingNode), p.insertText),
|
|
539
536
|
insertTextFormat: SnippetFormat,
|
|
540
537
|
kind: cssLanguageTypes_1.CompletionItemKind.Function
|
|
541
538
|
});
|
|
@@ -1069,8 +1066,4 @@
|
|
|
1069
1066
|
}
|
|
1070
1067
|
return text.substring(i + 1, offset);
|
|
1071
1068
|
}
|
|
1072
|
-
function isColorString(s) {
|
|
1073
|
-
// From https://stackoverflow.com/questions/8027423/how-to-check-if-a-string-is-a-valid-hex-color-representation/8027444
|
|
1074
|
-
return (s.toLowerCase() in languageFacts.colors) || /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(s);
|
|
1075
|
-
}
|
|
1076
1069
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vscode-css-languageservice",
|
|
3
|
-
"version": "6.2.
|
|
3
|
+
"version": "6.2.6",
|
|
4
4
|
"description": "Language service for CSS, LESS and SCSS",
|
|
5
5
|
"main": "./lib/umd/cssLanguageService.js",
|
|
6
6
|
"typings": "./lib/umd/cssLanguageService",
|
|
@@ -17,18 +17,18 @@
|
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@types/mocha": "^10.0.1",
|
|
19
19
|
"@types/node": "16.x",
|
|
20
|
-
"@typescript-eslint/eslint-plugin": "^5.59.
|
|
21
|
-
"@typescript-eslint/parser": "^5.59.
|
|
20
|
+
"@typescript-eslint/eslint-plugin": "^5.59.7",
|
|
21
|
+
"@typescript-eslint/parser": "^5.59.7",
|
|
22
22
|
"@vscode/web-custom-data": "^0.4.6",
|
|
23
|
-
"eslint": "^8.
|
|
23
|
+
"eslint": "^8.41.0",
|
|
24
24
|
"js-beautify": "^1.14.7",
|
|
25
25
|
"mocha": "^10.2.0",
|
|
26
|
-
"rimraf": "^5.0.
|
|
26
|
+
"rimraf": "^5.0.1",
|
|
27
27
|
"source-map-support": "^0.5.21",
|
|
28
28
|
"typescript": "^5.0.4"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@vscode/l10n": "^0.0.
|
|
31
|
+
"@vscode/l10n": "^0.0.14",
|
|
32
32
|
"vscode-languageserver-textdocument": "^1.0.8",
|
|
33
33
|
"vscode-languageserver-types": "^3.17.3",
|
|
34
34
|
"vscode-uri": "^3.0.7"
|