vscode-css-languageservice 6.2.9 → 6.2.11
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 +4 -4
- package/lib/esm/beautify/beautify-css.js +3 -7
- package/lib/esm/cssLanguageService.js +1 -0
- package/lib/esm/cssLanguageTypes.d.ts +4 -0
- package/lib/esm/parser/cssNodes.js +9 -0
- package/lib/esm/parser/cssParser.js +112 -3
- package/lib/esm/parser/cssScanner.js +8 -1
- package/lib/esm/parser/lessParser.js +1 -1
- package/lib/esm/parser/scssParser.js +4 -4
- package/lib/esm/services/cssNavigation.js +22 -1
- package/lib/esm/services/scssNavigation.js +3 -3
- package/lib/esm/services/selectorPrinting.js +38 -2
- package/lib/umd/beautify/beautify-css.js +3 -7
- package/lib/umd/cssLanguageService.js +1 -0
- package/lib/umd/cssLanguageTypes.d.ts +4 -0
- package/lib/umd/parser/cssNodes.js +11 -1
- package/lib/umd/parser/cssParser.js +112 -3
- package/lib/umd/parser/cssScanner.js +8 -1
- package/lib/umd/parser/lessParser.js +1 -1
- package/lib/umd/parser/scssParser.js +4 -4
- package/lib/umd/services/cssNavigation.js +22 -1
- package/lib/umd/services/scssNavigation.js +3 -3
- package/lib/umd/services/selectorPrinting.js +39 -3
- package/package.json +14 -14
- package/thirdpartynotices.txt +0 -29
package/README.md
CHANGED
|
@@ -39,8 +39,8 @@ Development
|
|
|
39
39
|
-----------
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
- clone this repo, run
|
|
43
|
-
- `
|
|
42
|
+
- clone this repo, run `npm install``
|
|
43
|
+
- `npm test` to compile and run tests
|
|
44
44
|
|
|
45
45
|
How can I run and debug the service?
|
|
46
46
|
|
|
@@ -53,8 +53,8 @@ How can I run and debug the service?
|
|
|
53
53
|
How can I run and debug the service inside an instance of VSCode?
|
|
54
54
|
|
|
55
55
|
- run VSCode out of sources setup as described here: https://github.com/Microsoft/vscode/wiki/How-to-Contribute
|
|
56
|
-
- run `
|
|
57
|
-
- use `
|
|
56
|
+
- run `npm link` in the folder of `vscode-css-languageservice`
|
|
57
|
+
- use `npm link vscode-css-languageservice` in `vscode/extensions/css-language-features/server` to run VSCode with the latest changes from `vscode-css-languageservice`
|
|
58
58
|
- run VSCode out of source (`vscode/scripts/code.sh|bat`) and open a `.css` file
|
|
59
59
|
- in VSCode window that is open on the `vscode-css-languageservice` sources, run command `Debug: Attach to Node process` and pick the `code-oss` process with the `css-language-features` path
|
|
60
60
|

|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// copied from js-beautify/js/lib/beautify-css.js
|
|
2
|
-
// version: 1.14.
|
|
2
|
+
// version: 1.14.11
|
|
3
3
|
/* AUTO-GENERATED. DO NOT MODIFY. */
|
|
4
4
|
/*
|
|
5
5
|
|
|
@@ -1280,13 +1280,11 @@ Beautifier.prototype.beautify = function() {
|
|
|
1280
1280
|
|
|
1281
1281
|
if (variable.match(/[ :]$/)) {
|
|
1282
1282
|
// we have a variable or pseudo-class, add it and insert one space before continuing
|
|
1283
|
-
variable = this.eatString(": ").replace(/\s
|
|
1283
|
+
variable = this.eatString(": ").replace(/\s+$/, '');
|
|
1284
1284
|
this.print_string(variable);
|
|
1285
1285
|
this._output.space_before_token = true;
|
|
1286
1286
|
}
|
|
1287
1287
|
|
|
1288
|
-
variable = variable.replace(/\s$/, '');
|
|
1289
|
-
|
|
1290
1288
|
// might be sass variable
|
|
1291
1289
|
if (parenLevel === 0 && variable.indexOf(':') !== -1) {
|
|
1292
1290
|
insidePropertyValue = true;
|
|
@@ -1306,13 +1304,11 @@ Beautifier.prototype.beautify = function() {
|
|
|
1306
1304
|
|
|
1307
1305
|
if (variableOrRule.match(/[ :]$/)) {
|
|
1308
1306
|
// we have a variable or pseudo-class, add it and insert one space before continuing
|
|
1309
|
-
variableOrRule = this.eatString(": ").replace(/\s
|
|
1307
|
+
variableOrRule = this.eatString(": ").replace(/\s+$/, '');
|
|
1310
1308
|
this.print_string(variableOrRule);
|
|
1311
1309
|
this._output.space_before_token = true;
|
|
1312
1310
|
}
|
|
1313
1311
|
|
|
1314
|
-
variableOrRule = variableOrRule.replace(/\s$/, '');
|
|
1315
|
-
|
|
1316
1312
|
// might be less variable
|
|
1317
1313
|
if (parenLevel === 0 && variableOrRule.indexOf(':') !== -1) {
|
|
1318
1314
|
insidePropertyValue = true;
|
|
@@ -33,6 +33,7 @@ function createFacade(parser, completion, hover, navigation, codeActions, valida
|
|
|
33
33
|
validation.configure(settings);
|
|
34
34
|
completion.configure(settings?.completion);
|
|
35
35
|
hover.configure(settings?.hover);
|
|
36
|
+
navigation.configure(settings?.importAliases);
|
|
36
37
|
},
|
|
37
38
|
setDataProviders: cssDataManager.setDataProviders.bind(cssDataManager),
|
|
38
39
|
doValidation: validation.doValidation.bind(validation),
|
|
@@ -13,6 +13,10 @@ export interface LanguageSettings {
|
|
|
13
13
|
lint?: LintSettings;
|
|
14
14
|
completion?: CompletionSettings;
|
|
15
15
|
hover?: HoverSettings;
|
|
16
|
+
importAliases?: AliasSettings;
|
|
17
|
+
}
|
|
18
|
+
export interface AliasSettings {
|
|
19
|
+
[key: string]: string;
|
|
16
20
|
}
|
|
17
21
|
export interface HoverSettings {
|
|
18
22
|
documentation?: boolean;
|
|
@@ -97,6 +97,7 @@ export var NodeType;
|
|
|
97
97
|
NodeType[NodeType["LayerNameList"] = 84] = "LayerNameList";
|
|
98
98
|
NodeType[NodeType["LayerName"] = 85] = "LayerName";
|
|
99
99
|
NodeType[NodeType["PropertyAtRule"] = 86] = "PropertyAtRule";
|
|
100
|
+
NodeType[NodeType["Container"] = 87] = "Container";
|
|
100
101
|
})(NodeType || (NodeType = {}));
|
|
101
102
|
export var ReferenceType;
|
|
102
103
|
(function (ReferenceType) {
|
|
@@ -922,6 +923,14 @@ export class Document extends BodyDeclaration {
|
|
|
922
923
|
return NodeType.Document;
|
|
923
924
|
}
|
|
924
925
|
}
|
|
926
|
+
export class Container extends BodyDeclaration {
|
|
927
|
+
constructor(offset, length) {
|
|
928
|
+
super(offset, length);
|
|
929
|
+
}
|
|
930
|
+
get type() {
|
|
931
|
+
return NodeType.Container;
|
|
932
|
+
}
|
|
933
|
+
}
|
|
925
934
|
export class Medialist extends Node {
|
|
926
935
|
constructor(offset, length) {
|
|
927
936
|
super(offset, length);
|
|
@@ -276,6 +276,7 @@ export class Parser {
|
|
|
276
276
|
|| this._parseViewPort()
|
|
277
277
|
|| this._parseNamespace()
|
|
278
278
|
|| this._parseDocument()
|
|
279
|
+
|| this._parseContainer()
|
|
279
280
|
|| this._parseUnknownAtRule();
|
|
280
281
|
}
|
|
281
282
|
_tryParseRuleset(isNested) {
|
|
@@ -615,6 +616,9 @@ export class Parser {
|
|
|
615
616
|
if (!node.addChild(this._parseURILiteral()) && !node.addChild(this._parseStringLiteral())) {
|
|
616
617
|
return this.finish(node, ParseError.URIOrStringExpected);
|
|
617
618
|
}
|
|
619
|
+
return this._completeParseImport(node);
|
|
620
|
+
}
|
|
621
|
+
_completeParseImport(node) {
|
|
618
622
|
if (this.acceptIdent('layer')) {
|
|
619
623
|
if (this.accept(TokenType.ParenthesisL)) {
|
|
620
624
|
if (!node.addChild(this._parseLayerName())) {
|
|
@@ -811,11 +815,10 @@ export class Parser {
|
|
|
811
815
|
}
|
|
812
816
|
_parseLayerName() {
|
|
813
817
|
// <layer-name> = <ident> [ '.' <ident> ]*
|
|
814
|
-
|
|
818
|
+
const node = this.createNode(nodes.NodeType.LayerName);
|
|
819
|
+
if (!node.addChild(this._parseIdent())) {
|
|
815
820
|
return null;
|
|
816
821
|
}
|
|
817
|
-
const node = this.createNode(nodes.NodeType.LayerName);
|
|
818
|
-
node.addChild(this._parseIdent());
|
|
819
822
|
while (!this.hasWhitespace() && this.acceptDelim('.')) {
|
|
820
823
|
if (this.hasWhitespace() || !node.addChild(this._parseIdent())) {
|
|
821
824
|
return this.finish(node, ParseError.IdentifierExpected);
|
|
@@ -1134,6 +1137,111 @@ export class Parser {
|
|
|
1134
1137
|
this.resync([], [TokenType.CurlyL]); // ignore all the rules
|
|
1135
1138
|
return this._parseBody(node, this._parseStylesheetStatement.bind(this));
|
|
1136
1139
|
}
|
|
1140
|
+
_parseContainer() {
|
|
1141
|
+
if (!this.peekKeyword('@container')) {
|
|
1142
|
+
return null;
|
|
1143
|
+
}
|
|
1144
|
+
const node = this.create(nodes.Container);
|
|
1145
|
+
this.consumeToken(); // @container
|
|
1146
|
+
node.addChild(this._parseIdent()); // optional container name
|
|
1147
|
+
node.addChild(this._parseContainerQuery());
|
|
1148
|
+
return this._parseBody(node, this._parseStylesheetStatement.bind(this));
|
|
1149
|
+
}
|
|
1150
|
+
_parseContainerQuery() {
|
|
1151
|
+
// <container-query> = not <query-in-parens>
|
|
1152
|
+
// | <query-in-parens> [ [ and <query-in-parens> ]* | [ or <query-in-parens> ]* ]
|
|
1153
|
+
const node = this.create(nodes.Node);
|
|
1154
|
+
if (this.acceptIdent('not')) {
|
|
1155
|
+
node.addChild(this._parseContainerQueryInParens());
|
|
1156
|
+
}
|
|
1157
|
+
else {
|
|
1158
|
+
node.addChild(this._parseContainerQueryInParens());
|
|
1159
|
+
if (this.peekIdent('and')) {
|
|
1160
|
+
while (this.acceptIdent('and')) {
|
|
1161
|
+
node.addChild(this._parseContainerQueryInParens());
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
else if (this.peekIdent('or')) {
|
|
1165
|
+
while (this.acceptIdent('or')) {
|
|
1166
|
+
node.addChild(this._parseContainerQueryInParens());
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
return this.finish(node);
|
|
1171
|
+
}
|
|
1172
|
+
_parseContainerQueryInParens() {
|
|
1173
|
+
// <query-in-parens> = ( <container-query> )
|
|
1174
|
+
// | ( <size-feature> )
|
|
1175
|
+
// | style( <style-query> )
|
|
1176
|
+
// | <general-enclosed>
|
|
1177
|
+
const node = this.create(nodes.Node);
|
|
1178
|
+
if (this.accept(TokenType.ParenthesisL)) {
|
|
1179
|
+
if (this.peekIdent('not') || this.peek(TokenType.ParenthesisL)) {
|
|
1180
|
+
node.addChild(this._parseContainerQuery());
|
|
1181
|
+
}
|
|
1182
|
+
else {
|
|
1183
|
+
node.addChild(this._parseMediaFeature());
|
|
1184
|
+
}
|
|
1185
|
+
if (!this.accept(TokenType.ParenthesisR)) {
|
|
1186
|
+
return this.finish(node, ParseError.RightParenthesisExpected, [], [TokenType.CurlyL]);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
else if (this.acceptIdent('style')) {
|
|
1190
|
+
if (this.hasWhitespace() || !this.accept(TokenType.ParenthesisL)) {
|
|
1191
|
+
return this.finish(node, ParseError.LeftParenthesisExpected, [], [TokenType.CurlyL]);
|
|
1192
|
+
}
|
|
1193
|
+
node.addChild(this._parseStyleQuery());
|
|
1194
|
+
if (!this.accept(TokenType.ParenthesisR)) {
|
|
1195
|
+
return this.finish(node, ParseError.RightParenthesisExpected, [], [TokenType.CurlyL]);
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
else {
|
|
1199
|
+
return this.finish(node, ParseError.LeftParenthesisExpected, [], [TokenType.CurlyL]);
|
|
1200
|
+
}
|
|
1201
|
+
return this.finish(node);
|
|
1202
|
+
}
|
|
1203
|
+
_parseStyleQuery() {
|
|
1204
|
+
// <style-query> = not <style-in-parens>
|
|
1205
|
+
// | <style-in-parens> [ [ and <style-in-parens> ]* | [ or <style-in-parens> ]* ]
|
|
1206
|
+
// | <style-feature>
|
|
1207
|
+
// <style-in-parens> = ( <style-query> )
|
|
1208
|
+
// | ( <style-feature> )
|
|
1209
|
+
// | <general-enclosed>
|
|
1210
|
+
const node = this.create(nodes.Node);
|
|
1211
|
+
if (this.acceptIdent('not')) {
|
|
1212
|
+
node.addChild(this._parseStyleInParens());
|
|
1213
|
+
}
|
|
1214
|
+
else if (this.peek(TokenType.ParenthesisL)) {
|
|
1215
|
+
node.addChild(this._parseStyleInParens());
|
|
1216
|
+
if (this.peekIdent('and')) {
|
|
1217
|
+
while (this.acceptIdent('and')) {
|
|
1218
|
+
node.addChild(this._parseStyleInParens());
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
else if (this.peekIdent('or')) {
|
|
1222
|
+
while (this.acceptIdent('or')) {
|
|
1223
|
+
node.addChild(this._parseStyleInParens());
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
else {
|
|
1228
|
+
node.addChild(this._parseDeclaration([TokenType.ParenthesisR]));
|
|
1229
|
+
}
|
|
1230
|
+
return this.finish(node);
|
|
1231
|
+
}
|
|
1232
|
+
_parseStyleInParens() {
|
|
1233
|
+
const node = this.create(nodes.Node);
|
|
1234
|
+
if (this.accept(TokenType.ParenthesisL)) {
|
|
1235
|
+
node.addChild(this._parseStyleQuery());
|
|
1236
|
+
if (!this.accept(TokenType.ParenthesisR)) {
|
|
1237
|
+
return this.finish(node, ParseError.RightParenthesisExpected, [], [TokenType.CurlyL]);
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
else {
|
|
1241
|
+
return this.finish(node, ParseError.LeftParenthesisExpected, [], [TokenType.CurlyL]);
|
|
1242
|
+
}
|
|
1243
|
+
return this.finish(node);
|
|
1244
|
+
}
|
|
1137
1245
|
// https://www.w3.org/TR/css-syntax-3/#consume-an-at-rule
|
|
1138
1246
|
_parseUnknownAtRule() {
|
|
1139
1247
|
if (!this.peek(TokenType.AtKeyword)) {
|
|
@@ -1562,6 +1670,7 @@ export class Parser {
|
|
|
1562
1670
|
this.peek(TokenType.Angle) ||
|
|
1563
1671
|
this.peek(TokenType.Time) ||
|
|
1564
1672
|
this.peek(TokenType.Dimension) ||
|
|
1673
|
+
this.peek(TokenType.ContainerQueryLength) ||
|
|
1565
1674
|
this.peek(TokenType.Freq)) {
|
|
1566
1675
|
const node = this.create(nodes.NumericValue);
|
|
1567
1676
|
this.consumeToken();
|
|
@@ -47,7 +47,8 @@ export var TokenType;
|
|
|
47
47
|
TokenType[TokenType["Comment"] = 39] = "Comment";
|
|
48
48
|
TokenType[TokenType["SingleLineComment"] = 40] = "SingleLineComment";
|
|
49
49
|
TokenType[TokenType["EOF"] = 41] = "EOF";
|
|
50
|
-
TokenType[TokenType["
|
|
50
|
+
TokenType[TokenType["ContainerQueryLength"] = 42] = "ContainerQueryLength";
|
|
51
|
+
TokenType[TokenType["CustomToken"] = 43] = "CustomToken"; // must be last token type
|
|
51
52
|
})(TokenType || (TokenType = {}));
|
|
52
53
|
export class MultiLineStream {
|
|
53
54
|
constructor(source) {
|
|
@@ -184,6 +185,12 @@ staticUnitTable['%'] = TokenType.Percentage;
|
|
|
184
185
|
staticUnitTable['fr'] = TokenType.Percentage;
|
|
185
186
|
staticUnitTable['dpi'] = TokenType.Resolution;
|
|
186
187
|
staticUnitTable['dpcm'] = TokenType.Resolution;
|
|
188
|
+
staticUnitTable['cqw'] = TokenType.ContainerQueryLength;
|
|
189
|
+
staticUnitTable['cqh'] = TokenType.ContainerQueryLength;
|
|
190
|
+
staticUnitTable['cqi'] = TokenType.ContainerQueryLength;
|
|
191
|
+
staticUnitTable['cqb'] = TokenType.ContainerQueryLength;
|
|
192
|
+
staticUnitTable['cqmin'] = TokenType.ContainerQueryLength;
|
|
193
|
+
staticUnitTable['cqmax'] = TokenType.ContainerQueryLength;
|
|
187
194
|
export class Scanner {
|
|
188
195
|
constructor() {
|
|
189
196
|
this.stream = new MultiLineStream('');
|
|
@@ -53,7 +53,7 @@ export class LESSParser extends cssParser.Parser {
|
|
|
53
53
|
if (!this.peek(TokenType.SemiColon) && !this.peek(TokenType.EOF)) {
|
|
54
54
|
node.setMedialist(this._parseMediaQueryList());
|
|
55
55
|
}
|
|
56
|
-
return this.
|
|
56
|
+
return this._completeParseImport(node);
|
|
57
57
|
}
|
|
58
58
|
_parsePlugin() {
|
|
59
59
|
if (!this.peekKeyword('@plugin')) {
|
|
@@ -46,10 +46,7 @@ export class SCSSParser extends cssParser.Parser {
|
|
|
46
46
|
return this.finish(node, ParseError.URIOrStringExpected);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
|
|
50
|
-
node.setMedialist(this._parseMediaQueryList());
|
|
51
|
-
}
|
|
52
|
-
return this.finish(node);
|
|
49
|
+
return this._completeParseImport(node);
|
|
53
50
|
}
|
|
54
51
|
// scss variables: $font-size: 12px;
|
|
55
52
|
_parseVariableDeclaration(panic = []) {
|
|
@@ -101,6 +98,9 @@ export class SCSSParser extends cssParser.Parser {
|
|
|
101
98
|
_parseKeyframeSelector() {
|
|
102
99
|
return this._tryParseKeyframeSelector()
|
|
103
100
|
|| this._parseControlStatement(this._parseKeyframeSelector.bind(this))
|
|
101
|
+
|| this._parseWarnAndDebug() // @warn, @debug and @error statements
|
|
102
|
+
|| this._parseMixinReference() // @include
|
|
103
|
+
|| this._parseFunctionDeclaration() // @function
|
|
104
104
|
|| this._parseVariableDeclaration()
|
|
105
105
|
|| this._parseMixinContent();
|
|
106
106
|
}
|
|
@@ -17,6 +17,9 @@ export class CSSNavigation {
|
|
|
17
17
|
this.fileSystemProvider = fileSystemProvider;
|
|
18
18
|
this.resolveModuleReferences = resolveModuleReferences;
|
|
19
19
|
}
|
|
20
|
+
configure(settings) {
|
|
21
|
+
this.defaultSettings = settings;
|
|
22
|
+
}
|
|
20
23
|
findDefinition(document, position, stylesheet) {
|
|
21
24
|
const symbols = new Symbols(stylesheet);
|
|
22
25
|
const offset = document.offsetAt(position);
|
|
@@ -334,7 +337,7 @@ export class CSSNavigation {
|
|
|
334
337
|
async mapReference(target, isRawLink) {
|
|
335
338
|
return target;
|
|
336
339
|
}
|
|
337
|
-
async resolveReference(target, documentUri, documentContext, isRawLink = false) {
|
|
340
|
+
async resolveReference(target, documentUri, documentContext, isRawLink = false, settings = this.defaultSettings) {
|
|
338
341
|
// Following [css-loader](https://github.com/webpack-contrib/css-loader#url)
|
|
339
342
|
// and [sass-loader's](https://github.com/webpack-contrib/sass-loader#imports)
|
|
340
343
|
// convention, if an import path starts with ~ then use node module resolution
|
|
@@ -357,6 +360,24 @@ export class CSSNavigation {
|
|
|
357
360
|
return moduleReference;
|
|
358
361
|
}
|
|
359
362
|
}
|
|
363
|
+
// Try resolving the reference from the language configuration alias settings
|
|
364
|
+
if (ref && !(await this.fileExists(ref))) {
|
|
365
|
+
const rootFolderUri = documentContext.resolveReference('/', documentUri);
|
|
366
|
+
if (settings && rootFolderUri) {
|
|
367
|
+
// Specific file reference
|
|
368
|
+
if (target in settings) {
|
|
369
|
+
return this.mapReference(joinPath(rootFolderUri, settings[target]), isRawLink);
|
|
370
|
+
}
|
|
371
|
+
// Reference folder
|
|
372
|
+
const firstSlash = target.indexOf('/');
|
|
373
|
+
const prefix = `${target.substring(0, firstSlash)}/`;
|
|
374
|
+
if (prefix in settings) {
|
|
375
|
+
const aliasPath = (settings[prefix]).slice(0, -1);
|
|
376
|
+
let newPath = joinPath(rootFolderUri, aliasPath);
|
|
377
|
+
return this.mapReference(newPath = joinPath(newPath, target.substring(prefix.length - 1)), isRawLink);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
360
381
|
// fall back. it might not exists
|
|
361
382
|
return ref;
|
|
362
383
|
}
|
|
@@ -35,15 +35,15 @@ export class SCSSNavigation extends CSSNavigation {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
function toPathVariations(target) {
|
|
38
|
-
// No variation for links that ends with suffix
|
|
39
|
-
if (target.endsWith('.
|
|
38
|
+
// No variation for links that ends with .css suffix
|
|
39
|
+
if (target.endsWith('.css')) {
|
|
40
40
|
return [target];
|
|
41
41
|
}
|
|
42
42
|
// If a link is like a/, try resolving a/index.scss and a/_index.scss
|
|
43
43
|
if (target.endsWith('/')) {
|
|
44
44
|
return [target + 'index.scss', target + '_index.scss'];
|
|
45
45
|
}
|
|
46
|
-
const targetUri = URI.parse(target);
|
|
46
|
+
const targetUri = URI.parse(target.replace(/\.scss$/, ''));
|
|
47
47
|
const basename = Utils.basename(targetUri);
|
|
48
48
|
const dirname = Utils.dirname(targetUri);
|
|
49
49
|
if (basename.startsWith('_')) {
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import * as nodes from '../parser/cssNodes';
|
|
7
7
|
import { Scanner } from '../parser/cssScanner';
|
|
8
8
|
import * as l10n from '@vscode/l10n';
|
|
9
|
+
import { Parser } from '../parser/cssParser';
|
|
9
10
|
export class Element {
|
|
10
11
|
constructor() {
|
|
11
12
|
this.parent = null;
|
|
@@ -402,10 +403,9 @@ export class SelectorPrinting {
|
|
|
402
403
|
specificity.tag += mostSpecificListItem.tag;
|
|
403
404
|
continue elementLoop;
|
|
404
405
|
}
|
|
405
|
-
if (text.match(/^:(?:
|
|
406
|
+
if (text.match(/^:(?:host|host-context)/i) && childElements.length > 0) {
|
|
406
407
|
// The specificity of :host() is that of a pseudo-class, plus the specificity of its argument.
|
|
407
408
|
// The specificity of :host-context() is that of a pseudo-class, plus the specificity of its argument.
|
|
408
|
-
// The specificity of an :nth-child() or :nth-last-child() selector is the specificity of the pseudo class itself (counting as one pseudo-class selector) plus the specificity of the most specific complex selector in its selector list argument.
|
|
409
409
|
specificity.attr++;
|
|
410
410
|
let mostSpecificListItem = calculateMostSpecificListItem(childElements);
|
|
411
411
|
specificity.id += mostSpecificListItem.id;
|
|
@@ -413,6 +413,42 @@ export class SelectorPrinting {
|
|
|
413
413
|
specificity.tag += mostSpecificListItem.tag;
|
|
414
414
|
continue elementLoop;
|
|
415
415
|
}
|
|
416
|
+
if (text.match(/^:(?:nth-child|nth-last-child)/i) && childElements.length > 0) {
|
|
417
|
+
/* The specificity of the :nth-child(An+B [of S]?) pseudo-class is the specificity of a single pseudo-class plus, if S is specified, the specificity of the most specific complex selector in S */
|
|
418
|
+
// https://www.w3.org/TR/selectors-4/#the-nth-child-pseudo
|
|
419
|
+
specificity.attr++;
|
|
420
|
+
// 23 = Binary Expression.
|
|
421
|
+
if (childElements.length === 3 && childElements[1].type === 23) {
|
|
422
|
+
let mostSpecificListItem = calculateMostSpecificListItem(childElements[2].getChildren());
|
|
423
|
+
specificity.id += mostSpecificListItem.id;
|
|
424
|
+
specificity.attr += mostSpecificListItem.attr;
|
|
425
|
+
specificity.tag += mostSpecificListItem.tag;
|
|
426
|
+
continue elementLoop;
|
|
427
|
+
}
|
|
428
|
+
// Edge case: 'n' without integer prefix A, with B integer non-existent, is not regarded as a binary expression token.
|
|
429
|
+
const parser = new Parser();
|
|
430
|
+
const pseudoSelectorText = childElements[1].getText();
|
|
431
|
+
parser.scanner.setSource(pseudoSelectorText);
|
|
432
|
+
const firstToken = parser.scanner.scan();
|
|
433
|
+
const secondToken = parser.scanner.scan();
|
|
434
|
+
if (firstToken.text === 'n' || firstToken.text === '-n' && secondToken.text === 'of') {
|
|
435
|
+
const complexSelectorListNodes = [];
|
|
436
|
+
const complexSelectorText = pseudoSelectorText.slice(secondToken.offset + 2);
|
|
437
|
+
const complexSelectorArray = complexSelectorText.split(',');
|
|
438
|
+
for (const selector of complexSelectorArray) {
|
|
439
|
+
const node = parser.internalParse(selector, parser._parseSelector);
|
|
440
|
+
if (node) {
|
|
441
|
+
complexSelectorListNodes.push(node);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
let mostSpecificListItem = calculateMostSpecificListItem(complexSelectorListNodes);
|
|
445
|
+
specificity.id += mostSpecificListItem.id;
|
|
446
|
+
specificity.attr += mostSpecificListItem.attr;
|
|
447
|
+
specificity.tag += mostSpecificListItem.tag;
|
|
448
|
+
continue elementLoop;
|
|
449
|
+
}
|
|
450
|
+
continue elementLoop;
|
|
451
|
+
}
|
|
416
452
|
specificity.attr++; //pseudo class
|
|
417
453
|
continue elementLoop;
|
|
418
454
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// copied from js-beautify/js/lib/beautify-css.js
|
|
2
|
-
// version: 1.14.
|
|
2
|
+
// version: 1.14.11
|
|
3
3
|
/* AUTO-GENERATED. DO NOT MODIFY. */
|
|
4
4
|
/*
|
|
5
5
|
|
|
@@ -1283,13 +1283,11 @@ Beautifier.prototype.beautify = function() {
|
|
|
1283
1283
|
|
|
1284
1284
|
if (variable.match(/[ :]$/)) {
|
|
1285
1285
|
// we have a variable or pseudo-class, add it and insert one space before continuing
|
|
1286
|
-
variable = this.eatString(": ").replace(/\s
|
|
1286
|
+
variable = this.eatString(": ").replace(/\s+$/, '');
|
|
1287
1287
|
this.print_string(variable);
|
|
1288
1288
|
this._output.space_before_token = true;
|
|
1289
1289
|
}
|
|
1290
1290
|
|
|
1291
|
-
variable = variable.replace(/\s$/, '');
|
|
1292
|
-
|
|
1293
1291
|
// might be sass variable
|
|
1294
1292
|
if (parenLevel === 0 && variable.indexOf(':') !== -1) {
|
|
1295
1293
|
insidePropertyValue = true;
|
|
@@ -1309,13 +1307,11 @@ Beautifier.prototype.beautify = function() {
|
|
|
1309
1307
|
|
|
1310
1308
|
if (variableOrRule.match(/[ :]$/)) {
|
|
1311
1309
|
// we have a variable or pseudo-class, add it and insert one space before continuing
|
|
1312
|
-
variableOrRule = this.eatString(": ").replace(/\s
|
|
1310
|
+
variableOrRule = this.eatString(": ").replace(/\s+$/, '');
|
|
1313
1311
|
this.print_string(variableOrRule);
|
|
1314
1312
|
this._output.space_before_token = true;
|
|
1315
1313
|
}
|
|
1316
1314
|
|
|
1317
|
-
variableOrRule = variableOrRule.replace(/\s$/, '');
|
|
1318
|
-
|
|
1319
1315
|
// might be less variable
|
|
1320
1316
|
if (parenLevel === 0 && variableOrRule.indexOf(':') !== -1) {
|
|
1321
1317
|
insidePropertyValue = true;
|
|
@@ -60,6 +60,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
60
60
|
validation.configure(settings);
|
|
61
61
|
completion.configure(settings?.completion);
|
|
62
62
|
hover.configure(settings?.hover);
|
|
63
|
+
navigation.configure(settings?.importAliases);
|
|
63
64
|
},
|
|
64
65
|
setDataProviders: cssDataManager.setDataProviders.bind(cssDataManager),
|
|
65
66
|
doValidation: validation.doValidation.bind(validation),
|
|
@@ -13,6 +13,10 @@ export interface LanguageSettings {
|
|
|
13
13
|
lint?: LintSettings;
|
|
14
14
|
completion?: CompletionSettings;
|
|
15
15
|
hover?: HoverSettings;
|
|
16
|
+
importAliases?: AliasSettings;
|
|
17
|
+
}
|
|
18
|
+
export interface AliasSettings {
|
|
19
|
+
[key: string]: string;
|
|
16
20
|
}
|
|
17
21
|
export interface HoverSettings {
|
|
18
22
|
documentation?: boolean;
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*--------------------------------------------------------------------------------------------*/
|
|
14
14
|
'use strict';
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.ParseErrorCollector = exports.Marker = exports.Level = exports.Module = exports.GuardCondition = exports.LessGuard = exports.ListEntry = exports.UnknownAtRule = exports.MixinDeclaration = exports.MixinReference = exports.MixinContentDeclaration = exports.MixinContentReference = exports.ExtendsReference = exports.Variable = exports.Interpolation = exports.VariableDeclaration = exports.NumericValue = exports.RatioValue = exports.HexColorValue = exports.Operator = exports.AttributeSelector = exports.Term = exports.BinaryExpression = exports.Expression = exports.PageBoxMarginBox = exports.Page = exports.SupportsCondition = exports.MediaFeature = exports.MediaCondition = exports.MediaQuery = exports.Medialist = exports.Document = exports.PropertyAtRule = exports.Layer = exports.Supports = exports.Media = exports.Namespace = exports.ForwardVisibility = exports.Forward = exports.ModuleConfiguration = exports.Use = exports.Import = exports.KeyframeSelector = exports.Keyframe = exports.NestedProperties = exports.FontFace = exports.ViewPort = exports.FunctionDeclaration = exports.ElseStatement = exports.WhileStatement = exports.EachStatement = exports.ForStatement = exports.IfStatement = exports.FunctionArgument = exports.FunctionParameter = exports.Function = exports.Invocation = exports.Property = exports.CustomPropertyDeclaration = exports.Declaration = exports.CustomPropertySet = exports.AbstractDeclaration = exports.AtApplyRule = exports.SimpleSelector = exports.Selector = exports.RuleSet = exports.BodyDeclaration = exports.Declarations = exports.Stylesheet = exports.Identifier = exports.UnicodeRange = exports.Nodelist = exports.Node = exports.getParentDeclaration = exports.getNodePath = exports.getNodeAtOffset = exports.ReferenceType = exports.NodeType = void 0;
|
|
16
|
+
exports.ParseErrorCollector = exports.Marker = exports.Level = exports.Module = exports.GuardCondition = exports.LessGuard = exports.ListEntry = exports.UnknownAtRule = exports.MixinDeclaration = exports.MixinReference = exports.MixinContentDeclaration = exports.MixinContentReference = exports.ExtendsReference = exports.Variable = exports.Interpolation = exports.VariableDeclaration = exports.NumericValue = exports.RatioValue = exports.HexColorValue = exports.Operator = exports.AttributeSelector = exports.Term = exports.BinaryExpression = exports.Expression = exports.PageBoxMarginBox = exports.Page = exports.SupportsCondition = exports.MediaFeature = exports.MediaCondition = exports.MediaQuery = exports.Medialist = exports.Container = exports.Document = exports.PropertyAtRule = exports.Layer = exports.Supports = exports.Media = exports.Namespace = exports.ForwardVisibility = exports.Forward = exports.ModuleConfiguration = exports.Use = exports.Import = exports.KeyframeSelector = exports.Keyframe = exports.NestedProperties = exports.FontFace = exports.ViewPort = exports.FunctionDeclaration = exports.ElseStatement = exports.WhileStatement = exports.EachStatement = exports.ForStatement = exports.IfStatement = exports.FunctionArgument = exports.FunctionParameter = exports.Function = exports.Invocation = exports.Property = exports.CustomPropertyDeclaration = exports.Declaration = exports.CustomPropertySet = exports.AbstractDeclaration = exports.AtApplyRule = exports.SimpleSelector = exports.Selector = exports.RuleSet = exports.BodyDeclaration = exports.Declarations = exports.Stylesheet = exports.Identifier = exports.UnicodeRange = exports.Nodelist = exports.Node = exports.getParentDeclaration = exports.getNodePath = exports.getNodeAtOffset = exports.ReferenceType = exports.NodeType = void 0;
|
|
17
17
|
const strings_1 = require("../utils/strings");
|
|
18
18
|
/// <summary>
|
|
19
19
|
/// Nodes for the css 2.1 specification. See for reference:
|
|
@@ -108,6 +108,7 @@
|
|
|
108
108
|
NodeType[NodeType["LayerNameList"] = 84] = "LayerNameList";
|
|
109
109
|
NodeType[NodeType["LayerName"] = 85] = "LayerName";
|
|
110
110
|
NodeType[NodeType["PropertyAtRule"] = 86] = "PropertyAtRule";
|
|
111
|
+
NodeType[NodeType["Container"] = 87] = "Container";
|
|
111
112
|
})(NodeType || (exports.NodeType = NodeType = {}));
|
|
112
113
|
var ReferenceType;
|
|
113
114
|
(function (ReferenceType) {
|
|
@@ -978,6 +979,15 @@
|
|
|
978
979
|
}
|
|
979
980
|
}
|
|
980
981
|
exports.Document = Document;
|
|
982
|
+
class Container extends BodyDeclaration {
|
|
983
|
+
constructor(offset, length) {
|
|
984
|
+
super(offset, length);
|
|
985
|
+
}
|
|
986
|
+
get type() {
|
|
987
|
+
return NodeType.Container;
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
exports.Container = Container;
|
|
981
991
|
class Medialist extends Node {
|
|
982
992
|
constructor(offset, length) {
|
|
983
993
|
super(offset, length);
|
|
@@ -287,6 +287,7 @@
|
|
|
287
287
|
|| this._parseViewPort()
|
|
288
288
|
|| this._parseNamespace()
|
|
289
289
|
|| this._parseDocument()
|
|
290
|
+
|| this._parseContainer()
|
|
290
291
|
|| this._parseUnknownAtRule();
|
|
291
292
|
}
|
|
292
293
|
_tryParseRuleset(isNested) {
|
|
@@ -626,6 +627,9 @@
|
|
|
626
627
|
if (!node.addChild(this._parseURILiteral()) && !node.addChild(this._parseStringLiteral())) {
|
|
627
628
|
return this.finish(node, cssErrors_1.ParseError.URIOrStringExpected);
|
|
628
629
|
}
|
|
630
|
+
return this._completeParseImport(node);
|
|
631
|
+
}
|
|
632
|
+
_completeParseImport(node) {
|
|
629
633
|
if (this.acceptIdent('layer')) {
|
|
630
634
|
if (this.accept(cssScanner_1.TokenType.ParenthesisL)) {
|
|
631
635
|
if (!node.addChild(this._parseLayerName())) {
|
|
@@ -822,11 +826,10 @@
|
|
|
822
826
|
}
|
|
823
827
|
_parseLayerName() {
|
|
824
828
|
// <layer-name> = <ident> [ '.' <ident> ]*
|
|
825
|
-
|
|
829
|
+
const node = this.createNode(nodes.NodeType.LayerName);
|
|
830
|
+
if (!node.addChild(this._parseIdent())) {
|
|
826
831
|
return null;
|
|
827
832
|
}
|
|
828
|
-
const node = this.createNode(nodes.NodeType.LayerName);
|
|
829
|
-
node.addChild(this._parseIdent());
|
|
830
833
|
while (!this.hasWhitespace() && this.acceptDelim('.')) {
|
|
831
834
|
if (this.hasWhitespace() || !node.addChild(this._parseIdent())) {
|
|
832
835
|
return this.finish(node, cssErrors_1.ParseError.IdentifierExpected);
|
|
@@ -1145,6 +1148,111 @@
|
|
|
1145
1148
|
this.resync([], [cssScanner_1.TokenType.CurlyL]); // ignore all the rules
|
|
1146
1149
|
return this._parseBody(node, this._parseStylesheetStatement.bind(this));
|
|
1147
1150
|
}
|
|
1151
|
+
_parseContainer() {
|
|
1152
|
+
if (!this.peekKeyword('@container')) {
|
|
1153
|
+
return null;
|
|
1154
|
+
}
|
|
1155
|
+
const node = this.create(nodes.Container);
|
|
1156
|
+
this.consumeToken(); // @container
|
|
1157
|
+
node.addChild(this._parseIdent()); // optional container name
|
|
1158
|
+
node.addChild(this._parseContainerQuery());
|
|
1159
|
+
return this._parseBody(node, this._parseStylesheetStatement.bind(this));
|
|
1160
|
+
}
|
|
1161
|
+
_parseContainerQuery() {
|
|
1162
|
+
// <container-query> = not <query-in-parens>
|
|
1163
|
+
// | <query-in-parens> [ [ and <query-in-parens> ]* | [ or <query-in-parens> ]* ]
|
|
1164
|
+
const node = this.create(nodes.Node);
|
|
1165
|
+
if (this.acceptIdent('not')) {
|
|
1166
|
+
node.addChild(this._parseContainerQueryInParens());
|
|
1167
|
+
}
|
|
1168
|
+
else {
|
|
1169
|
+
node.addChild(this._parseContainerQueryInParens());
|
|
1170
|
+
if (this.peekIdent('and')) {
|
|
1171
|
+
while (this.acceptIdent('and')) {
|
|
1172
|
+
node.addChild(this._parseContainerQueryInParens());
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
else if (this.peekIdent('or')) {
|
|
1176
|
+
while (this.acceptIdent('or')) {
|
|
1177
|
+
node.addChild(this._parseContainerQueryInParens());
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
return this.finish(node);
|
|
1182
|
+
}
|
|
1183
|
+
_parseContainerQueryInParens() {
|
|
1184
|
+
// <query-in-parens> = ( <container-query> )
|
|
1185
|
+
// | ( <size-feature> )
|
|
1186
|
+
// | style( <style-query> )
|
|
1187
|
+
// | <general-enclosed>
|
|
1188
|
+
const node = this.create(nodes.Node);
|
|
1189
|
+
if (this.accept(cssScanner_1.TokenType.ParenthesisL)) {
|
|
1190
|
+
if (this.peekIdent('not') || this.peek(cssScanner_1.TokenType.ParenthesisL)) {
|
|
1191
|
+
node.addChild(this._parseContainerQuery());
|
|
1192
|
+
}
|
|
1193
|
+
else {
|
|
1194
|
+
node.addChild(this._parseMediaFeature());
|
|
1195
|
+
}
|
|
1196
|
+
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
|
|
1197
|
+
return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected, [], [cssScanner_1.TokenType.CurlyL]);
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
else if (this.acceptIdent('style')) {
|
|
1201
|
+
if (this.hasWhitespace() || !this.accept(cssScanner_1.TokenType.ParenthesisL)) {
|
|
1202
|
+
return this.finish(node, cssErrors_1.ParseError.LeftParenthesisExpected, [], [cssScanner_1.TokenType.CurlyL]);
|
|
1203
|
+
}
|
|
1204
|
+
node.addChild(this._parseStyleQuery());
|
|
1205
|
+
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
|
|
1206
|
+
return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected, [], [cssScanner_1.TokenType.CurlyL]);
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
else {
|
|
1210
|
+
return this.finish(node, cssErrors_1.ParseError.LeftParenthesisExpected, [], [cssScanner_1.TokenType.CurlyL]);
|
|
1211
|
+
}
|
|
1212
|
+
return this.finish(node);
|
|
1213
|
+
}
|
|
1214
|
+
_parseStyleQuery() {
|
|
1215
|
+
// <style-query> = not <style-in-parens>
|
|
1216
|
+
// | <style-in-parens> [ [ and <style-in-parens> ]* | [ or <style-in-parens> ]* ]
|
|
1217
|
+
// | <style-feature>
|
|
1218
|
+
// <style-in-parens> = ( <style-query> )
|
|
1219
|
+
// | ( <style-feature> )
|
|
1220
|
+
// | <general-enclosed>
|
|
1221
|
+
const node = this.create(nodes.Node);
|
|
1222
|
+
if (this.acceptIdent('not')) {
|
|
1223
|
+
node.addChild(this._parseStyleInParens());
|
|
1224
|
+
}
|
|
1225
|
+
else if (this.peek(cssScanner_1.TokenType.ParenthesisL)) {
|
|
1226
|
+
node.addChild(this._parseStyleInParens());
|
|
1227
|
+
if (this.peekIdent('and')) {
|
|
1228
|
+
while (this.acceptIdent('and')) {
|
|
1229
|
+
node.addChild(this._parseStyleInParens());
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
else if (this.peekIdent('or')) {
|
|
1233
|
+
while (this.acceptIdent('or')) {
|
|
1234
|
+
node.addChild(this._parseStyleInParens());
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
else {
|
|
1239
|
+
node.addChild(this._parseDeclaration([cssScanner_1.TokenType.ParenthesisR]));
|
|
1240
|
+
}
|
|
1241
|
+
return this.finish(node);
|
|
1242
|
+
}
|
|
1243
|
+
_parseStyleInParens() {
|
|
1244
|
+
const node = this.create(nodes.Node);
|
|
1245
|
+
if (this.accept(cssScanner_1.TokenType.ParenthesisL)) {
|
|
1246
|
+
node.addChild(this._parseStyleQuery());
|
|
1247
|
+
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
|
|
1248
|
+
return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected, [], [cssScanner_1.TokenType.CurlyL]);
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
else {
|
|
1252
|
+
return this.finish(node, cssErrors_1.ParseError.LeftParenthesisExpected, [], [cssScanner_1.TokenType.CurlyL]);
|
|
1253
|
+
}
|
|
1254
|
+
return this.finish(node);
|
|
1255
|
+
}
|
|
1148
1256
|
// https://www.w3.org/TR/css-syntax-3/#consume-an-at-rule
|
|
1149
1257
|
_parseUnknownAtRule() {
|
|
1150
1258
|
if (!this.peek(cssScanner_1.TokenType.AtKeyword)) {
|
|
@@ -1573,6 +1681,7 @@
|
|
|
1573
1681
|
this.peek(cssScanner_1.TokenType.Angle) ||
|
|
1574
1682
|
this.peek(cssScanner_1.TokenType.Time) ||
|
|
1575
1683
|
this.peek(cssScanner_1.TokenType.Dimension) ||
|
|
1684
|
+
this.peek(cssScanner_1.TokenType.ContainerQueryLength) ||
|
|
1576
1685
|
this.peek(cssScanner_1.TokenType.Freq)) {
|
|
1577
1686
|
const node = this.create(nodes.NumericValue);
|
|
1578
1687
|
this.consumeToken();
|
|
@@ -58,7 +58,8 @@
|
|
|
58
58
|
TokenType[TokenType["Comment"] = 39] = "Comment";
|
|
59
59
|
TokenType[TokenType["SingleLineComment"] = 40] = "SingleLineComment";
|
|
60
60
|
TokenType[TokenType["EOF"] = 41] = "EOF";
|
|
61
|
-
TokenType[TokenType["
|
|
61
|
+
TokenType[TokenType["ContainerQueryLength"] = 42] = "ContainerQueryLength";
|
|
62
|
+
TokenType[TokenType["CustomToken"] = 43] = "CustomToken"; // must be last token type
|
|
62
63
|
})(TokenType || (exports.TokenType = TokenType = {}));
|
|
63
64
|
class MultiLineStream {
|
|
64
65
|
constructor(source) {
|
|
@@ -196,6 +197,12 @@
|
|
|
196
197
|
staticUnitTable['fr'] = TokenType.Percentage;
|
|
197
198
|
staticUnitTable['dpi'] = TokenType.Resolution;
|
|
198
199
|
staticUnitTable['dpcm'] = TokenType.Resolution;
|
|
200
|
+
staticUnitTable['cqw'] = TokenType.ContainerQueryLength;
|
|
201
|
+
staticUnitTable['cqh'] = TokenType.ContainerQueryLength;
|
|
202
|
+
staticUnitTable['cqi'] = TokenType.ContainerQueryLength;
|
|
203
|
+
staticUnitTable['cqb'] = TokenType.ContainerQueryLength;
|
|
204
|
+
staticUnitTable['cqmin'] = TokenType.ContainerQueryLength;
|
|
205
|
+
staticUnitTable['cqmax'] = TokenType.ContainerQueryLength;
|
|
199
206
|
class Scanner {
|
|
200
207
|
constructor() {
|
|
201
208
|
this.stream = new MultiLineStream('');
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
if (!this.peek(cssScanner_1.TokenType.SemiColon) && !this.peek(cssScanner_1.TokenType.EOF)) {
|
|
65
65
|
node.setMedialist(this._parseMediaQueryList());
|
|
66
66
|
}
|
|
67
|
-
return this.
|
|
67
|
+
return this._completeParseImport(node);
|
|
68
68
|
}
|
|
69
69
|
_parsePlugin() {
|
|
70
70
|
if (!this.peekKeyword('@plugin')) {
|
|
@@ -57,10 +57,7 @@
|
|
|
57
57
|
return this.finish(node, cssErrors_1.ParseError.URIOrStringExpected);
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
|
-
|
|
61
|
-
node.setMedialist(this._parseMediaQueryList());
|
|
62
|
-
}
|
|
63
|
-
return this.finish(node);
|
|
60
|
+
return this._completeParseImport(node);
|
|
64
61
|
}
|
|
65
62
|
// scss variables: $font-size: 12px;
|
|
66
63
|
_parseVariableDeclaration(panic = []) {
|
|
@@ -112,6 +109,9 @@
|
|
|
112
109
|
_parseKeyframeSelector() {
|
|
113
110
|
return this._tryParseKeyframeSelector()
|
|
114
111
|
|| this._parseControlStatement(this._parseKeyframeSelector.bind(this))
|
|
112
|
+
|| this._parseWarnAndDebug() // @warn, @debug and @error statements
|
|
113
|
+
|| this._parseMixinReference() // @include
|
|
114
|
+
|| this._parseFunctionDeclaration() // @function
|
|
115
115
|
|| this._parseVariableDeclaration()
|
|
116
116
|
|| this._parseMixinContent();
|
|
117
117
|
}
|
|
@@ -28,6 +28,9 @@
|
|
|
28
28
|
this.fileSystemProvider = fileSystemProvider;
|
|
29
29
|
this.resolveModuleReferences = resolveModuleReferences;
|
|
30
30
|
}
|
|
31
|
+
configure(settings) {
|
|
32
|
+
this.defaultSettings = settings;
|
|
33
|
+
}
|
|
31
34
|
findDefinition(document, position, stylesheet) {
|
|
32
35
|
const symbols = new cssSymbolScope_1.Symbols(stylesheet);
|
|
33
36
|
const offset = document.offsetAt(position);
|
|
@@ -345,7 +348,7 @@
|
|
|
345
348
|
async mapReference(target, isRawLink) {
|
|
346
349
|
return target;
|
|
347
350
|
}
|
|
348
|
-
async resolveReference(target, documentUri, documentContext, isRawLink = false) {
|
|
351
|
+
async resolveReference(target, documentUri, documentContext, isRawLink = false, settings = this.defaultSettings) {
|
|
349
352
|
// Following [css-loader](https://github.com/webpack-contrib/css-loader#url)
|
|
350
353
|
// and [sass-loader's](https://github.com/webpack-contrib/sass-loader#imports)
|
|
351
354
|
// convention, if an import path starts with ~ then use node module resolution
|
|
@@ -368,6 +371,24 @@
|
|
|
368
371
|
return moduleReference;
|
|
369
372
|
}
|
|
370
373
|
}
|
|
374
|
+
// Try resolving the reference from the language configuration alias settings
|
|
375
|
+
if (ref && !(await this.fileExists(ref))) {
|
|
376
|
+
const rootFolderUri = documentContext.resolveReference('/', documentUri);
|
|
377
|
+
if (settings && rootFolderUri) {
|
|
378
|
+
// Specific file reference
|
|
379
|
+
if (target in settings) {
|
|
380
|
+
return this.mapReference((0, resources_1.joinPath)(rootFolderUri, settings[target]), isRawLink);
|
|
381
|
+
}
|
|
382
|
+
// Reference folder
|
|
383
|
+
const firstSlash = target.indexOf('/');
|
|
384
|
+
const prefix = `${target.substring(0, firstSlash)}/`;
|
|
385
|
+
if (prefix in settings) {
|
|
386
|
+
const aliasPath = (settings[prefix]).slice(0, -1);
|
|
387
|
+
let newPath = (0, resources_1.joinPath)(rootFolderUri, aliasPath);
|
|
388
|
+
return this.mapReference(newPath = (0, resources_1.joinPath)(newPath, target.substring(prefix.length - 1)), isRawLink);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
371
392
|
// fall back. it might not exists
|
|
372
393
|
return ref;
|
|
373
394
|
}
|
|
@@ -47,15 +47,15 @@
|
|
|
47
47
|
}
|
|
48
48
|
exports.SCSSNavigation = SCSSNavigation;
|
|
49
49
|
function toPathVariations(target) {
|
|
50
|
-
// No variation for links that ends with suffix
|
|
51
|
-
if (target.endsWith('.
|
|
50
|
+
// No variation for links that ends with .css suffix
|
|
51
|
+
if (target.endsWith('.css')) {
|
|
52
52
|
return [target];
|
|
53
53
|
}
|
|
54
54
|
// If a link is like a/, try resolving a/index.scss and a/_index.scss
|
|
55
55
|
if (target.endsWith('/')) {
|
|
56
56
|
return [target + 'index.scss', target + '_index.scss'];
|
|
57
57
|
}
|
|
58
|
-
const targetUri = vscode_uri_1.URI.parse(target);
|
|
58
|
+
const targetUri = vscode_uri_1.URI.parse(target.replace(/\.scss$/, ''));
|
|
59
59
|
const basename = vscode_uri_1.Utils.basename(targetUri);
|
|
60
60
|
const dirname = vscode_uri_1.Utils.dirname(targetUri);
|
|
61
61
|
if (basename.startsWith('_')) {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
if (v !== undefined) module.exports = v;
|
|
5
5
|
}
|
|
6
6
|
else if (typeof define === "function" && define.amd) {
|
|
7
|
-
define(["require", "exports", "../parser/cssNodes", "../parser/cssScanner", "@vscode/l10n"], factory);
|
|
7
|
+
define(["require", "exports", "../parser/cssNodes", "../parser/cssScanner", "@vscode/l10n", "../parser/cssParser"], factory);
|
|
8
8
|
}
|
|
9
9
|
})(function (require, exports) {
|
|
10
10
|
/*---------------------------------------------------------------------------------------------
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
const nodes = require("../parser/cssNodes");
|
|
18
18
|
const cssScanner_1 = require("../parser/cssScanner");
|
|
19
19
|
const l10n = require("@vscode/l10n");
|
|
20
|
+
const cssParser_1 = require("../parser/cssParser");
|
|
20
21
|
class Element {
|
|
21
22
|
constructor() {
|
|
22
23
|
this.parent = null;
|
|
@@ -417,10 +418,9 @@
|
|
|
417
418
|
specificity.tag += mostSpecificListItem.tag;
|
|
418
419
|
continue elementLoop;
|
|
419
420
|
}
|
|
420
|
-
if (text.match(/^:(?:
|
|
421
|
+
if (text.match(/^:(?:host|host-context)/i) && childElements.length > 0) {
|
|
421
422
|
// The specificity of :host() is that of a pseudo-class, plus the specificity of its argument.
|
|
422
423
|
// The specificity of :host-context() is that of a pseudo-class, plus the specificity of its argument.
|
|
423
|
-
// The specificity of an :nth-child() or :nth-last-child() selector is the specificity of the pseudo class itself (counting as one pseudo-class selector) plus the specificity of the most specific complex selector in its selector list argument.
|
|
424
424
|
specificity.attr++;
|
|
425
425
|
let mostSpecificListItem = calculateMostSpecificListItem(childElements);
|
|
426
426
|
specificity.id += mostSpecificListItem.id;
|
|
@@ -428,6 +428,42 @@
|
|
|
428
428
|
specificity.tag += mostSpecificListItem.tag;
|
|
429
429
|
continue elementLoop;
|
|
430
430
|
}
|
|
431
|
+
if (text.match(/^:(?:nth-child|nth-last-child)/i) && childElements.length > 0) {
|
|
432
|
+
/* The specificity of the :nth-child(An+B [of S]?) pseudo-class is the specificity of a single pseudo-class plus, if S is specified, the specificity of the most specific complex selector in S */
|
|
433
|
+
// https://www.w3.org/TR/selectors-4/#the-nth-child-pseudo
|
|
434
|
+
specificity.attr++;
|
|
435
|
+
// 23 = Binary Expression.
|
|
436
|
+
if (childElements.length === 3 && childElements[1].type === 23) {
|
|
437
|
+
let mostSpecificListItem = calculateMostSpecificListItem(childElements[2].getChildren());
|
|
438
|
+
specificity.id += mostSpecificListItem.id;
|
|
439
|
+
specificity.attr += mostSpecificListItem.attr;
|
|
440
|
+
specificity.tag += mostSpecificListItem.tag;
|
|
441
|
+
continue elementLoop;
|
|
442
|
+
}
|
|
443
|
+
// Edge case: 'n' without integer prefix A, with B integer non-existent, is not regarded as a binary expression token.
|
|
444
|
+
const parser = new cssParser_1.Parser();
|
|
445
|
+
const pseudoSelectorText = childElements[1].getText();
|
|
446
|
+
parser.scanner.setSource(pseudoSelectorText);
|
|
447
|
+
const firstToken = parser.scanner.scan();
|
|
448
|
+
const secondToken = parser.scanner.scan();
|
|
449
|
+
if (firstToken.text === 'n' || firstToken.text === '-n' && secondToken.text === 'of') {
|
|
450
|
+
const complexSelectorListNodes = [];
|
|
451
|
+
const complexSelectorText = pseudoSelectorText.slice(secondToken.offset + 2);
|
|
452
|
+
const complexSelectorArray = complexSelectorText.split(',');
|
|
453
|
+
for (const selector of complexSelectorArray) {
|
|
454
|
+
const node = parser.internalParse(selector, parser._parseSelector);
|
|
455
|
+
if (node) {
|
|
456
|
+
complexSelectorListNodes.push(node);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
let mostSpecificListItem = calculateMostSpecificListItem(complexSelectorListNodes);
|
|
460
|
+
specificity.id += mostSpecificListItem.id;
|
|
461
|
+
specificity.attr += mostSpecificListItem.attr;
|
|
462
|
+
specificity.tag += mostSpecificListItem.tag;
|
|
463
|
+
continue elementLoop;
|
|
464
|
+
}
|
|
465
|
+
continue elementLoop;
|
|
466
|
+
}
|
|
431
467
|
specificity.attr++; //pseudo class
|
|
432
468
|
continue elementLoop;
|
|
433
469
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vscode-css-languageservice",
|
|
3
|
-
"version": "6.2.
|
|
3
|
+
"version": "6.2.11",
|
|
4
4
|
"description": "Language service for CSS, LESS and SCSS",
|
|
5
5
|
"main": "./lib/umd/cssLanguageService.js",
|
|
6
6
|
"typings": "./lib/umd/cssLanguageService",
|
|
@@ -15,23 +15,23 @@
|
|
|
15
15
|
"url": "https://github.com/Microsoft/vscode-css-languageservice"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@types/mocha": "^10.0.
|
|
18
|
+
"@types/mocha": "^10.0.6",
|
|
19
19
|
"@types/node": "16.x",
|
|
20
|
-
"@typescript-eslint/eslint-plugin": "^6.
|
|
21
|
-
"@typescript-eslint/parser": "^6.
|
|
20
|
+
"@typescript-eslint/eslint-plugin": "^6.13.0",
|
|
21
|
+
"@typescript-eslint/parser": "^6.13.0",
|
|
22
22
|
"@vscode/web-custom-data": "^0.4.8",
|
|
23
|
-
"eslint": "^8.
|
|
24
|
-
"js-beautify": "^1.14.
|
|
23
|
+
"eslint": "^8.54.0",
|
|
24
|
+
"js-beautify": "^1.14.11",
|
|
25
25
|
"mocha": "^10.2.0",
|
|
26
|
-
"rimraf": "^5.0.
|
|
26
|
+
"rimraf": "^5.0.5",
|
|
27
27
|
"source-map-support": "^0.5.21",
|
|
28
28
|
"typescript": "^5.2.2"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@vscode/l10n": "^0.0.16",
|
|
32
|
-
"vscode-languageserver-textdocument": "^1.0.
|
|
33
|
-
"vscode-languageserver-types": "3.17.
|
|
34
|
-
"vscode-uri": "^3.0.
|
|
32
|
+
"vscode-languageserver-textdocument": "^1.0.11",
|
|
33
|
+
"vscode-languageserver-types": "3.17.5",
|
|
34
|
+
"vscode-uri": "^3.0.8"
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
|
37
37
|
"prepack": "npm run clean && npm run compile-esm && npm run test && npm run remove-sourcemap-refs",
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
"mocha": "mocha --require source-map-support/register",
|
|
45
45
|
"coverage": "npm run compile && npx nyc --reporter=html --reporter=text mocha",
|
|
46
46
|
"lint": "eslint src/**/*.ts",
|
|
47
|
-
"update-data": "
|
|
48
|
-
"install-types-next": "
|
|
47
|
+
"update-data": "npm install @vscode/web-custom-data -D && node ./build/generateData.js",
|
|
48
|
+
"install-types-next": "npm install vscode-languageserver-types@next -f -S && npm install vscode-languageserver-textdocument@next -f -S",
|
|
49
49
|
"copy-jsbeautify": "node ./build/copy-jsbeautify.js",
|
|
50
|
-
"update-jsbeautify": "
|
|
51
|
-
"update-jsbeautify-next": "
|
|
50
|
+
"update-jsbeautify": "npm install js-beautify && node ./build/update-jsbeautify.js",
|
|
51
|
+
"update-jsbeautify-next": "npm install js-beautify@next && node ./build/update-jsbeautify.js"
|
|
52
52
|
}
|
|
53
53
|
}
|
package/thirdpartynotices.txt
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
THIRD-PARTY SOFTWARE NOTICES AND INFORMATION
|
|
2
|
-
|
|
3
|
-
vscode-css-languageservice incorporates third party material from the projects listed below. The original copyright
|
|
4
|
-
notice and the license under which Microsoft received such third party material are set forth below. Microsoft
|
|
5
|
-
reserves all other rights not expressly granted, whether by implication, estoppel or otherwise.
|
|
6
|
-
|
|
7
|
-
1. JS Beautifier (https://github.com/beautify-web/js-beautify)
|
|
8
|
-
|
|
9
|
-
The MIT License (MIT)
|
|
10
|
-
|
|
11
|
-
Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
|
|
12
|
-
|
|
13
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
15
|
-
in the Software without restriction, including without limitation the rights
|
|
16
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
18
|
-
furnished to do so, subject to the following conditions:
|
|
19
|
-
|
|
20
|
-
The above copyright notice and this permission notice shall be included in
|
|
21
|
-
all copies or substantial portions of the Software.
|
|
22
|
-
|
|
23
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
29
|
-
THE SOFTWARE.
|