vscode-css-languageservice 6.3.8 → 6.3.10

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.
@@ -60,7 +60,8 @@
60
60
  };
61
61
  exports.cssWideFunctions = {
62
62
  'var()': 'Evaluates the value of a custom variable.',
63
- 'calc()': 'Evaluates an mathematical expression. The following operators can be used: + - * /.'
63
+ 'calc()': 'Evaluates an mathematical expression. The following operators can be used: + - * /.',
64
+ 'if()': 'Evaluates a conditional expression.'
64
65
  };
65
66
  exports.imageFunctions = {
66
67
  'url()': 'Reference an image file by URL',
@@ -56,5 +56,6 @@
56
56
  IdentifierOrWildcardExpected: new CSSIssueType('css-idorwildcardexpected', l10n.t("identifier or wildcard expected")),
57
57
  WildcardExpected: new CSSIssueType('css-wildcardexpected', l10n.t("wildcard expected")),
58
58
  IdentifierOrVariableExpected: new CSSIssueType('css-idorvarexpected', l10n.t("identifier or variable expected")),
59
+ IfConditionExpected: new CSSIssueType('css-ifconditionexpected', l10n.t("if condition expected")),
59
60
  };
60
61
  });
@@ -418,8 +418,8 @@
418
418
  }
419
419
  return hasContent ? this.finish(node) : null;
420
420
  }
421
- _parseDeclaration(stopTokens) {
422
- const customProperty = this._tryParseCustomPropertyDeclaration(stopTokens);
421
+ _parseDeclaration(stopTokens, standaloneCustomPropertyValid = false) {
422
+ const customProperty = this._tryParseCustomPropertyDeclaration(stopTokens, standaloneCustomPropertyValid);
423
423
  if (customProperty) {
424
424
  return customProperty;
425
425
  }
@@ -442,7 +442,7 @@
442
442
  }
443
443
  return this.finish(node);
444
444
  }
445
- _tryParseCustomPropertyDeclaration(stopTokens) {
445
+ _tryParseCustomPropertyDeclaration(stopTokens, standaloneCustomPropertyValid = false) {
446
446
  if (!this.peekRegExp(cssScanner_1.TokenType.Ident, /^--/)) {
447
447
  return null;
448
448
  }
@@ -451,6 +451,9 @@
451
451
  return null;
452
452
  }
453
453
  if (!this.accept(cssScanner_1.TokenType.Colon)) {
454
+ if (standaloneCustomPropertyValid) {
455
+ return this.finish(node);
456
+ }
454
457
  return this.finish(node, cssErrors_1.ParseError.ColonExpected, [cssScanner_1.TokenType.Colon]);
455
458
  }
456
459
  if (this.prevToken) {
@@ -1017,6 +1020,56 @@
1017
1020
  }
1018
1021
  return this.finish(node);
1019
1022
  }
1023
+ _parseBooleanExpression(parseTest) {
1024
+ // <boolean-expr[ <test> ]> = not <boolean-expr-group> | <boolean-expr-group>
1025
+ // [ [ and <boolean-expr-group> ]*
1026
+ // | [ or <boolean-expr-group> ]* ]
1027
+ const node = this.create(nodes.Node);
1028
+ if (this.acceptIdent('not')) {
1029
+ if (!node.addChild(this._parseBooleanExpressionGroup(parseTest))) {
1030
+ return null;
1031
+ }
1032
+ }
1033
+ else {
1034
+ if (!node.addChild(this._parseBooleanExpressionGroup(parseTest))) {
1035
+ return null;
1036
+ }
1037
+ if (this.peekIdent('and')) {
1038
+ while (this.acceptIdent('and')) {
1039
+ if (!node.addChild(this._parseBooleanExpressionGroup(parseTest))) {
1040
+ return null;
1041
+ }
1042
+ }
1043
+ }
1044
+ else if (this.peekIdent('or')) {
1045
+ while (this.acceptIdent('or')) {
1046
+ if (!node.addChild(this._parseBooleanExpressionGroup(parseTest))) {
1047
+ return null;
1048
+ }
1049
+ }
1050
+ }
1051
+ }
1052
+ return this.finish(node);
1053
+ }
1054
+ _parseBooleanExpressionGroup(parseTest) {
1055
+ // <boolean-expr-group> = <test> | ( <boolean-expr[ <test> ]> ) | <general-enclosed>
1056
+ const node = this.create(nodes.Node);
1057
+ const pos = this.mark();
1058
+ if (this.accept(cssScanner_1.TokenType.ParenthesisL)) {
1059
+ if (node.addChild(this._parseBooleanExpression(parseTest))) {
1060
+ if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
1061
+ return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected, [], [cssScanner_1.TokenType.CurlyL]);
1062
+ }
1063
+ return this.finish(node);
1064
+ }
1065
+ this.restoreAtMark(pos);
1066
+ }
1067
+ if (!node.addChild(parseTest())) {
1068
+ return null;
1069
+ }
1070
+ ;
1071
+ return this.finish(node);
1072
+ }
1020
1073
  _parseMediaCondition() {
1021
1074
  // <media-condition> = <media-not> | <media-and> | <media-or> | <media-in-parens>
1022
1075
  // <media-not> = not <media-in-parens>
@@ -1136,7 +1189,7 @@
1136
1189
  if (this.accept(cssScanner_1.TokenType.ParenthesisL)) {
1137
1190
  // scope-start selector can start with a combinator as it defaults to :scope
1138
1191
  // Treat as nested
1139
- if (!node.setScopeStart(this._parseSelector(true))) {
1192
+ if (!node.setScopeStart(this._parseScopeSelectorList())) {
1140
1193
  return this.finish(node, cssErrors_1.ParseError.SelectorExpected, [], [cssScanner_1.TokenType.ParenthesisR]);
1141
1194
  }
1142
1195
  if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
@@ -1150,7 +1203,7 @@
1150
1203
  }
1151
1204
  // 'to' selector can start with a combinator as it defaults to :scope
1152
1205
  // Treat as nested
1153
- if (!node.setScopeEnd(this._parseSelector(true))) {
1206
+ if (!node.setScopeEnd(this._parseScopeSelectorList())) {
1154
1207
  return this.finish(node, cssErrors_1.ParseError.SelectorExpected, [], [cssScanner_1.TokenType.ParenthesisR]);
1155
1208
  }
1156
1209
  if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
@@ -1159,6 +1212,16 @@
1159
1212
  }
1160
1213
  return this.finish(node);
1161
1214
  }
1215
+ _parseScopeSelectorList() {
1216
+ const selectors = this.createNode(nodes.NodeType.SelectorList);
1217
+ if (!selectors.addChild(this._parseSelector(true))) {
1218
+ return null;
1219
+ }
1220
+ while (this.accept(cssScanner_1.TokenType.Comma) && selectors.addChild(this._parseSelector(true))) {
1221
+ // loop
1222
+ }
1223
+ return this.finish(selectors);
1224
+ }
1162
1225
  _parseMedium() {
1163
1226
  const node = this.create(nodes.Node);
1164
1227
  if (node.addChild(this._parseIdent())) {
@@ -1239,7 +1302,15 @@
1239
1302
  const node = this.create(nodes.Container);
1240
1303
  this.consumeToken(); // @container
1241
1304
  node.addChild(this._parseIdent()); // optional container name
1242
- node.addChild(this._parseContainerQuery());
1305
+ if (node.addChild(this._parseContainerQuery())) {
1306
+ while (this.accept(cssScanner_1.TokenType.Comma)) {
1307
+ if (this.peek(cssScanner_1.TokenType.CurlyL)) {
1308
+ break;
1309
+ }
1310
+ node.addChild(this._parseIdent()); // optional container name
1311
+ node.addChild(this._parseContainerQuery());
1312
+ }
1313
+ }
1243
1314
  return this._parseBody(node, this._parseContainerDeclaration.bind(this, isNested));
1244
1315
  }
1245
1316
  _parseContainerQuery() {
@@ -1250,7 +1321,7 @@
1250
1321
  node.addChild(this._parseContainerQueryInParens());
1251
1322
  }
1252
1323
  else {
1253
- node.addChild(this._parseContainerQueryInParens());
1324
+ node.addChild(this._parseContainerQueryInParens(true));
1254
1325
  if (this.peekIdent('and')) {
1255
1326
  while (this.acceptIdent('and')) {
1256
1327
  node.addChild(this._parseContainerQueryInParens());
@@ -1264,7 +1335,7 @@
1264
1335
  }
1265
1336
  return this.finish(node);
1266
1337
  }
1267
- _parseContainerQueryInParens() {
1338
+ _parseContainerQueryInParens(optional = false) {
1268
1339
  // <query-in-parens> = ( <container-query> )
1269
1340
  // | ( <size-feature> )
1270
1341
  // | style( <style-query> )
@@ -1291,6 +1362,9 @@
1291
1362
  }
1292
1363
  }
1293
1364
  else {
1365
+ if (optional) {
1366
+ return null;
1367
+ }
1294
1368
  return this.finish(node, cssErrors_1.ParseError.LeftParenthesisExpected, [], [cssScanner_1.TokenType.CurlyL]);
1295
1369
  }
1296
1370
  return this.finish(node);
@@ -1320,7 +1394,7 @@
1320
1394
  }
1321
1395
  }
1322
1396
  else {
1323
- node.addChild(this._parseDeclaration([cssScanner_1.TokenType.ParenthesisR]));
1397
+ node.addChild(this._parseDeclaration([cssScanner_1.TokenType.ParenthesisR], true));
1324
1398
  }
1325
1399
  return this.finish(node);
1326
1400
  }
@@ -1826,6 +1900,12 @@
1826
1900
  _parseFunction() {
1827
1901
  const pos = this.mark();
1828
1902
  const node = this.create(nodes.Function);
1903
+ let parseArgument = this._parseFunctionArgument.bind(this);
1904
+ let separator = cssScanner_1.TokenType.Comma;
1905
+ if (this.peekIdent("if")) {
1906
+ parseArgument = this._parseIfBranch.bind(this);
1907
+ separator = cssScanner_1.TokenType.SemiColon;
1908
+ }
1829
1909
  if (!node.setIdentifier(this._parseFunctionIdentifier())) {
1830
1910
  return null;
1831
1911
  }
@@ -1833,12 +1913,12 @@
1833
1913
  this.restoreAtMark(pos);
1834
1914
  return null;
1835
1915
  }
1836
- if (node.getArguments().addChild(this._parseFunctionArgument())) {
1837
- while (this.accept(cssScanner_1.TokenType.Comma)) {
1916
+ if (node.getArguments().addChild(parseArgument())) {
1917
+ while (this.accept(separator)) {
1838
1918
  if (this.peek(cssScanner_1.TokenType.ParenthesisR)) {
1839
1919
  break;
1840
1920
  }
1841
- if (!node.getArguments().addChild(this._parseFunctionArgument())) {
1921
+ if (!node.getArguments().addChild(parseArgument())) {
1842
1922
  this.markError(node, cssErrors_1.ParseError.ExpressionExpected);
1843
1923
  }
1844
1924
  }
@@ -1873,6 +1953,73 @@
1873
1953
  }
1874
1954
  return null;
1875
1955
  }
1956
+ _parseIfBranch() {
1957
+ // <if-branch> = <if-condition> : <declaration-value>?
1958
+ const node = this.create(nodes.Node);
1959
+ if (!node.addChild(this._parseIfCondition())) {
1960
+ return this.finish(node, cssErrors_1.ParseError.IfConditionExpected, [], [cssScanner_1.TokenType.SemiColon]);
1961
+ }
1962
+ if (!this.accept(cssScanner_1.TokenType.Colon)) {
1963
+ return this.finish(node, cssErrors_1.ParseError.ColonExpected, [], [cssScanner_1.TokenType.SemiColon]);
1964
+ }
1965
+ node.addChild(this._parseExpr());
1966
+ return this.finish(node);
1967
+ }
1968
+ _parseIfCondition() {
1969
+ // <if-condition> = <boolean-expr[ <if-test> ]> | else
1970
+ const node = this.create(nodes.Node);
1971
+ if (this.peekIdent("else")) {
1972
+ node.addChild(this._parseIdent());
1973
+ return this.finish(node);
1974
+ }
1975
+ return this._parseBooleanExpression(this._parseIfTest.bind(this));
1976
+ }
1977
+ _parseIfTest() {
1978
+ // <if-test> =
1979
+ // supports( [ <ident> : <declaration-value> ] | <supports-condition> ) |
1980
+ // media( <media-feature> | <media-condition> ) |
1981
+ // style( <style-query> )
1982
+ const node = this.create(nodes.Node);
1983
+ if (this.acceptIdent('supports')) {
1984
+ if (this.hasWhitespace() || !this.accept(cssScanner_1.TokenType.ParenthesisL)) {
1985
+ return this.finish(node, cssErrors_1.ParseError.LeftParenthesisExpected, [], [cssScanner_1.TokenType.Colon]);
1986
+ }
1987
+ node.addChild(this._tryToParseDeclaration() || this._parseSupportsCondition());
1988
+ if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
1989
+ return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected, [], [cssScanner_1.TokenType.Colon]);
1990
+ }
1991
+ return this.finish(node);
1992
+ }
1993
+ if (this.acceptIdent('media')) {
1994
+ if (this.hasWhitespace() || !this.accept(cssScanner_1.TokenType.ParenthesisL)) {
1995
+ return this.finish(node, cssErrors_1.ParseError.LeftParenthesisExpected, [], [cssScanner_1.TokenType.Colon]);
1996
+ }
1997
+ const pos = this.mark();
1998
+ const condition = this._parseMediaCondition();
1999
+ if (condition && !condition.isErroneous()) {
2000
+ node.addChild(condition);
2001
+ }
2002
+ else {
2003
+ this.restoreAtMark(pos);
2004
+ node.addChild(this._parseMediaFeature());
2005
+ }
2006
+ if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
2007
+ return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected, [], [cssScanner_1.TokenType.Colon]);
2008
+ }
2009
+ return this.finish(node);
2010
+ }
2011
+ if (this.acceptIdent('style')) {
2012
+ if (this.hasWhitespace() || !this.accept(cssScanner_1.TokenType.ParenthesisL)) {
2013
+ return this.finish(node, cssErrors_1.ParseError.LeftParenthesisExpected, [], [cssScanner_1.TokenType.Colon]);
2014
+ }
2015
+ node.addChild(this._parseStyleQuery());
2016
+ if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
2017
+ return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected, [], [cssScanner_1.TokenType.Colon]);
2018
+ }
2019
+ return this.finish(node);
2020
+ }
2021
+ return null;
2022
+ }
1876
2023
  _parseHexColor() {
1877
2024
  if (this.peekRegExp(cssScanner_1.TokenType.Hash, /^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{4}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$/g)) {
1878
2025
  const node = this.create(nodes.HexColorValue);
@@ -627,6 +627,64 @@
627
627
  _parseMixinReferenceBodyStatement() {
628
628
  return this._tryParseKeyframeSelector() || this._parseRuleSetDeclaration();
629
629
  }
630
+ _parseIfTest() {
631
+ const node = this.create(nodes.Node);
632
+ if (this.acceptIdent('sass')) {
633
+ if (this.hasWhitespace() || !this.accept(cssScanner_1.TokenType.ParenthesisL)) {
634
+ return this.finish(node, cssErrors_1.ParseError.LeftParenthesisExpected, [], [cssScanner_1.TokenType.CurlyL]);
635
+ }
636
+ node.addChild(this._parseExpr());
637
+ if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
638
+ return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected, [], [cssScanner_1.TokenType.CurlyL]);
639
+ }
640
+ return this.finish(node);
641
+ }
642
+ return super._parseIfTest();
643
+ }
644
+ _parseFunction() {
645
+ const pos = this.mark();
646
+ const node = this.create(nodes.Function);
647
+ let isIf = this.peekIdent('if');
648
+ if (!node.setIdentifier(this._parseFunctionIdentifier())) {
649
+ return null;
650
+ }
651
+ if (this.hasWhitespace() || !this.accept(cssScanner_1.TokenType.ParenthesisL)) {
652
+ this.restoreAtMark(pos);
653
+ return null;
654
+ }
655
+ let firstArgument;
656
+ let parseArgument = this._parseFunctionArgument.bind(this);
657
+ let separator = cssScanner_1.TokenType.Comma;
658
+ if (!isIf) {
659
+ firstArgument = this._parseFunctionArgument();
660
+ }
661
+ else {
662
+ const pos = this.mark();
663
+ firstArgument = this._parseIfBranch();
664
+ if (firstArgument && !firstArgument.isErroneous()) {
665
+ parseArgument = this._parseIfBranch.bind(this);
666
+ separator = cssScanner_1.TokenType.SemiColon;
667
+ }
668
+ else {
669
+ this.restoreAtMark(pos);
670
+ firstArgument = this._parseFunctionArgument();
671
+ }
672
+ }
673
+ if (node.getArguments().addChild(firstArgument)) {
674
+ while (this.accept(separator)) {
675
+ if (this.peek(cssScanner_1.TokenType.ParenthesisR)) {
676
+ break;
677
+ }
678
+ if (!node.getArguments().addChild(parseArgument())) {
679
+ this.markError(node, cssErrors_1.ParseError.ExpressionExpected);
680
+ }
681
+ }
682
+ }
683
+ if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
684
+ return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected);
685
+ }
686
+ return this.finish(node);
687
+ }
630
688
  _parseFunctionArgument() {
631
689
  // [variableName ':'] expression | variableName '...'
632
690
  const node = this.create(nodes.FunctionArgument);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vscode-css-languageservice",
3
- "version": "6.3.8",
3
+ "version": "6.3.10",
4
4
  "description": "Language service for CSS, LESS and SCSS",
5
5
  "main": "./lib/umd/cssLanguageService.js",
6
6
  "typings": "./lib/umd/cssLanguageService",
@@ -16,16 +16,16 @@
16
16
  },
17
17
  "devDependencies": {
18
18
  "@types/mocha": "^10.0.10",
19
- "@types/node": "18.x",
20
- "@typescript-eslint/eslint-plugin": "^8.44.1",
21
- "@typescript-eslint/parser": "^8.44.1",
22
- "@vscode/web-custom-data": "^0.6.0",
23
- "eslint": "^9.36.0",
19
+ "@types/node": "22.x",
20
+ "@typescript-eslint/eslint-plugin": "^8.56.0",
21
+ "@typescript-eslint/parser": "^8.56.0",
22
+ "@vscode/web-custom-data": "^0.6.3",
23
+ "eslint": "^9.39.3",
24
24
  "js-beautify": "^1.15.4",
25
- "mocha": "^11.7.2",
26
- "rimraf": "^6.0.1",
25
+ "mocha": "^11.7.5",
26
+ "rimraf": "^6.1.3",
27
27
  "source-map-support": "^0.5.21",
28
- "typescript": "^5.9.2"
28
+ "typescript": "^5.9.3"
29
29
  },
30
30
  "dependencies": {
31
31
  "@vscode/l10n": "^0.0.18",