@eslint/css-tree 3.5.4 → 3.6.0

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/dist/data.cjs CHANGED
@@ -526,8 +526,7 @@ module.exports = {
526
526
  "inset-area": "[[left|center|right|span-left|span-right|x-start|x-end|span-x-start|span-x-end|x-self-start|x-self-end|span-x-self-start|span-x-self-end|span-all]||[top|center|bottom|span-top|span-bottom|y-start|y-end|span-y-start|span-y-end|y-self-start|y-self-end|span-y-self-start|span-y-self-end|span-all]|[block-start|center|block-end|span-block-start|span-block-end|span-all]||[inline-start|center|inline-end|span-inline-start|span-inline-end|span-all]|[self-block-start|self-block-end|span-self-block-start|span-self-block-end|span-all]||[self-inline-start|self-inline-end|span-self-inline-start|span-self-inline-end|span-all]|[start|center|end|span-start|span-end|span-all]{1,2}|[self-start|center|self-end|span-self-start|span-self-end|span-all]{1,2}]",
527
527
  "font-variant-css2": "normal|small-caps",
528
528
  "font-width-css3": "normal|ultra-condensed|extra-condensed|condensed|semi-condensed|semi-expanded|expanded|extra-expanded|ultra-expanded",
529
- "system-family-name": "caption|icon|menu|message-box|small-caption|status-bar",
530
- "parentheses-block": "( <any-value>* )"
529
+ "system-family-name": "caption|icon|menu|message-box|small-caption|status-bar"
531
530
  },
532
531
  "properties": {
533
532
  "--*": "<declaration-value>",
@@ -1198,7 +1197,7 @@ module.exports = {
1198
1197
  "counter-style": {
1199
1198
  "prelude": "<counter-style-name>",
1200
1199
  "descriptors": {
1201
- "additive-symbols": "[<integer>&&<symbol>]#",
1200
+ "additive-symbols": "[<integer [0,∞]>&&<symbol>]#",
1202
1201
  "fallback": "<counter-style-name>",
1203
1202
  "negative": "<symbol> <symbol>?",
1204
1203
  "pad": "<integer>&&<symbol>",
@@ -1274,7 +1273,7 @@ module.exports = {
1274
1273
  "bleed": "auto|<length>",
1275
1274
  "marks": "none|[crop||cross]",
1276
1275
  "page-orientation": "upright|rotate-left|rotate-right",
1277
- "size": "<length>{1,2}|auto|[<page-size>||[portrait|landscape]]"
1276
+ "size": "<length [0,∞]>{1,2}|auto|[<page-size>||[portrait|landscape]]"
1278
1277
  }
1279
1278
  },
1280
1279
  "position-try": {
package/dist/data.js CHANGED
@@ -526,8 +526,7 @@ export default {
526
526
  "inset-area": "[[left|center|right|span-left|span-right|x-start|x-end|span-x-start|span-x-end|x-self-start|x-self-end|span-x-self-start|span-x-self-end|span-all]||[top|center|bottom|span-top|span-bottom|y-start|y-end|span-y-start|span-y-end|y-self-start|y-self-end|span-y-self-start|span-y-self-end|span-all]|[block-start|center|block-end|span-block-start|span-block-end|span-all]||[inline-start|center|inline-end|span-inline-start|span-inline-end|span-all]|[self-block-start|self-block-end|span-self-block-start|span-self-block-end|span-all]||[self-inline-start|self-inline-end|span-self-inline-start|span-self-inline-end|span-all]|[start|center|end|span-start|span-end|span-all]{1,2}|[self-start|center|self-end|span-self-start|span-self-end|span-all]{1,2}]",
527
527
  "font-variant-css2": "normal|small-caps",
528
528
  "font-width-css3": "normal|ultra-condensed|extra-condensed|condensed|semi-condensed|semi-expanded|expanded|extra-expanded|ultra-expanded",
529
- "system-family-name": "caption|icon|menu|message-box|small-caption|status-bar",
530
- "parentheses-block": "( <any-value>* )"
529
+ "system-family-name": "caption|icon|menu|message-box|small-caption|status-bar"
531
530
  },
532
531
  "properties": {
533
532
  "--*": "<declaration-value>",
@@ -1198,7 +1197,7 @@ export default {
1198
1197
  "counter-style": {
1199
1198
  "prelude": "<counter-style-name>",
1200
1199
  "descriptors": {
1201
- "additive-symbols": "[<integer>&&<symbol>]#",
1200
+ "additive-symbols": "[<integer [0,∞]>&&<symbol>]#",
1202
1201
  "fallback": "<counter-style-name>",
1203
1202
  "negative": "<symbol> <symbol>?",
1204
1203
  "pad": "<integer>&&<symbol>",
@@ -1274,7 +1273,7 @@ export default {
1274
1273
  "bleed": "auto|<length>",
1275
1274
  "marks": "none|[crop||cross]",
1276
1275
  "page-orientation": "upright|rotate-left|rotate-right",
1277
- "size": "<length>{1,2}|auto|[<page-size>||[portrait|landscape]]"
1276
+ "size": "<length [0,∞]>{1,2}|auto|[<page-size>||[portrait|landscape]]"
1278
1277
  }
1279
1278
  },
1280
1279
  "position-try": {
package/dist/version.cjs CHANGED
@@ -1 +1 @@
1
- module.exports = "3.5.4";
1
+ module.exports = "3.6.0";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = "3.5.4";
1
+ export const version = "3.6.0";
package/lib/index.d.ts CHANGED
@@ -1331,7 +1331,7 @@ export class TokenStream {
1331
1331
  * @param offset - The offset from the current token's starting index (optional). If provided, the function checks the token at the specified offset instead of the current token.
1332
1332
  * @returns True if the token is a delimiter with the specified character code, false otherwise.
1333
1333
  */
1334
- isDelim(code: number, offset: number): boolean;
1334
+ isDelim(code: number, offset?: number): boolean;
1335
1335
 
1336
1336
  /**
1337
1337
  * Skips a specified number of tokens forward in the stream.
@@ -34,7 +34,91 @@ import {
34
34
  RightCurlyBracket
35
35
  } from '../tokenizer/index.js';
36
36
 
37
- const calcFunctionNames = ['calc(', '-moz-calc(', '-webkit-calc('];
37
+ // CSS mathematical functions categorized by return type behavior
38
+ // See: https://www.w3.org/TR/css-values-4/#math
39
+
40
+ // Calculation functions that return different types depending on input
41
+ const calcFunctionNames = [
42
+ 'calc(',
43
+ '-moz-calc(',
44
+ '-webkit-calc('
45
+ ];
46
+
47
+ // Comparison functions that return different types depending on input
48
+ const comparisonFunctionNames = [
49
+ 'min(',
50
+ 'max(',
51
+ 'clamp('
52
+ ];
53
+
54
+ // Functions that return a stepped value, i.e. a value that is rounded to the nearest step
55
+ const steppedValueFunctionNames = [
56
+ 'round(',
57
+ 'mod(',
58
+ 'rem('
59
+ ];
60
+
61
+ // Trigonometrical functions that return a <number>
62
+ const trigNumberFunctionNames = [
63
+ 'sin(',
64
+ 'cos(',
65
+ 'tan('
66
+ ];
67
+
68
+ // Trigonometrical functions that return a <angle>
69
+ const trigAngleFunctionNames = [
70
+ 'asin(',
71
+ 'acos(',
72
+ 'atan(',
73
+ 'atan2('
74
+ ];
75
+
76
+ // Other functions that return a <number>
77
+ const otherNumberFunctionNames = [
78
+ 'pow(',
79
+ 'sqrt(',
80
+ 'log(',
81
+ 'exp(',
82
+ 'sign('
83
+ ];
84
+
85
+ // Exponential functions that return a <number> or <dimension> or <percentage>
86
+ const expNumberDimensionPercentageFunctionNames = [
87
+ 'hypot('
88
+ ];
89
+
90
+ // Return the same type as the input
91
+ const signFunctionNames = [
92
+ 'abs('
93
+ ];
94
+
95
+ const numberFunctionNames = [
96
+ ...calcFunctionNames,
97
+ ...comparisonFunctionNames,
98
+ ...steppedValueFunctionNames,
99
+ ...trigNumberFunctionNames,
100
+ ...otherNumberFunctionNames,
101
+ ...expNumberDimensionPercentageFunctionNames,
102
+ ...signFunctionNames
103
+ ];
104
+
105
+ const percentageFunctionNames = [
106
+ ...calcFunctionNames,
107
+ ...comparisonFunctionNames,
108
+ ...steppedValueFunctionNames,
109
+ ...expNumberDimensionPercentageFunctionNames,
110
+ ...signFunctionNames
111
+ ];
112
+
113
+ const dimensionFunctionNames = [
114
+ ...calcFunctionNames,
115
+ ...comparisonFunctionNames,
116
+ ...steppedValueFunctionNames,
117
+ ...trigAngleFunctionNames,
118
+ ...expNumberDimensionPercentageFunctionNames,
119
+ ...signFunctionNames
120
+ ];
121
+
38
122
  const balancePair = new Map([
39
123
  [FunctionToken, RightParenthesis],
40
124
  [LeftParenthesis, RightParenthesis],
@@ -141,16 +225,17 @@ function consumeFunction(token, getNextToken) {
141
225
  return length;
142
226
  }
143
227
 
228
+
144
229
  // TODO: implement
145
230
  // can be used wherever <length>, <frequency>, <angle>, <time>, <percentage>, <number>, or <integer> values are allowed
146
231
  // https://drafts.csswg.org/css-values/#calc-notation
147
- function calc(next) {
232
+ function math(next, functionNames) {
148
233
  return function(token, getNextToken, opts) {
149
234
  if (token === null) {
150
235
  return 0;
151
236
  }
152
237
 
153
- if (token.type === FunctionToken && eqStrAny(token.value, calcFunctionNames)) {
238
+ if (token.type === FunctionToken && eqStrAny(token.value, functionNames)) {
154
239
  return consumeFunction(token, getNextToken);
155
240
  }
156
241
 
@@ -557,12 +642,12 @@ export const productionTypes = {
557
642
  'ident': tokenType(Ident),
558
643
 
559
644
  // percentage
560
- 'percentage': calc(percentage),
645
+ 'percentage': math(percentage, percentageFunctionNames),
561
646
 
562
647
  // numeric
563
648
  'zero': zero(),
564
- 'number': calc(number),
565
- 'integer': calc(integer),
649
+ 'number': math(number, numberFunctionNames),
650
+ 'integer': math(integer, numberFunctionNames),
566
651
 
567
652
  // complex types
568
653
  'custom-ident': customIdent,
@@ -601,15 +686,15 @@ export function createDemensionTypes(units) {
601
686
  } = units || {};
602
687
 
603
688
  return {
604
- 'dimension': calc(dimension(null)),
605
- 'angle': calc(dimension(angle)),
606
- 'decibel': calc(dimension(decibel)),
607
- 'frequency': calc(dimension(frequency)),
608
- 'flex': calc(dimension(flex)),
609
- 'length': calc(zero(dimension(length))),
610
- 'resolution': calc(dimension(resolution)),
611
- 'semitones': calc(dimension(semitones)),
612
- 'time': calc(dimension(time))
689
+ 'dimension': math(dimension(null), dimensionFunctionNames),
690
+ 'angle': math(dimension(angle), dimensionFunctionNames),
691
+ 'decibel': math(dimension(decibel), dimensionFunctionNames),
692
+ 'frequency': math(dimension(frequency), dimensionFunctionNames),
693
+ 'flex': math(dimension(flex), dimensionFunctionNames),
694
+ 'length': math(zero(dimension(length)), dimensionFunctionNames),
695
+ 'resolution': math(dimension(resolution), dimensionFunctionNames),
696
+ 'semitones': math(dimension(semitones), dimensionFunctionNames),
697
+ 'time': math(dimension(time), dimensionFunctionNames)
613
698
  };
614
699
  }
615
700
 
@@ -5,6 +5,7 @@ import {
5
5
  Semicolon,
6
6
  Hash,
7
7
  Colon,
8
+ Ident,
8
9
  AtKeyword,
9
10
  LeftSquareBracket,
10
11
  LeftCurlyBracket,
@@ -44,10 +45,24 @@ function consumeDeclaration() {
44
45
  return node;
45
46
  }
46
47
 
48
+ function isElementSelectorStart() {
49
+ if (this.tokenType !== Ident) {
50
+ return false;
51
+ }
52
+
53
+ const nextTokenType = this.lookupTypeNonSC(1);
54
+
55
+ if (nextTokenType !== Colon && nextTokenType !== Semicolon && nextTokenType !== RightCurlyBracket) {
56
+ return true;
57
+ }
58
+
59
+ return false;
60
+ }
61
+
47
62
  function isSelectorStart() {
48
63
  return this.tokenType === Delim && selectorStarts.has(this.source.charCodeAt(this.tokenStart)) ||
49
64
  this.tokenType === Hash || this.tokenType === LeftSquareBracket ||
50
- this.tokenType === Colon;
65
+ this.tokenType === Colon || isElementSelectorStart.call(this);
51
66
  }
52
67
 
53
68
  export const name = 'Block';
@@ -60,8 +75,7 @@ export const structure = {
60
75
  ]]
61
76
  };
62
77
 
63
- export function parse(isStyleBlock) {
64
- const consumer = isStyleBlock ? consumeDeclaration : consumeRule;
78
+ export function parse(isStyleBlock, { allowNestedRules = false } = {}) {
65
79
  const start = this.tokenStart;
66
80
  let children = this.createList();
67
81
 
@@ -83,10 +97,16 @@ export function parse(isStyleBlock) {
83
97
  break;
84
98
 
85
99
  default:
86
- if (isStyleBlock && isSelectorStart.call(this)) {
87
- children.push(consumeRule.call(this));
100
+ if (isStyleBlock) {
101
+
102
+ if (allowNestedRules && isSelectorStart.call(this)) {
103
+ children.push(consumeRule.call(this));
104
+ } else {
105
+ children.push(consumeDeclaration.call(this));
106
+ }
107
+
88
108
  } else {
89
- children.push(consumer.call(this));
109
+ children.push(consumeRule.call(this));
90
110
  }
91
111
  }
92
112
  }
@@ -35,7 +35,7 @@ export function parse() {
35
35
  prelude = consumeRaw.call(this, startToken);
36
36
  }
37
37
 
38
- block = this.Block(true);
38
+ block = this.Block(true, { allowNestedRules: true });
39
39
 
40
40
  return {
41
41
  type: 'Rule',
@@ -48,4 +48,3 @@ export function generate(node) {
48
48
  this.node(node.prelude);
49
49
  this.node(node.block);
50
50
  }
51
-
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eslint/css-tree",
3
- "version": "3.5.4",
3
+ "version": "3.6.0",
4
4
  "description": "A tool set for CSS: fast detailed parser (CSS → AST), walker (AST traversal), generator (AST → CSS) and lexer (validation and matching) based on specs and browser implementations",
5
5
  "author": "Roman Dvornov <rdvornov@gmail.com> (https://github.com/lahmatiy)",
6
6
  "license": "MIT",
@@ -107,7 +107,7 @@
107
107
  "test:types": "tsc -p tests/types/tsconfig.json"
108
108
  },
109
109
  "dependencies": {
110
- "mdn-data": "2.20.0",
110
+ "mdn-data": "2.21.0",
111
111
  "source-map-js": "^1.0.1"
112
112
  },
113
113
  "devDependencies": {