vscode-css-languageservice 6.1.0 → 6.2.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 +4 -0
- package/README.md +4 -3
- package/lib/esm/beautify/beautify-css.js +1 -1
- package/lib/esm/cssLanguageService.d.ts +2 -1
- package/lib/esm/cssLanguageService.js +1 -0
- package/lib/esm/cssLanguageTypes.d.ts +2 -2
- package/lib/esm/data/webCustomData.js +3502 -310
- package/lib/esm/languageFacts/colors.js +6 -7
- package/lib/esm/parser/cssErrors.js +34 -35
- package/lib/esm/parser/cssNodes.js +25 -4
- package/lib/esm/parser/cssParser.js +31 -16
- package/lib/esm/parser/lessParser.js +1 -0
- package/lib/esm/parser/scssErrors.js +4 -5
- package/lib/esm/parser/scssParser.js +4 -0
- package/lib/esm/services/cssCodeActions.js +2 -3
- package/lib/esm/services/cssCompletion.js +13 -4
- package/lib/esm/services/cssNavigation.js +44 -25
- package/lib/esm/services/lessCompletion.js +58 -59
- package/lib/esm/services/lint.js +64 -18
- package/lib/esm/services/lintRules.js +21 -22
- package/lib/esm/services/scssCompletion.js +107 -107
- package/lib/esm/services/scssNavigation.js +35 -57
- package/lib/esm/services/selectorPrinting.js +2 -3
- package/lib/umd/beautify/beautify-css.js +1 -1
- package/lib/umd/cssLanguageService.d.ts +2 -1
- package/lib/umd/cssLanguageService.js +1 -0
- package/lib/umd/cssLanguageTypes.d.ts +2 -2
- package/lib/umd/data/webCustomData.js +3502 -310
- package/lib/umd/languageFacts/colors.js +7 -8
- package/lib/umd/parser/cssErrors.js +35 -36
- package/lib/umd/parser/cssNodes.js +27 -5
- package/lib/umd/parser/cssParser.js +31 -16
- package/lib/umd/parser/lessParser.js +1 -0
- package/lib/umd/parser/scssErrors.js +5 -6
- package/lib/umd/parser/scssParser.js +4 -0
- package/lib/umd/services/cssCodeActions.js +3 -4
- package/lib/umd/services/cssCompletion.js +14 -5
- package/lib/umd/services/cssNavigation.js +45 -26
- package/lib/umd/services/lessCompletion.js +59 -60
- package/lib/umd/services/lint.js +65 -19
- package/lib/umd/services/lintRules.js +22 -23
- package/lib/umd/services/scssCompletion.js +108 -108
- package/lib/umd/services/scssNavigation.js +34 -56
- package/lib/umd/services/selectorPrinting.js +3 -4
- package/package.json +13 -16
|
@@ -3,14 +3,13 @@
|
|
|
3
3
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
import * as nodes from '../parser/cssNodes';
|
|
6
|
-
import * as
|
|
7
|
-
const localize = nls.loadMessageBundle();
|
|
6
|
+
import * as l10n from '@vscode/l10n';
|
|
8
7
|
export const colorFunctions = [
|
|
9
|
-
{ func: 'rgb($red, $green, $blue)', desc:
|
|
10
|
-
{ func: 'rgba($red, $green, $blue, $alpha)', desc:
|
|
11
|
-
{ func: 'hsl($hue, $saturation, $lightness)', desc:
|
|
12
|
-
{ func: 'hsla($hue, $saturation, $lightness, $alpha)', desc:
|
|
13
|
-
{ func: 'hwb($hue $white $black)', desc:
|
|
8
|
+
{ func: 'rgb($red, $green, $blue)', desc: l10n.t('Creates a Color from red, green, and blue values.') },
|
|
9
|
+
{ func: 'rgba($red, $green, $blue, $alpha)', desc: l10n.t('Creates a Color from red, green, blue, and alpha values.') },
|
|
10
|
+
{ func: 'hsl($hue, $saturation, $lightness)', desc: l10n.t('Creates a Color from hue, saturation, and lightness values.') },
|
|
11
|
+
{ func: 'hsla($hue, $saturation, $lightness, $alpha)', desc: l10n.t('Creates a Color from hue, saturation, lightness, and alpha values.') },
|
|
12
|
+
{ func: 'hwb($hue $white $black)', desc: l10n.t('Creates a Color from hue, white and black.') }
|
|
14
13
|
];
|
|
15
14
|
export const colors = {
|
|
16
15
|
aliceblue: '#f0f8ff',
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
'use strict';
|
|
6
|
-
import * as
|
|
7
|
-
const localize = nls.loadMessageBundle();
|
|
6
|
+
import * as l10n from '@vscode/l10n';
|
|
8
7
|
export class CSSIssueType {
|
|
9
8
|
constructor(id, message) {
|
|
10
9
|
this.id = id;
|
|
@@ -12,37 +11,37 @@ export class CSSIssueType {
|
|
|
12
11
|
}
|
|
13
12
|
}
|
|
14
13
|
export const ParseError = {
|
|
15
|
-
NumberExpected: new CSSIssueType('css-numberexpected',
|
|
16
|
-
ConditionExpected: new CSSIssueType('css-conditionexpected',
|
|
17
|
-
RuleOrSelectorExpected: new CSSIssueType('css-ruleorselectorexpected',
|
|
18
|
-
DotExpected: new CSSIssueType('css-dotexpected',
|
|
19
|
-
ColonExpected: new CSSIssueType('css-colonexpected',
|
|
20
|
-
SemiColonExpected: new CSSIssueType('css-semicolonexpected',
|
|
21
|
-
TermExpected: new CSSIssueType('css-termexpected',
|
|
22
|
-
ExpressionExpected: new CSSIssueType('css-expressionexpected',
|
|
23
|
-
OperatorExpected: new CSSIssueType('css-operatorexpected',
|
|
24
|
-
IdentifierExpected: new CSSIssueType('css-identifierexpected',
|
|
25
|
-
PercentageExpected: new CSSIssueType('css-percentageexpected',
|
|
26
|
-
URIOrStringExpected: new CSSIssueType('css-uriorstringexpected',
|
|
27
|
-
URIExpected: new CSSIssueType('css-uriexpected',
|
|
28
|
-
VariableNameExpected: new CSSIssueType('css-varnameexpected',
|
|
29
|
-
VariableValueExpected: new CSSIssueType('css-varvalueexpected',
|
|
30
|
-
PropertyValueExpected: new CSSIssueType('css-propertyvalueexpected',
|
|
31
|
-
LeftCurlyExpected: new CSSIssueType('css-lcurlyexpected',
|
|
32
|
-
RightCurlyExpected: new CSSIssueType('css-rcurlyexpected',
|
|
33
|
-
LeftSquareBracketExpected: new CSSIssueType('css-rbracketexpected',
|
|
34
|
-
RightSquareBracketExpected: new CSSIssueType('css-lbracketexpected',
|
|
35
|
-
LeftParenthesisExpected: new CSSIssueType('css-lparentexpected',
|
|
36
|
-
RightParenthesisExpected: new CSSIssueType('css-rparentexpected',
|
|
37
|
-
CommaExpected: new CSSIssueType('css-commaexpected',
|
|
38
|
-
PageDirectiveOrDeclarationExpected: new CSSIssueType('css-pagedirordeclexpected',
|
|
39
|
-
UnknownAtRule: new CSSIssueType('css-unknownatrule',
|
|
40
|
-
UnknownKeyword: new CSSIssueType('css-unknownkeyword',
|
|
41
|
-
SelectorExpected: new CSSIssueType('css-selectorexpected',
|
|
42
|
-
StringLiteralExpected: new CSSIssueType('css-stringliteralexpected',
|
|
43
|
-
WhitespaceExpected: new CSSIssueType('css-whitespaceexpected',
|
|
44
|
-
MediaQueryExpected: new CSSIssueType('css-mediaqueryexpected',
|
|
45
|
-
IdentifierOrWildcardExpected: new CSSIssueType('css-idorwildcardexpected',
|
|
46
|
-
WildcardExpected: new CSSIssueType('css-wildcardexpected',
|
|
47
|
-
IdentifierOrVariableExpected: new CSSIssueType('css-idorvarexpected',
|
|
14
|
+
NumberExpected: new CSSIssueType('css-numberexpected', l10n.t("number expected")),
|
|
15
|
+
ConditionExpected: new CSSIssueType('css-conditionexpected', l10n.t("condition expected")),
|
|
16
|
+
RuleOrSelectorExpected: new CSSIssueType('css-ruleorselectorexpected', l10n.t("at-rule or selector expected")),
|
|
17
|
+
DotExpected: new CSSIssueType('css-dotexpected', l10n.t("dot expected")),
|
|
18
|
+
ColonExpected: new CSSIssueType('css-colonexpected', l10n.t("colon expected")),
|
|
19
|
+
SemiColonExpected: new CSSIssueType('css-semicolonexpected', l10n.t("semi-colon expected")),
|
|
20
|
+
TermExpected: new CSSIssueType('css-termexpected', l10n.t("term expected")),
|
|
21
|
+
ExpressionExpected: new CSSIssueType('css-expressionexpected', l10n.t("expression expected")),
|
|
22
|
+
OperatorExpected: new CSSIssueType('css-operatorexpected', l10n.t("operator expected")),
|
|
23
|
+
IdentifierExpected: new CSSIssueType('css-identifierexpected', l10n.t("identifier expected")),
|
|
24
|
+
PercentageExpected: new CSSIssueType('css-percentageexpected', l10n.t("percentage expected")),
|
|
25
|
+
URIOrStringExpected: new CSSIssueType('css-uriorstringexpected', l10n.t("uri or string expected")),
|
|
26
|
+
URIExpected: new CSSIssueType('css-uriexpected', l10n.t("URI expected")),
|
|
27
|
+
VariableNameExpected: new CSSIssueType('css-varnameexpected', l10n.t("variable name expected")),
|
|
28
|
+
VariableValueExpected: new CSSIssueType('css-varvalueexpected', l10n.t("variable value expected")),
|
|
29
|
+
PropertyValueExpected: new CSSIssueType('css-propertyvalueexpected', l10n.t("property value expected")),
|
|
30
|
+
LeftCurlyExpected: new CSSIssueType('css-lcurlyexpected', l10n.t("{ expected")),
|
|
31
|
+
RightCurlyExpected: new CSSIssueType('css-rcurlyexpected', l10n.t("} expected")),
|
|
32
|
+
LeftSquareBracketExpected: new CSSIssueType('css-rbracketexpected', l10n.t("[ expected")),
|
|
33
|
+
RightSquareBracketExpected: new CSSIssueType('css-lbracketexpected', l10n.t("] expected")),
|
|
34
|
+
LeftParenthesisExpected: new CSSIssueType('css-lparentexpected', l10n.t("( expected")),
|
|
35
|
+
RightParenthesisExpected: new CSSIssueType('css-rparentexpected', l10n.t(") expected")),
|
|
36
|
+
CommaExpected: new CSSIssueType('css-commaexpected', l10n.t("comma expected")),
|
|
37
|
+
PageDirectiveOrDeclarationExpected: new CSSIssueType('css-pagedirordeclexpected', l10n.t("page directive or declaraton expected")),
|
|
38
|
+
UnknownAtRule: new CSSIssueType('css-unknownatrule', l10n.t("at-rule unknown")),
|
|
39
|
+
UnknownKeyword: new CSSIssueType('css-unknownkeyword', l10n.t("unknown keyword")),
|
|
40
|
+
SelectorExpected: new CSSIssueType('css-selectorexpected', l10n.t("selector expected")),
|
|
41
|
+
StringLiteralExpected: new CSSIssueType('css-stringliteralexpected', l10n.t("string literal expected")),
|
|
42
|
+
WhitespaceExpected: new CSSIssueType('css-whitespaceexpected', l10n.t("whitespace expected")),
|
|
43
|
+
MediaQueryExpected: new CSSIssueType('css-mediaqueryexpected', l10n.t("media query expected")),
|
|
44
|
+
IdentifierOrWildcardExpected: new CSSIssueType('css-idorwildcardexpected', l10n.t("identifier or wildcard expected")),
|
|
45
|
+
WildcardExpected: new CSSIssueType('css-wildcardexpected', l10n.t("wildcard expected")),
|
|
46
|
+
IdentifierOrVariableExpected: new CSSIssueType('css-idorvarexpected', l10n.t("identifier or variable expected")),
|
|
48
47
|
};
|
|
@@ -96,6 +96,7 @@ export var NodeType;
|
|
|
96
96
|
NodeType[NodeType["Layer"] = 83] = "Layer";
|
|
97
97
|
NodeType[NodeType["LayerNameList"] = 84] = "LayerNameList";
|
|
98
98
|
NodeType[NodeType["LayerName"] = 85] = "LayerName";
|
|
99
|
+
NodeType[NodeType["PropertyAtRule"] = 86] = "PropertyAtRule";
|
|
99
100
|
})(NodeType || (NodeType = {}));
|
|
100
101
|
export var ReferenceType;
|
|
101
102
|
(function (ReferenceType) {
|
|
@@ -108,6 +109,7 @@ export var ReferenceType;
|
|
|
108
109
|
ReferenceType[ReferenceType["Module"] = 6] = "Module";
|
|
109
110
|
ReferenceType[ReferenceType["Forward"] = 7] = "Forward";
|
|
110
111
|
ReferenceType[ReferenceType["ForwardVisibility"] = 8] = "ForwardVisibility";
|
|
112
|
+
ReferenceType[ReferenceType["Property"] = 9] = "Property";
|
|
111
113
|
})(ReferenceType || (ReferenceType = {}));
|
|
112
114
|
export function getNodeAtOffset(node, offset) {
|
|
113
115
|
let candidate = null;
|
|
@@ -150,6 +152,7 @@ export function getParentDeclaration(node) {
|
|
|
150
152
|
return null;
|
|
151
153
|
}
|
|
152
154
|
export class Node {
|
|
155
|
+
get end() { return this.offset + this.length; }
|
|
153
156
|
constructor(offset = -1, len = -1, nodeType) {
|
|
154
157
|
this.parent = null;
|
|
155
158
|
this.offset = offset;
|
|
@@ -158,7 +161,6 @@ export class Node {
|
|
|
158
161
|
this.nodeType = nodeType;
|
|
159
162
|
}
|
|
160
163
|
}
|
|
161
|
-
get end() { return this.offset + this.length; }
|
|
162
164
|
set type(type) {
|
|
163
165
|
this.nodeType = type;
|
|
164
166
|
}
|
|
@@ -893,6 +895,25 @@ export class Layer extends BodyDeclaration {
|
|
|
893
895
|
return this.names;
|
|
894
896
|
}
|
|
895
897
|
}
|
|
898
|
+
export class PropertyAtRule extends BodyDeclaration {
|
|
899
|
+
constructor(offset, length) {
|
|
900
|
+
super(offset, length);
|
|
901
|
+
}
|
|
902
|
+
get type() {
|
|
903
|
+
return NodeType.PropertyAtRule;
|
|
904
|
+
}
|
|
905
|
+
setName(node) {
|
|
906
|
+
if (node) {
|
|
907
|
+
node.attachTo(this);
|
|
908
|
+
this.name = node;
|
|
909
|
+
return true;
|
|
910
|
+
}
|
|
911
|
+
return false;
|
|
912
|
+
}
|
|
913
|
+
getName() {
|
|
914
|
+
return this.name;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
896
917
|
export class Document extends BodyDeclaration {
|
|
897
918
|
constructor(offset, length) {
|
|
898
919
|
super(offset, length);
|
|
@@ -1494,14 +1515,14 @@ export class DefaultVisitor implements IVisitor {
|
|
|
1494
1515
|
}
|
|
1495
1516
|
*/
|
|
1496
1517
|
export class ParseErrorCollector {
|
|
1497
|
-
constructor() {
|
|
1498
|
-
this.entries = [];
|
|
1499
|
-
}
|
|
1500
1518
|
static entries(node) {
|
|
1501
1519
|
const visitor = new ParseErrorCollector();
|
|
1502
1520
|
node.acceptVisitor(visitor);
|
|
1503
1521
|
return visitor.entries;
|
|
1504
1522
|
}
|
|
1523
|
+
constructor() {
|
|
1524
|
+
this.entries = [];
|
|
1525
|
+
}
|
|
1505
1526
|
visitNode(node) {
|
|
1506
1527
|
if (node.isErroneous()) {
|
|
1507
1528
|
node.collectIssues(this.entries);
|
|
@@ -272,6 +272,7 @@ export class Parser {
|
|
|
272
272
|
|| this._parseKeyframe()
|
|
273
273
|
|| this._parseSupports(isNested)
|
|
274
274
|
|| this._parseLayer()
|
|
275
|
+
|| this._parsePropertyAtRule()
|
|
275
276
|
|| this._parseViewPort()
|
|
276
277
|
|| this._parseNamespace()
|
|
277
278
|
|| this._parseDocument()
|
|
@@ -717,6 +718,20 @@ export class Parser {
|
|
|
717
718
|
}
|
|
718
719
|
return this._parseBody(node, this._parseRuleSetDeclaration.bind(this));
|
|
719
720
|
}
|
|
721
|
+
_parsePropertyAtRule() {
|
|
722
|
+
// @property <custom-property-name> {
|
|
723
|
+
// <declaration-list>
|
|
724
|
+
// }
|
|
725
|
+
if (!this.peekKeyword('@property')) {
|
|
726
|
+
return null;
|
|
727
|
+
}
|
|
728
|
+
const node = this.create(nodes.PropertyAtRule);
|
|
729
|
+
this.consumeToken(); // @layer
|
|
730
|
+
if (!this.peekRegExp(TokenType.Ident, /^--/) || !node.setName(this._parseIdent([nodes.ReferenceType.Property]))) {
|
|
731
|
+
return this.finish(node, ParseError.IdentifierExpected);
|
|
732
|
+
}
|
|
733
|
+
return this._parseBody(node, this._parseDeclaration.bind(this));
|
|
734
|
+
}
|
|
720
735
|
_parseLayer() {
|
|
721
736
|
// @layer layer-name {rules}
|
|
722
737
|
// @layer layer-name;
|
|
@@ -954,29 +969,17 @@ export class Parser {
|
|
|
954
969
|
// <mf-plain> = <mf-name> : <mf-value>
|
|
955
970
|
// <mf-boolean> = <mf-name>
|
|
956
971
|
// <mf-range> = <mf-name> [ '<' | '>' ]? '='? <mf-value> | <mf-value> [ '<' | '>' ]? '='? <mf-name> | <mf-value> '<' '='? <mf-name> '<' '='? <mf-value> | <mf-value> '>' '='? <mf-name> '>' '='? <mf-value>
|
|
957
|
-
const parseRangeOperator = () => {
|
|
958
|
-
if (this.acceptDelim('<') || this.acceptDelim('>')) {
|
|
959
|
-
if (!this.hasWhitespace()) {
|
|
960
|
-
this.acceptDelim('=');
|
|
961
|
-
}
|
|
962
|
-
return true;
|
|
963
|
-
}
|
|
964
|
-
else if (this.acceptDelim('=')) {
|
|
965
|
-
return true;
|
|
966
|
-
}
|
|
967
|
-
return false;
|
|
968
|
-
};
|
|
969
972
|
if (node.addChild(this._parseMediaFeatureName())) {
|
|
970
973
|
if (this.accept(TokenType.Colon)) {
|
|
971
974
|
if (!node.addChild(this._parseMediaFeatureValue())) {
|
|
972
975
|
return this.finish(node, ParseError.TermExpected, [], resyncStopToken);
|
|
973
976
|
}
|
|
974
977
|
}
|
|
975
|
-
else if (
|
|
978
|
+
else if (this._parseMediaFeatureRangeOperator()) {
|
|
976
979
|
if (!node.addChild(this._parseMediaFeatureValue())) {
|
|
977
980
|
return this.finish(node, ParseError.TermExpected, [], resyncStopToken);
|
|
978
981
|
}
|
|
979
|
-
if (
|
|
982
|
+
if (this._parseMediaFeatureRangeOperator()) {
|
|
980
983
|
if (!node.addChild(this._parseMediaFeatureValue())) {
|
|
981
984
|
return this.finish(node, ParseError.TermExpected, [], resyncStopToken);
|
|
982
985
|
}
|
|
@@ -987,13 +990,13 @@ export class Parser {
|
|
|
987
990
|
}
|
|
988
991
|
}
|
|
989
992
|
else if (node.addChild(this._parseMediaFeatureValue())) {
|
|
990
|
-
if (!
|
|
993
|
+
if (!this._parseMediaFeatureRangeOperator()) {
|
|
991
994
|
return this.finish(node, ParseError.OperatorExpected, [], resyncStopToken);
|
|
992
995
|
}
|
|
993
996
|
if (!node.addChild(this._parseMediaFeatureName())) {
|
|
994
997
|
return this.finish(node, ParseError.IdentifierExpected, [], resyncStopToken);
|
|
995
998
|
}
|
|
996
|
-
if (
|
|
999
|
+
if (this._parseMediaFeatureRangeOperator()) {
|
|
997
1000
|
if (!node.addChild(this._parseMediaFeatureValue())) {
|
|
998
1001
|
return this.finish(node, ParseError.TermExpected, [], resyncStopToken);
|
|
999
1002
|
}
|
|
@@ -1004,6 +1007,18 @@ export class Parser {
|
|
|
1004
1007
|
}
|
|
1005
1008
|
return this.finish(node);
|
|
1006
1009
|
}
|
|
1010
|
+
_parseMediaFeatureRangeOperator() {
|
|
1011
|
+
if (this.acceptDelim('<') || this.acceptDelim('>')) {
|
|
1012
|
+
if (!this.hasWhitespace()) {
|
|
1013
|
+
this.acceptDelim('=');
|
|
1014
|
+
}
|
|
1015
|
+
return true;
|
|
1016
|
+
}
|
|
1017
|
+
else if (this.acceptDelim('=')) {
|
|
1018
|
+
return true;
|
|
1019
|
+
}
|
|
1020
|
+
return false;
|
|
1021
|
+
}
|
|
1007
1022
|
_parseMediaFeatureName() {
|
|
1008
1023
|
return this._parseIdent();
|
|
1009
1024
|
}
|
|
@@ -273,6 +273,7 @@ export class LESSParser extends cssParser.Parser {
|
|
|
273
273
|
|| this._parseImport()
|
|
274
274
|
|| this._parseSupports(true) // @supports
|
|
275
275
|
|| this._parseLayer() // @layer
|
|
276
|
+
|| this._parsePropertyAtRule() // @property
|
|
276
277
|
|| this._parseDetachedRuleSetMixin() // less detached ruleset mixin
|
|
277
278
|
|| this._parseVariableDeclaration() // Variable declarations
|
|
278
279
|
|| super._parseRuleSetDeclarationAtStatement();
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
'use strict';
|
|
6
|
-
import * as
|
|
7
|
-
const localize = nls.loadMessageBundle();
|
|
6
|
+
import * as l10n from '@vscode/l10n';
|
|
8
7
|
export class SCSSIssueType {
|
|
9
8
|
constructor(id, message) {
|
|
10
9
|
this.id = id;
|
|
@@ -12,7 +11,7 @@ export class SCSSIssueType {
|
|
|
12
11
|
}
|
|
13
12
|
}
|
|
14
13
|
export const SCSSParseError = {
|
|
15
|
-
FromExpected: new SCSSIssueType('scss-fromexpected',
|
|
16
|
-
ThroughOrToExpected: new SCSSIssueType('scss-throughexpected',
|
|
17
|
-
InExpected: new SCSSIssueType('scss-fromexpected',
|
|
14
|
+
FromExpected: new SCSSIssueType('scss-fromexpected', l10n.t("'from' expected")),
|
|
15
|
+
ThroughOrToExpected: new SCSSIssueType('scss-throughexpected', l10n.t("'through' or 'to' expected")),
|
|
16
|
+
InExpected: new SCSSIssueType('scss-fromexpected', l10n.t("'in' expected")),
|
|
18
17
|
};
|
|
@@ -89,6 +89,9 @@ export class SCSSParser extends cssParser.Parser {
|
|
|
89
89
|
_parseMediaCondition() {
|
|
90
90
|
return this._parseInterpolation() || super._parseMediaCondition();
|
|
91
91
|
}
|
|
92
|
+
_parseMediaFeatureRangeOperator() {
|
|
93
|
+
return this.accept(scssScanner.SmallerEqualsOperator) || this.accept(scssScanner.GreaterEqualsOperator) || super._parseMediaFeatureRangeOperator();
|
|
94
|
+
}
|
|
92
95
|
_parseMediaFeatureName() {
|
|
93
96
|
return this._parseModuleMember()
|
|
94
97
|
|| this._parseFunction() // function before ident
|
|
@@ -215,6 +218,7 @@ export class SCSSParser extends cssParser.Parser {
|
|
|
215
218
|
|| this._parseRuleset(true) // @at-rule
|
|
216
219
|
|| this._parseSupports(true) // @supports
|
|
217
220
|
|| this._parseLayer() // @layer
|
|
221
|
+
|| this._parsePropertyAtRule() // @property
|
|
218
222
|
|| super._parseRuleSetDeclarationAtStatement();
|
|
219
223
|
}
|
|
220
224
|
return this._parseVariableDeclaration() // variable declaration
|
|
@@ -7,8 +7,7 @@ import * as nodes from '../parser/cssNodes';
|
|
|
7
7
|
import { difference } from '../utils/strings';
|
|
8
8
|
import { Rules } from '../services/lintRules';
|
|
9
9
|
import { Command, TextEdit, CodeAction, CodeActionKind, TextDocumentEdit, VersionedTextDocumentIdentifier } from '../cssLanguageTypes';
|
|
10
|
-
import * as
|
|
11
|
-
const localize = nls.loadMessageBundle();
|
|
10
|
+
import * as l10n from '@vscode/l10n';
|
|
12
11
|
export class CSSCodeActions {
|
|
13
12
|
constructor(cssDataManager) {
|
|
14
13
|
this.cssDataManager = cssDataManager;
|
|
@@ -44,7 +43,7 @@ export class CSSCodeActions {
|
|
|
44
43
|
let maxActions = 3;
|
|
45
44
|
for (const candidate of candidates) {
|
|
46
45
|
const propertyName = candidate.property;
|
|
47
|
-
const title =
|
|
46
|
+
const title = l10n.t("Rename to '{0}'", propertyName);
|
|
48
47
|
const edit = TextEdit.replace(marker.range, propertyName);
|
|
49
48
|
const documentIdentifier = VersionedTextDocumentIdentifier.create(document.uri, document.version);
|
|
50
49
|
const workspaceEdit = { documentChanges: [TextDocumentEdit.create(documentIdentifier, [edit])] };
|
|
@@ -8,10 +8,9 @@ import { Symbols } from '../parser/cssSymbolScope';
|
|
|
8
8
|
import * as languageFacts from '../languageFacts/facts';
|
|
9
9
|
import * as strings from '../utils/strings';
|
|
10
10
|
import { Position, CompletionItemKind, Range, TextEdit, InsertTextFormat, MarkupKind, CompletionItemTag } from '../cssLanguageTypes';
|
|
11
|
-
import * as
|
|
11
|
+
import * as l10n from '@vscode/l10n';
|
|
12
12
|
import { isDefined } from '../utils/objects';
|
|
13
13
|
import { PathCompletionParticipant } from './pathCompletion';
|
|
14
|
-
const localize = nls.loadMessageBundle();
|
|
15
14
|
const SnippetFormat = InsertTextFormat.Snippet;
|
|
16
15
|
const retriggerCommand = {
|
|
17
16
|
title: 'Suggest',
|
|
@@ -57,6 +56,7 @@ export class CSSCompletion {
|
|
|
57
56
|
const pathCompletionResult = await participant.computeCompletions(document, documentContext);
|
|
58
57
|
return {
|
|
59
58
|
isIncomplete: result.isIncomplete || pathCompletionResult.isIncomplete,
|
|
59
|
+
itemDefaults: result.itemDefaults,
|
|
60
60
|
items: pathCompletionResult.items.concat(result.items)
|
|
61
61
|
};
|
|
62
62
|
}
|
|
@@ -73,7 +73,16 @@ export class CSSCompletion {
|
|
|
73
73
|
this.styleSheet = styleSheet;
|
|
74
74
|
this.documentSettings = documentSettings;
|
|
75
75
|
try {
|
|
76
|
-
const result = {
|
|
76
|
+
const result = {
|
|
77
|
+
isIncomplete: false,
|
|
78
|
+
itemDefaults: {
|
|
79
|
+
editRange: {
|
|
80
|
+
start: { line: position.line, character: position.character - this.currentWord.length },
|
|
81
|
+
end: position
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
items: []
|
|
85
|
+
};
|
|
77
86
|
this.nodePath = nodes.getNodePath(this.styleSheet, this.offset);
|
|
78
87
|
for (let i = this.nodePath.length - 1; i >= 0; i--) {
|
|
79
88
|
const node = this.nodePath[i];
|
|
@@ -401,7 +410,7 @@ export class CSSCompletion {
|
|
|
401
410
|
if (symbol.node.type === nodes.NodeType.FunctionParameter) {
|
|
402
411
|
const mixinNode = (symbol.node.getParent());
|
|
403
412
|
if (mixinNode.type === nodes.NodeType.MixinDeclaration) {
|
|
404
|
-
completionItem.detail =
|
|
413
|
+
completionItem.detail = l10n.t('argument from \'{0}\'', mixinNode.getName());
|
|
405
414
|
}
|
|
406
415
|
}
|
|
407
416
|
result.items.push(completionItem);
|
|
@@ -4,13 +4,12 @@
|
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
'use strict';
|
|
6
6
|
import { DocumentHighlightKind, Location, Range, SymbolKind, TextEdit, FileType } from '../cssLanguageTypes';
|
|
7
|
-
import * as
|
|
7
|
+
import * as l10n from '@vscode/l10n';
|
|
8
8
|
import * as nodes from '../parser/cssNodes';
|
|
9
9
|
import { Symbols } from '../parser/cssSymbolScope';
|
|
10
10
|
import { getColorValue, hslFromColor, hwbFromColor } from '../languageFacts/facts';
|
|
11
11
|
import { startsWith } from '../utils/strings';
|
|
12
12
|
import { dirname, joinPath } from '../utils/resources';
|
|
13
|
-
const localize = nls.loadMessageBundle();
|
|
14
13
|
const startsWithSchemeRegex = /^\w+:\/\//;
|
|
15
14
|
const startsWithData = /^data:/;
|
|
16
15
|
export class CSSNavigation {
|
|
@@ -43,16 +42,23 @@ export class CSSNavigation {
|
|
|
43
42
|
};
|
|
44
43
|
});
|
|
45
44
|
}
|
|
46
|
-
|
|
47
|
-
const result = [];
|
|
45
|
+
getHighlightNode(document, position, stylesheet) {
|
|
48
46
|
const offset = document.offsetAt(position);
|
|
49
47
|
let node = nodes.getNodeAtOffset(stylesheet, offset);
|
|
50
48
|
if (!node || node.type === nodes.NodeType.Stylesheet || node.type === nodes.NodeType.Declarations) {
|
|
51
|
-
return
|
|
49
|
+
return;
|
|
52
50
|
}
|
|
53
51
|
if (node.type === nodes.NodeType.Identifier && node.parent && node.parent.type === nodes.NodeType.ClassSelector) {
|
|
54
52
|
node = node.parent;
|
|
55
53
|
}
|
|
54
|
+
return node;
|
|
55
|
+
}
|
|
56
|
+
findDocumentHighlights(document, position, stylesheet) {
|
|
57
|
+
const result = [];
|
|
58
|
+
const node = this.getHighlightNode(document, position, stylesheet);
|
|
59
|
+
if (!node) {
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
56
62
|
const symbols = new Symbols(stylesheet);
|
|
57
63
|
const symbol = symbols.findSymbolFromNode(node);
|
|
58
64
|
const name = node.getText();
|
|
@@ -115,7 +121,7 @@ export class CSSNavigation {
|
|
|
115
121
|
resolvedLinks.push(link);
|
|
116
122
|
}
|
|
117
123
|
else {
|
|
118
|
-
const resolvedTarget = await this.
|
|
124
|
+
const resolvedTarget = await this.resolveReference(target, document.uri, documentContext, data.isRawLink);
|
|
119
125
|
if (resolvedTarget !== undefined) {
|
|
120
126
|
link.target = resolvedTarget;
|
|
121
127
|
resolvedLinks.push(link);
|
|
@@ -230,11 +236,11 @@ export class CSSNavigation {
|
|
|
230
236
|
collect(node.getName(), SymbolKind.Function, node, node.getIdentifier(), node.getDeclarations());
|
|
231
237
|
}
|
|
232
238
|
else if (node instanceof nodes.Keyframe) {
|
|
233
|
-
const name =
|
|
239
|
+
const name = l10n.t("@keyframes {0}", node.getName());
|
|
234
240
|
collect(name, SymbolKind.Class, node, node.getIdentifier(), node.getDeclarations());
|
|
235
241
|
}
|
|
236
242
|
else if (node instanceof nodes.FontFace) {
|
|
237
|
-
const name =
|
|
243
|
+
const name = l10n.t("@font-face");
|
|
238
244
|
collect(name, SymbolKind.Class, node, undefined, node.getDeclarations());
|
|
239
245
|
}
|
|
240
246
|
else if (node instanceof nodes.Media) {
|
|
@@ -294,6 +300,12 @@ export class CSSNavigation {
|
|
|
294
300
|
result.push({ label: label, textEdit: TextEdit.replace(range, label) });
|
|
295
301
|
return result;
|
|
296
302
|
}
|
|
303
|
+
prepareRename(document, position, stylesheet) {
|
|
304
|
+
const node = this.getHighlightNode(document, position, stylesheet);
|
|
305
|
+
if (node) {
|
|
306
|
+
return Range.create(document.positionAt(node.offset), document.positionAt(node.end));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
297
309
|
doRename(document, position, newName, stylesheet) {
|
|
298
310
|
const highlights = this.findDocumentHighlights(document, position, stylesheet);
|
|
299
311
|
const edits = highlights.map(h => TextEdit.replace(h.range, newName));
|
|
@@ -304,39 +316,46 @@ export class CSSNavigation {
|
|
|
304
316
|
async resolveModuleReference(ref, documentUri, documentContext) {
|
|
305
317
|
if (startsWith(documentUri, 'file://')) {
|
|
306
318
|
const moduleName = getModuleNameFromPath(ref);
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
319
|
+
if (moduleName && moduleName !== '.' && moduleName !== '..') {
|
|
320
|
+
const rootFolderUri = documentContext.resolveReference('/', documentUri);
|
|
321
|
+
const documentFolderUri = dirname(documentUri);
|
|
322
|
+
const modulePath = await this.resolvePathToModule(moduleName, documentFolderUri, rootFolderUri);
|
|
323
|
+
if (modulePath) {
|
|
324
|
+
const pathWithinModule = ref.substring(moduleName.length + 1);
|
|
325
|
+
return joinPath(modulePath, pathWithinModule);
|
|
326
|
+
}
|
|
313
327
|
}
|
|
314
328
|
}
|
|
315
329
|
return undefined;
|
|
316
330
|
}
|
|
317
|
-
async
|
|
318
|
-
|
|
331
|
+
async mapReference(target, isRawLink) {
|
|
332
|
+
return target;
|
|
333
|
+
}
|
|
334
|
+
async resolveReference(target, documentUri, documentContext, isRawLink = false) {
|
|
319
335
|
// Following [css-loader](https://github.com/webpack-contrib/css-loader#url)
|
|
320
336
|
// and [sass-loader's](https://github.com/webpack-contrib/sass-loader#imports)
|
|
321
337
|
// convention, if an import path starts with ~ then use node module resolution
|
|
322
338
|
// *unless* it starts with "~/" as this refers to the user's home directory.
|
|
323
|
-
if (
|
|
324
|
-
|
|
325
|
-
return await this.resolveModuleReference(
|
|
339
|
+
if (target[0] === '~' && target[1] !== '/' && this.fileSystemProvider) {
|
|
340
|
+
target = target.substring(1);
|
|
341
|
+
return this.mapReference(await this.resolveModuleReference(target, documentUri, documentContext), isRawLink);
|
|
326
342
|
}
|
|
343
|
+
const ref = await this.mapReference(documentContext.resolveReference(target, documentUri), isRawLink);
|
|
327
344
|
// Following [less-loader](https://github.com/webpack-contrib/less-loader#imports)
|
|
328
345
|
// and [sass-loader's](https://github.com/webpack-contrib/sass-loader#resolving-import-at-rules)
|
|
329
|
-
// new resolving import at-rules (~ is deprecated). The loader will first try to resolve @import as a relative path. If it cannot be resolved,
|
|
346
|
+
// new resolving import at-rules (~ is deprecated). The loader will first try to resolve @import as a relative path. If it cannot be resolved,
|
|
330
347
|
// then the loader will try to resolve @import inside node_modules.
|
|
331
348
|
if (this.resolveModuleReferences) {
|
|
332
|
-
if (
|
|
333
|
-
return
|
|
349
|
+
if (ref && await this.fileExists(ref)) {
|
|
350
|
+
return ref;
|
|
334
351
|
}
|
|
335
|
-
|
|
336
|
-
|
|
352
|
+
const moduleReference = await this.mapReference(await this.resolveModuleReference(target, documentUri, documentContext), isRawLink);
|
|
353
|
+
if (moduleReference) {
|
|
354
|
+
return moduleReference;
|
|
337
355
|
}
|
|
338
356
|
}
|
|
339
|
-
|
|
357
|
+
// fall back. it might not exists
|
|
358
|
+
return ref;
|
|
340
359
|
}
|
|
341
360
|
async resolvePathToModule(_moduleName, documentFolderUri, rootFolderUri) {
|
|
342
361
|
// resolve the module relative to the document. We can't use `require` here as the code is webpacked.
|