@eslint/css-tree 3.2.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.
Files changed (279) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +194 -0
  3. package/cjs/convertor/create.cjs +32 -0
  4. package/cjs/convertor/index.cjs +8 -0
  5. package/cjs/data-patch.cjs +7 -0
  6. package/cjs/data.cjs +120 -0
  7. package/cjs/definition-syntax/SyntaxError.cjs +16 -0
  8. package/cjs/definition-syntax/generate.cjs +139 -0
  9. package/cjs/definition-syntax/index.cjs +13 -0
  10. package/cjs/definition-syntax/parse.cjs +556 -0
  11. package/cjs/definition-syntax/scanner.cjs +113 -0
  12. package/cjs/definition-syntax/walk.cjs +57 -0
  13. package/cjs/generator/create.cjs +102 -0
  14. package/cjs/generator/index.cjs +8 -0
  15. package/cjs/generator/sourceMap.cjs +96 -0
  16. package/cjs/generator/token-before.cjs +170 -0
  17. package/cjs/index.cjs +65 -0
  18. package/cjs/lexer/Lexer.cjs +517 -0
  19. package/cjs/lexer/error.cjs +128 -0
  20. package/cjs/lexer/generic-an-plus-b.cjs +235 -0
  21. package/cjs/lexer/generic-const.cjs +12 -0
  22. package/cjs/lexer/generic-urange.cjs +149 -0
  23. package/cjs/lexer/generic.cjs +589 -0
  24. package/cjs/lexer/index.cjs +7 -0
  25. package/cjs/lexer/match-graph.cjs +530 -0
  26. package/cjs/lexer/match.cjs +632 -0
  27. package/cjs/lexer/prepare-tokens.cjs +54 -0
  28. package/cjs/lexer/search.cjs +65 -0
  29. package/cjs/lexer/structure.cjs +173 -0
  30. package/cjs/lexer/trace.cjs +73 -0
  31. package/cjs/lexer/units.cjs +38 -0
  32. package/cjs/parser/SyntaxError.cjs +74 -0
  33. package/cjs/parser/create.cjs +378 -0
  34. package/cjs/parser/index.cjs +8 -0
  35. package/cjs/parser/parse-selector.cjs +8 -0
  36. package/cjs/parser/sequence.cjs +47 -0
  37. package/cjs/syntax/atrule/container.cjs +32 -0
  38. package/cjs/syntax/atrule/font-face.cjs +12 -0
  39. package/cjs/syntax/atrule/import.cjs +101 -0
  40. package/cjs/syntax/atrule/index.cjs +27 -0
  41. package/cjs/syntax/atrule/layer.cjs +16 -0
  42. package/cjs/syntax/atrule/media.cjs +16 -0
  43. package/cjs/syntax/atrule/nest.cjs +16 -0
  44. package/cjs/syntax/atrule/page.cjs +16 -0
  45. package/cjs/syntax/atrule/scope.cjs +16 -0
  46. package/cjs/syntax/atrule/starting-style.cjs +12 -0
  47. package/cjs/syntax/atrule/supports.cjs +16 -0
  48. package/cjs/syntax/config/generator.cjs +9 -0
  49. package/cjs/syntax/config/lexer.cjs +14 -0
  50. package/cjs/syntax/config/mix.cjs +126 -0
  51. package/cjs/syntax/config/parser-selector.cjs +19 -0
  52. package/cjs/syntax/config/parser.cjs +49 -0
  53. package/cjs/syntax/config/walker.cjs +9 -0
  54. package/cjs/syntax/create.cjs +58 -0
  55. package/cjs/syntax/function/expression.cjs +11 -0
  56. package/cjs/syntax/function/var.cjs +43 -0
  57. package/cjs/syntax/index.cjs +14 -0
  58. package/cjs/syntax/node/AnPlusB.cjs +293 -0
  59. package/cjs/syntax/node/Atrule.cjs +103 -0
  60. package/cjs/syntax/node/AtrulePrelude.cjs +52 -0
  61. package/cjs/syntax/node/AttributeSelector.cjs +148 -0
  62. package/cjs/syntax/node/Block.cjs +96 -0
  63. package/cjs/syntax/node/Brackets.cjs +38 -0
  64. package/cjs/syntax/node/CDC.cjs +26 -0
  65. package/cjs/syntax/node/CDO.cjs +26 -0
  66. package/cjs/syntax/node/ClassSelector.cjs +31 -0
  67. package/cjs/syntax/node/Combinator.cjs +61 -0
  68. package/cjs/syntax/node/Comment.cjs +40 -0
  69. package/cjs/syntax/node/Condition.cjs +120 -0
  70. package/cjs/syntax/node/Declaration.cjs +166 -0
  71. package/cjs/syntax/node/DeclarationList.cjs +62 -0
  72. package/cjs/syntax/node/Dimension.cjs +30 -0
  73. package/cjs/syntax/node/Feature.cjs +101 -0
  74. package/cjs/syntax/node/FeatureFunction.cjs +67 -0
  75. package/cjs/syntax/node/FeatureRange.cjs +133 -0
  76. package/cjs/syntax/node/Function.cjs +45 -0
  77. package/cjs/syntax/node/GeneralEnclosed.cjs +68 -0
  78. package/cjs/syntax/node/Hash.cjs +30 -0
  79. package/cjs/syntax/node/IdSelector.cjs +33 -0
  80. package/cjs/syntax/node/Identifier.cjs +25 -0
  81. package/cjs/syntax/node/Layer.cjs +35 -0
  82. package/cjs/syntax/node/LayerList.cjs +43 -0
  83. package/cjs/syntax/node/MediaQuery.cjs +100 -0
  84. package/cjs/syntax/node/MediaQueryList.cjs +41 -0
  85. package/cjs/syntax/node/NestingSelector.cjs +29 -0
  86. package/cjs/syntax/node/Nth.cjs +54 -0
  87. package/cjs/syntax/node/Number.cjs +25 -0
  88. package/cjs/syntax/node/Operator.cjs +28 -0
  89. package/cjs/syntax/node/Parentheses.cjs +38 -0
  90. package/cjs/syntax/node/Percentage.cjs +25 -0
  91. package/cjs/syntax/node/PseudoClassSelector.cjs +67 -0
  92. package/cjs/syntax/node/PseudoElementSelector.cjs +69 -0
  93. package/cjs/syntax/node/Ratio.cjs +71 -0
  94. package/cjs/syntax/node/Raw.cjs +48 -0
  95. package/cjs/syntax/node/Rule.cjs +58 -0
  96. package/cjs/syntax/node/Scope.cjs +69 -0
  97. package/cjs/syntax/node/Selector.cjs +38 -0
  98. package/cjs/syntax/node/SelectorList.cjs +43 -0
  99. package/cjs/syntax/node/String.cjs +26 -0
  100. package/cjs/syntax/node/StyleSheet.cjs +83 -0
  101. package/cjs/syntax/node/SupportsDeclaration.cjs +38 -0
  102. package/cjs/syntax/node/TypeSelector.cjs +59 -0
  103. package/cjs/syntax/node/UnicodeRange.cjs +158 -0
  104. package/cjs/syntax/node/Url.cjs +54 -0
  105. package/cjs/syntax/node/Value.cjs +26 -0
  106. package/cjs/syntax/node/WhiteSpace.cjs +34 -0
  107. package/cjs/syntax/node/index-generate.cjs +103 -0
  108. package/cjs/syntax/node/index-parse-selector.cjs +39 -0
  109. package/cjs/syntax/node/index-parse.cjs +103 -0
  110. package/cjs/syntax/node/index.cjs +103 -0
  111. package/cjs/syntax/pseudo/index.cjs +60 -0
  112. package/cjs/syntax/pseudo/lang.cjs +37 -0
  113. package/cjs/syntax/scope/atrulePrelude.cjs +9 -0
  114. package/cjs/syntax/scope/default.cjs +76 -0
  115. package/cjs/syntax/scope/index.cjs +11 -0
  116. package/cjs/syntax/scope/selector.cjs +88 -0
  117. package/cjs/syntax/scope/value.cjs +29 -0
  118. package/cjs/tokenizer/OffsetToLocation.cjs +91 -0
  119. package/cjs/tokenizer/TokenStream.cjs +358 -0
  120. package/cjs/tokenizer/adopt-buffer.cjs +13 -0
  121. package/cjs/tokenizer/char-code-definitions.cjs +236 -0
  122. package/cjs/tokenizer/index.cjs +554 -0
  123. package/cjs/tokenizer/names.cjs +32 -0
  124. package/cjs/tokenizer/types.cjs +57 -0
  125. package/cjs/tokenizer/utils.cjs +261 -0
  126. package/cjs/utils/List.cjs +473 -0
  127. package/cjs/utils/clone.cjs +25 -0
  128. package/cjs/utils/create-custom-error.cjs +18 -0
  129. package/cjs/utils/ident.cjs +102 -0
  130. package/cjs/utils/index.cjs +20 -0
  131. package/cjs/utils/names.cjs +113 -0
  132. package/cjs/utils/string.cjs +99 -0
  133. package/cjs/utils/url.cjs +108 -0
  134. package/cjs/version.cjs +5 -0
  135. package/cjs/walker/create.cjs +291 -0
  136. package/cjs/walker/index.cjs +8 -0
  137. package/data/patch.json +874 -0
  138. package/dist/csstree.esm.js +12 -0
  139. package/dist/csstree.js +12 -0
  140. package/dist/data.cjs +1341 -0
  141. package/dist/data.js +1341 -0
  142. package/dist/version.cjs +1 -0
  143. package/dist/version.js +1 -0
  144. package/lib/convertor/create.js +28 -0
  145. package/lib/convertor/index.js +4 -0
  146. package/lib/data-patch.js +6 -0
  147. package/lib/data.js +118 -0
  148. package/lib/definition-syntax/SyntaxError.js +12 -0
  149. package/lib/definition-syntax/generate.js +135 -0
  150. package/lib/definition-syntax/index.js +4 -0
  151. package/lib/definition-syntax/parse.js +552 -0
  152. package/lib/definition-syntax/scanner.js +109 -0
  153. package/lib/definition-syntax/walk.js +53 -0
  154. package/lib/generator/create.js +97 -0
  155. package/lib/generator/index.js +4 -0
  156. package/lib/generator/sourceMap.js +92 -0
  157. package/lib/generator/token-before.js +182 -0
  158. package/lib/index.d.ts +3016 -0
  159. package/lib/index.js +30 -0
  160. package/lib/lexer/Lexer.js +511 -0
  161. package/lib/lexer/error.js +123 -0
  162. package/lib/lexer/generic-an-plus-b.js +238 -0
  163. package/lib/lexer/generic-const.js +8 -0
  164. package/lib/lexer/generic-urange.js +151 -0
  165. package/lib/lexer/generic.js +622 -0
  166. package/lib/lexer/index.js +1 -0
  167. package/lib/lexer/match-graph.js +527 -0
  168. package/lib/lexer/match.js +630 -0
  169. package/lib/lexer/prepare-tokens.js +50 -0
  170. package/lib/lexer/search.js +61 -0
  171. package/lib/lexer/structure.js +169 -0
  172. package/lib/lexer/trace.js +66 -0
  173. package/lib/lexer/units.js +27 -0
  174. package/lib/parser/SyntaxError.js +70 -0
  175. package/lib/parser/create.js +388 -0
  176. package/lib/parser/index.js +4 -0
  177. package/lib/parser/parse-selector.js +4 -0
  178. package/lib/parser/sequence.js +43 -0
  179. package/lib/syntax/atrule/container.js +28 -0
  180. package/lib/syntax/atrule/font-face.js +8 -0
  181. package/lib/syntax/atrule/import.js +104 -0
  182. package/lib/syntax/atrule/index.js +23 -0
  183. package/lib/syntax/atrule/layer.js +12 -0
  184. package/lib/syntax/atrule/media.js +12 -0
  185. package/lib/syntax/atrule/nest.js +12 -0
  186. package/lib/syntax/atrule/page.js +12 -0
  187. package/lib/syntax/atrule/scope.js +12 -0
  188. package/lib/syntax/atrule/starting-style.js +8 -0
  189. package/lib/syntax/atrule/supports.js +12 -0
  190. package/lib/syntax/config/generator.js +5 -0
  191. package/lib/syntax/config/lexer.js +10 -0
  192. package/lib/syntax/config/mix.js +122 -0
  193. package/lib/syntax/config/parser-selector.js +15 -0
  194. package/lib/syntax/config/parser.js +45 -0
  195. package/lib/syntax/config/walker.js +5 -0
  196. package/lib/syntax/create.js +55 -0
  197. package/lib/syntax/function/expression.js +7 -0
  198. package/lib/syntax/function/var.js +39 -0
  199. package/lib/syntax/index.js +10 -0
  200. package/lib/syntax/node/AnPlusB.js +292 -0
  201. package/lib/syntax/node/Atrule.js +100 -0
  202. package/lib/syntax/node/AtrulePrelude.js +47 -0
  203. package/lib/syntax/node/AttributeSelector.js +147 -0
  204. package/lib/syntax/node/Block.js +95 -0
  205. package/lib/syntax/node/Brackets.js +35 -0
  206. package/lib/syntax/node/CDC.js +19 -0
  207. package/lib/syntax/node/CDO.js +19 -0
  208. package/lib/syntax/node/ClassSelector.js +24 -0
  209. package/lib/syntax/node/Combinator.js +54 -0
  210. package/lib/syntax/node/Comment.js +33 -0
  211. package/lib/syntax/node/Condition.js +123 -0
  212. package/lib/syntax/node/Declaration.js +165 -0
  213. package/lib/syntax/node/DeclarationList.js +62 -0
  214. package/lib/syntax/node/Dimension.js +23 -0
  215. package/lib/syntax/node/Feature.js +103 -0
  216. package/lib/syntax/node/FeatureFunction.js +63 -0
  217. package/lib/syntax/node/FeatureRange.js +133 -0
  218. package/lib/syntax/node/Function.js +41 -0
  219. package/lib/syntax/node/GeneralEnclosed.js +66 -0
  220. package/lib/syntax/node/Hash.js +23 -0
  221. package/lib/syntax/node/IdSelector.js +26 -0
  222. package/lib/syntax/node/Identifier.js +18 -0
  223. package/lib/syntax/node/Layer.js +28 -0
  224. package/lib/syntax/node/LayerList.js +36 -0
  225. package/lib/syntax/node/MediaQuery.js +102 -0
  226. package/lib/syntax/node/MediaQueryList.js +34 -0
  227. package/lib/syntax/node/NestingSelector.js +22 -0
  228. package/lib/syntax/node/Nth.js +47 -0
  229. package/lib/syntax/node/Number.js +18 -0
  230. package/lib/syntax/node/Operator.js +21 -0
  231. package/lib/syntax/node/Parentheses.js +34 -0
  232. package/lib/syntax/node/Percentage.js +18 -0
  233. package/lib/syntax/node/PseudoClassSelector.js +65 -0
  234. package/lib/syntax/node/PseudoElementSelector.js +66 -0
  235. package/lib/syntax/node/Ratio.js +68 -0
  236. package/lib/syntax/node/Raw.js +41 -0
  237. package/lib/syntax/node/Rule.js +51 -0
  238. package/lib/syntax/node/Scope.js +66 -0
  239. package/lib/syntax/node/Selector.js +31 -0
  240. package/lib/syntax/node/SelectorList.js +35 -0
  241. package/lib/syntax/node/String.js +19 -0
  242. package/lib/syntax/node/StyleSheet.js +82 -0
  243. package/lib/syntax/node/SupportsDeclaration.js +34 -0
  244. package/lib/syntax/node/TypeSelector.js +52 -0
  245. package/lib/syntax/node/UnicodeRange.js +156 -0
  246. package/lib/syntax/node/Url.js +52 -0
  247. package/lib/syntax/node/Value.js +19 -0
  248. package/lib/syntax/node/WhiteSpace.js +27 -0
  249. package/lib/syntax/node/index-generate.js +49 -0
  250. package/lib/syntax/node/index-parse-selector.js +17 -0
  251. package/lib/syntax/node/index-parse.js +49 -0
  252. package/lib/syntax/node/index.js +49 -0
  253. package/lib/syntax/pseudo/index.js +56 -0
  254. package/lib/syntax/pseudo/lang.js +33 -0
  255. package/lib/syntax/scope/atrulePrelude.js +5 -0
  256. package/lib/syntax/scope/default.js +85 -0
  257. package/lib/syntax/scope/index.js +3 -0
  258. package/lib/syntax/scope/selector.js +94 -0
  259. package/lib/syntax/scope/value.js +25 -0
  260. package/lib/tokenizer/OffsetToLocation.js +87 -0
  261. package/lib/tokenizer/TokenStream.js +366 -0
  262. package/lib/tokenizer/adopt-buffer.js +9 -0
  263. package/lib/tokenizer/char-code-definitions.js +212 -0
  264. package/lib/tokenizer/index.js +513 -0
  265. package/lib/tokenizer/names.js +28 -0
  266. package/lib/tokenizer/types.js +28 -0
  267. package/lib/tokenizer/utils.js +254 -0
  268. package/lib/utils/List.js +469 -0
  269. package/lib/utils/clone.js +21 -0
  270. package/lib/utils/create-custom-error.js +14 -0
  271. package/lib/utils/ident.js +101 -0
  272. package/lib/utils/index.js +6 -0
  273. package/lib/utils/names.js +106 -0
  274. package/lib/utils/string.js +99 -0
  275. package/lib/utils/url.js +108 -0
  276. package/lib/version.js +5 -0
  277. package/lib/walker/create.js +287 -0
  278. package/lib/walker/index.js +4 -0
  279. package/package.json +133 -0
@@ -0,0 +1,556 @@
1
+ 'use strict';
2
+
3
+ const scanner = require('./scanner.cjs');
4
+
5
+ const TAB = 9;
6
+ const N = 10;
7
+ const F = 12;
8
+ const R = 13;
9
+ const SPACE = 32;
10
+ const EXCLAMATIONMARK = 33; // !
11
+ const NUMBERSIGN = 35; // #
12
+ const AMPERSAND = 38; // &
13
+ const APOSTROPHE = 39; // '
14
+ const LEFTPARENTHESIS = 40; // (
15
+ const RIGHTPARENTHESIS = 41; // )
16
+ const ASTERISK = 42; // *
17
+ const PLUSSIGN = 43; // +
18
+ const COMMA = 44; // ,
19
+ const HYPERMINUS = 45; // -
20
+ const LESSTHANSIGN = 60; // <
21
+ const GREATERTHANSIGN = 62; // >
22
+ const QUESTIONMARK = 63; // ?
23
+ const COMMERCIALAT = 64; // @
24
+ const LEFTSQUAREBRACKET = 91; // [
25
+ const RIGHTSQUAREBRACKET = 93; // ]
26
+ const LEFTCURLYBRACKET = 123; // {
27
+ const VERTICALLINE = 124; // |
28
+ const RIGHTCURLYBRACKET = 125; // }
29
+ const INFINITY = 8734; // ∞
30
+ const COMBINATOR_PRECEDENCE = {
31
+ ' ': 1,
32
+ '&&': 2,
33
+ '||': 3,
34
+ '|': 4
35
+ };
36
+
37
+ function readMultiplierRange(scanner) {
38
+ let min = null;
39
+ let max = null;
40
+
41
+ scanner.eat(LEFTCURLYBRACKET);
42
+ scanner.skipWs();
43
+
44
+ min = scanner.scanNumber(scanner);
45
+ scanner.skipWs();
46
+
47
+ if (scanner.charCode() === COMMA) {
48
+ scanner.pos++;
49
+ scanner.skipWs();
50
+
51
+ if (scanner.charCode() !== RIGHTCURLYBRACKET) {
52
+ max = scanner.scanNumber(scanner);
53
+ scanner.skipWs();
54
+ }
55
+ } else {
56
+ max = min;
57
+ }
58
+
59
+ scanner.eat(RIGHTCURLYBRACKET);
60
+
61
+ return {
62
+ min: Number(min),
63
+ max: max ? Number(max) : 0
64
+ };
65
+ }
66
+
67
+ function readMultiplier(scanner) {
68
+ let range = null;
69
+ let comma = false;
70
+
71
+ switch (scanner.charCode()) {
72
+ case ASTERISK:
73
+ scanner.pos++;
74
+
75
+ range = {
76
+ min: 0,
77
+ max: 0
78
+ };
79
+
80
+ break;
81
+
82
+ case PLUSSIGN:
83
+ scanner.pos++;
84
+
85
+ range = {
86
+ min: 1,
87
+ max: 0
88
+ };
89
+
90
+ break;
91
+
92
+ case QUESTIONMARK:
93
+ scanner.pos++;
94
+
95
+ range = {
96
+ min: 0,
97
+ max: 1
98
+ };
99
+
100
+ break;
101
+
102
+ case NUMBERSIGN:
103
+ scanner.pos++;
104
+
105
+ comma = true;
106
+
107
+ if (scanner.charCode() === LEFTCURLYBRACKET) {
108
+ range = readMultiplierRange(scanner);
109
+ } else if (scanner.charCode() === QUESTIONMARK) {
110
+ // https://www.w3.org/TR/css-values-4/#component-multipliers
111
+ // > the # and ? multipliers may be stacked as #?
112
+ // In this case just treat "#?" as a single multiplier
113
+ // { min: 0, max: 0, comma: true }
114
+ scanner.pos++;
115
+ range = {
116
+ min: 0,
117
+ max: 0
118
+ };
119
+ } else {
120
+ range = {
121
+ min: 1,
122
+ max: 0
123
+ };
124
+ }
125
+
126
+ break;
127
+
128
+ case LEFTCURLYBRACKET:
129
+ range = readMultiplierRange(scanner);
130
+ break;
131
+
132
+ default:
133
+ return null;
134
+ }
135
+
136
+ return {
137
+ type: 'Multiplier',
138
+ comma,
139
+ min: range.min,
140
+ max: range.max,
141
+ term: null
142
+ };
143
+ }
144
+
145
+ function maybeMultiplied(scanner, node) {
146
+ const multiplier = readMultiplier(scanner);
147
+
148
+ if (multiplier !== null) {
149
+ multiplier.term = node;
150
+
151
+ // https://www.w3.org/TR/css-values-4/#component-multipliers
152
+ // > The + and # multipliers may be stacked as +#;
153
+ // Represent "+#" as nested multipliers:
154
+ // { ...<multiplier #>,
155
+ // term: {
156
+ // ...<multipler +>,
157
+ // term: node
158
+ // }
159
+ // }
160
+ if (scanner.charCode() === NUMBERSIGN &&
161
+ scanner.charCodeAt(scanner.pos - 1) === PLUSSIGN) {
162
+ return maybeMultiplied(scanner, multiplier);
163
+ }
164
+
165
+ return multiplier;
166
+ }
167
+
168
+ return node;
169
+ }
170
+
171
+ function maybeToken(scanner) {
172
+ const ch = scanner.peek();
173
+
174
+ if (ch === '') {
175
+ return null;
176
+ }
177
+
178
+ return maybeMultiplied(scanner, {
179
+ type: 'Token',
180
+ value: ch
181
+ });
182
+ }
183
+
184
+ function readProperty(scanner) {
185
+ let name;
186
+
187
+ scanner.eat(LESSTHANSIGN);
188
+ scanner.eat(APOSTROPHE);
189
+
190
+ name = scanner.scanWord();
191
+
192
+ scanner.eat(APOSTROPHE);
193
+ scanner.eat(GREATERTHANSIGN);
194
+
195
+ return maybeMultiplied(scanner, {
196
+ type: 'Property',
197
+ name
198
+ });
199
+ }
200
+
201
+ // https://drafts.csswg.org/css-values-3/#numeric-ranges
202
+ // 4.1. Range Restrictions and Range Definition Notation
203
+ //
204
+ // Range restrictions can be annotated in the numeric type notation using CSS bracketed
205
+ // range notation—[min,max]—within the angle brackets, after the identifying keyword,
206
+ // indicating a closed range between (and including) min and max.
207
+ // For example, <integer [0, 10]> indicates an integer between 0 and 10, inclusive.
208
+ function readTypeRange(scanner) {
209
+ // use null for Infinity to make AST format JSON serializable/deserializable
210
+ let min = null; // -Infinity
211
+ let max = null; // Infinity
212
+ let sign = 1;
213
+
214
+ scanner.eat(LEFTSQUAREBRACKET);
215
+
216
+ if (scanner.charCode() === HYPERMINUS) {
217
+ scanner.peek();
218
+ sign = -1;
219
+ }
220
+
221
+ if (sign == -1 && scanner.charCode() === INFINITY) {
222
+ scanner.peek();
223
+ } else {
224
+ min = sign * Number(scanner.scanNumber(scanner));
225
+
226
+ if (scanner.isNameCharCode()) {
227
+ min += scanner.scanWord();
228
+ }
229
+ }
230
+
231
+ scanner.skipWs();
232
+ scanner.eat(COMMA);
233
+ scanner.skipWs();
234
+
235
+ if (scanner.charCode() === INFINITY) {
236
+ scanner.peek();
237
+ } else {
238
+ sign = 1;
239
+
240
+ if (scanner.charCode() === HYPERMINUS) {
241
+ scanner.peek();
242
+ sign = -1;
243
+ }
244
+
245
+ max = sign * Number(scanner.scanNumber(scanner));
246
+
247
+ if (scanner.isNameCharCode()) {
248
+ max += scanner.scanWord();
249
+ }
250
+ }
251
+
252
+ scanner.eat(RIGHTSQUAREBRACKET);
253
+
254
+ return {
255
+ type: 'Range',
256
+ min,
257
+ max
258
+ };
259
+ }
260
+
261
+ function readType(scanner) {
262
+ let name;
263
+ let opts = null;
264
+
265
+ scanner.eat(LESSTHANSIGN);
266
+ name = scanner.scanWord();
267
+
268
+ // https://drafts.csswg.org/css-values-5/#boolean
269
+ if (name === 'boolean-expr') {
270
+ scanner.eat(LEFTSQUAREBRACKET);
271
+
272
+ const implicitGroup = readImplicitGroup(scanner, RIGHTSQUAREBRACKET);
273
+
274
+ scanner.eat(RIGHTSQUAREBRACKET);
275
+ scanner.eat(GREATERTHANSIGN);
276
+
277
+ return maybeMultiplied(scanner, {
278
+ type: 'Boolean',
279
+ term: implicitGroup.terms.length === 1
280
+ ? implicitGroup.terms[0]
281
+ : implicitGroup
282
+ });
283
+ }
284
+
285
+ if (scanner.charCode() === LEFTPARENTHESIS &&
286
+ scanner.nextCharCode() === RIGHTPARENTHESIS) {
287
+ scanner.pos += 2;
288
+ name += '()';
289
+ }
290
+
291
+ if (scanner.charCodeAt(scanner.findWsEnd(scanner.pos)) === LEFTSQUAREBRACKET) {
292
+ scanner.skipWs();
293
+ opts = readTypeRange(scanner);
294
+ }
295
+
296
+ scanner.eat(GREATERTHANSIGN);
297
+
298
+ return maybeMultiplied(scanner, {
299
+ type: 'Type',
300
+ name,
301
+ opts
302
+ });
303
+ }
304
+
305
+ function readKeywordOrFunction(scanner) {
306
+ const name = scanner.scanWord();
307
+
308
+ if (scanner.charCode() === LEFTPARENTHESIS) {
309
+ scanner.pos++;
310
+
311
+ return {
312
+ type: 'Function',
313
+ name
314
+ };
315
+ }
316
+
317
+ return maybeMultiplied(scanner, {
318
+ type: 'Keyword',
319
+ name
320
+ });
321
+ }
322
+
323
+ function regroupTerms(terms, combinators) {
324
+ function createGroup(terms, combinator) {
325
+ return {
326
+ type: 'Group',
327
+ terms,
328
+ combinator,
329
+ disallowEmpty: false,
330
+ explicit: false
331
+ };
332
+ }
333
+
334
+ let combinator;
335
+
336
+ combinators = Object.keys(combinators)
337
+ .sort((a, b) => COMBINATOR_PRECEDENCE[a] - COMBINATOR_PRECEDENCE[b]);
338
+
339
+ while (combinators.length > 0) {
340
+ combinator = combinators.shift();
341
+
342
+ let i = 0;
343
+ let subgroupStart = 0;
344
+
345
+ for (; i < terms.length; i++) {
346
+ const term = terms[i];
347
+
348
+ if (term.type === 'Combinator') {
349
+ if (term.value === combinator) {
350
+ if (subgroupStart === -1) {
351
+ subgroupStart = i - 1;
352
+ }
353
+ terms.splice(i, 1);
354
+ i--;
355
+ } else {
356
+ if (subgroupStart !== -1 && i - subgroupStart > 1) {
357
+ terms.splice(
358
+ subgroupStart,
359
+ i - subgroupStart,
360
+ createGroup(terms.slice(subgroupStart, i), combinator)
361
+ );
362
+ i = subgroupStart + 1;
363
+ }
364
+ subgroupStart = -1;
365
+ }
366
+ }
367
+ }
368
+
369
+ if (subgroupStart !== -1 && combinators.length) {
370
+ terms.splice(
371
+ subgroupStart,
372
+ i - subgroupStart,
373
+ createGroup(terms.slice(subgroupStart, i), combinator)
374
+ );
375
+ }
376
+ }
377
+
378
+ return combinator;
379
+ }
380
+
381
+ function readImplicitGroup(scanner, stopCharCode) {
382
+ const combinators = Object.create(null);
383
+ const terms = [];
384
+ let token;
385
+ let prevToken = null;
386
+ let prevTokenPos = scanner.pos;
387
+
388
+ while (scanner.charCode() !== stopCharCode && (token = peek(scanner, stopCharCode))) {
389
+ if (token.type !== 'Spaces') {
390
+ if (token.type === 'Combinator') {
391
+ // check for combinator in group beginning and double combinator sequence
392
+ if (prevToken === null || prevToken.type === 'Combinator') {
393
+ scanner.pos = prevTokenPos;
394
+ scanner.error('Unexpected combinator');
395
+ }
396
+
397
+ combinators[token.value] = true;
398
+ } else if (prevToken !== null && prevToken.type !== 'Combinator') {
399
+ combinators[' '] = true; // a b
400
+ terms.push({
401
+ type: 'Combinator',
402
+ value: ' '
403
+ });
404
+ }
405
+
406
+ terms.push(token);
407
+ prevToken = token;
408
+ prevTokenPos = scanner.pos;
409
+ }
410
+ }
411
+
412
+ // check for combinator in group ending
413
+ if (prevToken !== null && prevToken.type === 'Combinator') {
414
+ scanner.pos -= prevTokenPos;
415
+ scanner.error('Unexpected combinator');
416
+ }
417
+
418
+ return {
419
+ type: 'Group',
420
+ terms,
421
+ combinator: regroupTerms(terms, combinators) || ' ',
422
+ disallowEmpty: false,
423
+ explicit: false
424
+ };
425
+ }
426
+
427
+ function readGroup(scanner, stopCharCode) {
428
+ let result;
429
+
430
+ scanner.eat(LEFTSQUAREBRACKET);
431
+ result = readImplicitGroup(scanner, stopCharCode);
432
+ scanner.eat(RIGHTSQUAREBRACKET);
433
+
434
+ result.explicit = true;
435
+
436
+ if (scanner.charCode() === EXCLAMATIONMARK) {
437
+ scanner.pos++;
438
+ result.disallowEmpty = true;
439
+ }
440
+
441
+ return result;
442
+ }
443
+
444
+ function peek(scanner, stopCharCode) {
445
+ let code = scanner.charCode();
446
+
447
+ switch (code) {
448
+ case RIGHTSQUAREBRACKET:
449
+ // don't eat, stop scan a group
450
+ break;
451
+
452
+ case LEFTSQUAREBRACKET:
453
+ return maybeMultiplied(scanner, readGroup(scanner, stopCharCode));
454
+
455
+ case LESSTHANSIGN:
456
+ return scanner.nextCharCode() === APOSTROPHE
457
+ ? readProperty(scanner)
458
+ : readType(scanner);
459
+
460
+ case VERTICALLINE:
461
+ return {
462
+ type: 'Combinator',
463
+ value: scanner.substringToPos(
464
+ scanner.pos + (scanner.nextCharCode() === VERTICALLINE ? 2 : 1)
465
+ )
466
+ };
467
+
468
+ case AMPERSAND:
469
+ scanner.pos++;
470
+ scanner.eat(AMPERSAND);
471
+
472
+ return {
473
+ type: 'Combinator',
474
+ value: '&&'
475
+ };
476
+
477
+ case COMMA:
478
+ scanner.pos++;
479
+ return {
480
+ type: 'Comma'
481
+ };
482
+
483
+ case APOSTROPHE:
484
+ return maybeMultiplied(scanner, {
485
+ type: 'String',
486
+ value: scanner.scanString()
487
+ });
488
+
489
+ case SPACE:
490
+ case TAB:
491
+ case N:
492
+ case R:
493
+ case F:
494
+ return {
495
+ type: 'Spaces',
496
+ value: scanner.scanSpaces()
497
+ };
498
+
499
+ case COMMERCIALAT:
500
+ code = scanner.nextCharCode();
501
+
502
+ if (scanner.isNameCharCode(code)) {
503
+ scanner.pos++;
504
+ return {
505
+ type: 'AtKeyword',
506
+ name: scanner.scanWord()
507
+ };
508
+ }
509
+
510
+ return maybeToken(scanner);
511
+
512
+ case ASTERISK:
513
+ case PLUSSIGN:
514
+ case QUESTIONMARK:
515
+ case NUMBERSIGN:
516
+ case EXCLAMATIONMARK:
517
+ // prohibited tokens (used as a multiplier start)
518
+ break;
519
+
520
+ case LEFTCURLYBRACKET:
521
+ // LEFTCURLYBRACKET is allowed since mdn/data uses it w/o quoting
522
+ // check next char isn't a number, because it's likely a disjoined multiplier
523
+ code = scanner.nextCharCode();
524
+
525
+ if (code < 48 || code > 57) {
526
+ return maybeToken(scanner);
527
+ }
528
+
529
+ break;
530
+
531
+ default:
532
+ if (scanner.isNameCharCode(code)) {
533
+ return readKeywordOrFunction(scanner);
534
+ }
535
+
536
+ return maybeToken(scanner);
537
+ }
538
+ }
539
+
540
+ function parse(source) {
541
+ const scanner$1 = new scanner.Scanner(source);
542
+ const result = readImplicitGroup(scanner$1);
543
+
544
+ if (scanner$1.pos !== source.length) {
545
+ scanner$1.error('Unexpected input');
546
+ }
547
+
548
+ // reduce redundant groups with single group term
549
+ if (result.terms.length === 1 && result.terms[0].type === 'Group') {
550
+ return result.terms[0];
551
+ }
552
+
553
+ return result;
554
+ }
555
+
556
+ exports.parse = parse;
@@ -0,0 +1,113 @@
1
+ 'use strict';
2
+
3
+ const SyntaxError = require('./SyntaxError.cjs');
4
+
5
+ const TAB = 9;
6
+ const N = 10;
7
+ const F = 12;
8
+ const R = 13;
9
+ const SPACE = 32;
10
+ const NAME_CHAR = new Uint8Array(128).map((_, idx) =>
11
+ /[a-zA-Z0-9\-]/.test(String.fromCharCode(idx)) ? 1 : 0
12
+ );
13
+
14
+ class Scanner {
15
+ constructor(str) {
16
+ this.str = str;
17
+ this.pos = 0;
18
+ }
19
+
20
+ charCodeAt(pos) {
21
+ return pos < this.str.length ? this.str.charCodeAt(pos) : 0;
22
+ }
23
+ charCode() {
24
+ return this.charCodeAt(this.pos);
25
+ }
26
+ isNameCharCode(code = this.charCode()) {
27
+ return code < 128 && NAME_CHAR[code] === 1;
28
+ }
29
+ nextCharCode() {
30
+ return this.charCodeAt(this.pos + 1);
31
+ }
32
+ nextNonWsCode(pos) {
33
+ return this.charCodeAt(this.findWsEnd(pos));
34
+ }
35
+ skipWs() {
36
+ this.pos = this.findWsEnd(this.pos);
37
+ }
38
+ findWsEnd(pos) {
39
+ for (; pos < this.str.length; pos++) {
40
+ const code = this.str.charCodeAt(pos);
41
+ if (code !== R && code !== N && code !== F && code !== SPACE && code !== TAB) {
42
+ break;
43
+ }
44
+ }
45
+
46
+ return pos;
47
+ }
48
+ substringToPos(end) {
49
+ return this.str.substring(this.pos, this.pos = end);
50
+ }
51
+ eat(code) {
52
+ if (this.charCode() !== code) {
53
+ this.error('Expect `' + String.fromCharCode(code) + '`');
54
+ }
55
+
56
+ this.pos++;
57
+ }
58
+ peek() {
59
+ return this.pos < this.str.length ? this.str.charAt(this.pos++) : '';
60
+ }
61
+ error(message) {
62
+ throw new SyntaxError.SyntaxError(message, this.str, this.pos);
63
+ }
64
+
65
+ scanSpaces() {
66
+ return this.substringToPos(this.findWsEnd(this.pos));
67
+ }
68
+ scanWord() {
69
+ let end = this.pos;
70
+
71
+ for (; end < this.str.length; end++) {
72
+ const code = this.str.charCodeAt(end);
73
+ if (code >= 128 || NAME_CHAR[code] === 0) {
74
+ break;
75
+ }
76
+ }
77
+
78
+ if (this.pos === end) {
79
+ this.error('Expect a keyword');
80
+ }
81
+
82
+ return this.substringToPos(end);
83
+ }
84
+ scanNumber() {
85
+ let end = this.pos;
86
+
87
+ for (; end < this.str.length; end++) {
88
+ const code = this.str.charCodeAt(end);
89
+
90
+ if (code < 48 || code > 57) {
91
+ break;
92
+ }
93
+ }
94
+
95
+ if (this.pos === end) {
96
+ this.error('Expect a number');
97
+ }
98
+
99
+ return this.substringToPos(end);
100
+ }
101
+ scanString() {
102
+ const end = this.str.indexOf('\'', this.pos + 1);
103
+
104
+ if (end === -1) {
105
+ this.pos = this.str.length;
106
+ this.error('Expect an apostrophe');
107
+ }
108
+
109
+ return this.substringToPos(end + 1);
110
+ }
111
+ }
112
+
113
+ exports.Scanner = Scanner;
@@ -0,0 +1,57 @@
1
+ 'use strict';
2
+
3
+ const noop = function() {};
4
+
5
+ function ensureFunction(value) {
6
+ return typeof value === 'function' ? value : noop;
7
+ }
8
+
9
+ function walk(node, options, context) {
10
+ function walk(node) {
11
+ enter.call(context, node);
12
+
13
+ switch (node.type) {
14
+ case 'Group':
15
+ node.terms.forEach(walk);
16
+ break;
17
+
18
+ case 'Multiplier':
19
+ case 'Boolean':
20
+ walk(node.term);
21
+ break;
22
+
23
+ case 'Type':
24
+ case 'Property':
25
+ case 'Keyword':
26
+ case 'AtKeyword':
27
+ case 'Function':
28
+ case 'String':
29
+ case 'Token':
30
+ case 'Comma':
31
+ break;
32
+
33
+ default:
34
+ throw new Error('Unknown type: ' + node.type);
35
+ }
36
+
37
+ leave.call(context, node);
38
+ }
39
+
40
+ let enter = noop;
41
+ let leave = noop;
42
+
43
+ if (typeof options === 'function') {
44
+ enter = options;
45
+ } else if (options) {
46
+ enter = ensureFunction(options.enter);
47
+ leave = ensureFunction(options.leave);
48
+ }
49
+
50
+ if (enter === noop && leave === noop) {
51
+ throw new Error('Neither `enter` nor `leave` walker handler is set or both aren\'t a function');
52
+ }
53
+
54
+ walk(node);
55
+ }
56
+
57
+ exports.walk = walk;