@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,632 @@
1
+ 'use strict';
2
+
3
+ const matchGraph = require('./match-graph.cjs');
4
+ const types = require('../tokenizer/types.cjs');
5
+
6
+ const { hasOwnProperty } = Object.prototype;
7
+ const STUB = 0;
8
+ const TOKEN = 1;
9
+ const OPEN_SYNTAX = 2;
10
+ const CLOSE_SYNTAX = 3;
11
+
12
+ const EXIT_REASON_MATCH = 'Match';
13
+ const EXIT_REASON_MISMATCH = 'Mismatch';
14
+ const EXIT_REASON_ITERATION_LIMIT = 'Maximum iteration number exceeded (please fill an issue on https://github.com/csstree/csstree/issues)';
15
+
16
+ const ITERATION_LIMIT = 15000;
17
+
18
+ function reverseList(list) {
19
+ let prev = null;
20
+ let next = null;
21
+ let item = list;
22
+
23
+ while (item !== null) {
24
+ next = item.prev;
25
+ item.prev = prev;
26
+ prev = item;
27
+ item = next;
28
+ }
29
+
30
+ return prev;
31
+ }
32
+
33
+ function areStringsEqualCaseInsensitive(testStr, referenceStr) {
34
+ if (testStr.length !== referenceStr.length) {
35
+ return false;
36
+ }
37
+
38
+ for (let i = 0; i < testStr.length; i++) {
39
+ const referenceCode = referenceStr.charCodeAt(i);
40
+ let testCode = testStr.charCodeAt(i);
41
+
42
+ // testCode.toLowerCase() for U+0041 LATIN CAPITAL LETTER A (A) .. U+005A LATIN CAPITAL LETTER Z (Z).
43
+ if (testCode >= 0x0041 && testCode <= 0x005A) {
44
+ testCode = testCode | 32;
45
+ }
46
+
47
+ if (testCode !== referenceCode) {
48
+ return false;
49
+ }
50
+ }
51
+
52
+ return true;
53
+ }
54
+
55
+ function isContextEdgeDelim(token) {
56
+ if (token.type !== types.Delim) {
57
+ return false;
58
+ }
59
+
60
+ // Fix matching for unicode-range: U+30??, U+FF00-FF9F
61
+ // Probably we need to check out previous match instead
62
+ return token.value !== '?';
63
+ }
64
+
65
+ function isCommaContextStart(token) {
66
+ if (token === null) {
67
+ return true;
68
+ }
69
+
70
+ return (
71
+ token.type === types.Comma ||
72
+ token.type === types.Function ||
73
+ token.type === types.LeftParenthesis ||
74
+ token.type === types.LeftSquareBracket ||
75
+ token.type === types.LeftCurlyBracket ||
76
+ isContextEdgeDelim(token)
77
+ );
78
+ }
79
+
80
+ function isCommaContextEnd(token) {
81
+ if (token === null) {
82
+ return true;
83
+ }
84
+
85
+ return (
86
+ token.type === types.RightParenthesis ||
87
+ token.type === types.RightSquareBracket ||
88
+ token.type === types.RightCurlyBracket ||
89
+ (token.type === types.Delim && token.value === '/')
90
+ );
91
+ }
92
+
93
+ function internalMatch(tokens, state, syntaxes) {
94
+ function moveToNextToken() {
95
+ do {
96
+ tokenIndex++;
97
+ token = tokenIndex < tokens.length ? tokens[tokenIndex] : null;
98
+ } while (token !== null && (token.type === types.WhiteSpace || token.type === types.Comment));
99
+ }
100
+
101
+ function getNextToken(offset) {
102
+ const nextIndex = tokenIndex + offset;
103
+
104
+ return nextIndex < tokens.length ? tokens[nextIndex] : null;
105
+ }
106
+
107
+ function stateSnapshotFromSyntax(nextState, prev) {
108
+ return {
109
+ nextState,
110
+ matchStack,
111
+ syntaxStack,
112
+ thenStack,
113
+ tokenIndex,
114
+ prev
115
+ };
116
+ }
117
+
118
+ function pushThenStack(nextState) {
119
+ thenStack = {
120
+ nextState,
121
+ matchStack,
122
+ syntaxStack,
123
+ prev: thenStack
124
+ };
125
+ }
126
+
127
+ function pushElseStack(nextState) {
128
+ elseStack = stateSnapshotFromSyntax(nextState, elseStack);
129
+ }
130
+
131
+ function addTokenToMatch() {
132
+ matchStack = {
133
+ type: TOKEN,
134
+ syntax: state.syntax,
135
+ token,
136
+ prev: matchStack
137
+ };
138
+
139
+ moveToNextToken();
140
+ syntaxStash = null;
141
+
142
+ if (tokenIndex > longestMatch) {
143
+ longestMatch = tokenIndex;
144
+ }
145
+ }
146
+
147
+ function openSyntax() {
148
+ syntaxStack = {
149
+ syntax: state.syntax,
150
+ opts: state.syntax.opts || (syntaxStack !== null && syntaxStack.opts) || null,
151
+ prev: syntaxStack
152
+ };
153
+
154
+ matchStack = {
155
+ type: OPEN_SYNTAX,
156
+ syntax: state.syntax,
157
+ token: matchStack.token,
158
+ prev: matchStack
159
+ };
160
+ }
161
+
162
+ function closeSyntax() {
163
+ if (matchStack.type === OPEN_SYNTAX) {
164
+ matchStack = matchStack.prev;
165
+ } else {
166
+ matchStack = {
167
+ type: CLOSE_SYNTAX,
168
+ syntax: syntaxStack.syntax,
169
+ token: matchStack.token,
170
+ prev: matchStack
171
+ };
172
+ }
173
+
174
+ syntaxStack = syntaxStack.prev;
175
+ }
176
+
177
+ let syntaxStack = null;
178
+ let thenStack = null;
179
+ let elseStack = null;
180
+
181
+ // null – stashing allowed, nothing stashed
182
+ // false – stashing disabled, nothing stashed
183
+ // anithing else – fail stashable syntaxes, some syntax stashed
184
+ let syntaxStash = null;
185
+
186
+ let iterationCount = 0; // count iterations and prevent infinite loop
187
+ let exitReason = null;
188
+
189
+ let token = null;
190
+ let tokenIndex = -1;
191
+ let longestMatch = 0;
192
+ let matchStack = {
193
+ type: STUB,
194
+ syntax: null,
195
+ token: null,
196
+ prev: null
197
+ };
198
+
199
+ moveToNextToken();
200
+
201
+ while (exitReason === null && ++iterationCount < ITERATION_LIMIT) {
202
+ // function mapList(list, fn) {
203
+ // const result = [];
204
+ // while (list) {
205
+ // result.unshift(fn(list));
206
+ // list = list.prev;
207
+ // }
208
+ // return result;
209
+ // }
210
+ // console.log('--\n',
211
+ // '#' + iterationCount,
212
+ // require('util').inspect({
213
+ // match: mapList(matchStack, x => x.type === TOKEN ? x.token && x.token.value : x.syntax ? ({ [OPEN_SYNTAX]: '<', [CLOSE_SYNTAX]: '</' }[x.type] || x.type) + '!' + x.syntax.name : null),
214
+ // token: token && token.value,
215
+ // tokenIndex,
216
+ // syntax: syntax.type + (syntax.id ? ' #' + syntax.id : '')
217
+ // }, { depth: null })
218
+ // );
219
+ switch (state.type) {
220
+ case 'Match':
221
+ if (thenStack === null) {
222
+ // turn to MISMATCH when some tokens left unmatched
223
+ if (token !== null) {
224
+ // doesn't mismatch if just one token left and it's an IE hack
225
+ if (tokenIndex !== tokens.length - 1 || (token.value !== '\\0' && token.value !== '\\9')) {
226
+ state = matchGraph.MISMATCH;
227
+ break;
228
+ }
229
+ }
230
+
231
+ // break the main loop, return a result - MATCH
232
+ exitReason = EXIT_REASON_MATCH;
233
+ break;
234
+ }
235
+
236
+ // go to next syntax (`then` branch)
237
+ state = thenStack.nextState;
238
+
239
+ // check match is not empty
240
+ if (state === matchGraph.DISALLOW_EMPTY) {
241
+ if (thenStack.matchStack === matchStack) {
242
+ state = matchGraph.MISMATCH;
243
+ break;
244
+ } else {
245
+ state = matchGraph.MATCH;
246
+ }
247
+ }
248
+
249
+ // close syntax if needed
250
+ while (thenStack.syntaxStack !== syntaxStack) {
251
+ closeSyntax();
252
+ }
253
+
254
+ // pop stack
255
+ thenStack = thenStack.prev;
256
+ break;
257
+
258
+ case 'Mismatch':
259
+ // when some syntax is stashed
260
+ if (syntaxStash !== null && syntaxStash !== false) {
261
+ // there is no else branches or a branch reduce match stack
262
+ if (elseStack === null || tokenIndex > elseStack.tokenIndex) {
263
+ // restore state from the stash
264
+ elseStack = syntaxStash;
265
+ syntaxStash = false; // disable stashing
266
+ }
267
+ } else if (elseStack === null) {
268
+ // no else branches -> break the main loop
269
+ // return a result - MISMATCH
270
+ exitReason = EXIT_REASON_MISMATCH;
271
+ break;
272
+ }
273
+
274
+ // go to next syntax (`else` branch)
275
+ state = elseStack.nextState;
276
+
277
+ // restore all the rest stack states
278
+ thenStack = elseStack.thenStack;
279
+ syntaxStack = elseStack.syntaxStack;
280
+ matchStack = elseStack.matchStack;
281
+ tokenIndex = elseStack.tokenIndex;
282
+ token = tokenIndex < tokens.length ? tokens[tokenIndex] : null;
283
+
284
+ // pop stack
285
+ elseStack = elseStack.prev;
286
+ break;
287
+
288
+ case 'MatchGraph':
289
+ state = state.match;
290
+ break;
291
+
292
+ case 'If':
293
+ // IMPORTANT: else stack push must go first,
294
+ // since it stores the state of thenStack before changes
295
+ if (state.else !== matchGraph.MISMATCH) {
296
+ pushElseStack(state.else);
297
+ }
298
+
299
+ if (state.then !== matchGraph.MATCH) {
300
+ pushThenStack(state.then);
301
+ }
302
+
303
+ state = state.match;
304
+ break;
305
+
306
+ case 'MatchOnce':
307
+ state = {
308
+ type: 'MatchOnceBuffer',
309
+ syntax: state,
310
+ index: 0,
311
+ mask: 0
312
+ };
313
+ break;
314
+
315
+ case 'MatchOnceBuffer': {
316
+ const terms = state.syntax.terms;
317
+
318
+ if (state.index === terms.length) {
319
+ // no matches at all or it's required all terms to be matched
320
+ if (state.mask === 0 || state.syntax.all) {
321
+ state = matchGraph.MISMATCH;
322
+ break;
323
+ }
324
+
325
+ // a partial match is ok
326
+ state = matchGraph.MATCH;
327
+ break;
328
+ }
329
+
330
+ // all terms are matched
331
+ if (state.mask === (1 << terms.length) - 1) {
332
+ state = matchGraph.MATCH;
333
+ break;
334
+ }
335
+
336
+ for (; state.index < terms.length; state.index++) {
337
+ const matchFlag = 1 << state.index;
338
+
339
+ if ((state.mask & matchFlag) === 0) {
340
+ // IMPORTANT: else stack push must go first,
341
+ // since it stores the state of thenStack before changes
342
+ pushElseStack(state);
343
+ pushThenStack({
344
+ type: 'AddMatchOnce',
345
+ syntax: state.syntax,
346
+ mask: state.mask | matchFlag
347
+ });
348
+
349
+ // match
350
+ state = terms[state.index++];
351
+ break;
352
+ }
353
+ }
354
+ break;
355
+ }
356
+
357
+ case 'AddMatchOnce':
358
+ state = {
359
+ type: 'MatchOnceBuffer',
360
+ syntax: state.syntax,
361
+ index: 0,
362
+ mask: state.mask
363
+ };
364
+ break;
365
+
366
+ case 'Enum':
367
+ if (token !== null) {
368
+ let name = token.value.toLowerCase();
369
+
370
+ // drop \0 and \9 hack from keyword name
371
+ if (name.indexOf('\\') !== -1) {
372
+ name = name.replace(/\\[09].*$/, '');
373
+ }
374
+
375
+ if (hasOwnProperty.call(state.map, name)) {
376
+ state = state.map[name];
377
+ break;
378
+ }
379
+ }
380
+
381
+ state = matchGraph.MISMATCH;
382
+ break;
383
+
384
+ case 'Generic': {
385
+ const opts = syntaxStack !== null ? syntaxStack.opts : null;
386
+ const lastTokenIndex = tokenIndex + Math.floor(state.fn(token, getNextToken, opts));
387
+
388
+ if (!isNaN(lastTokenIndex) && lastTokenIndex > tokenIndex) {
389
+ while (tokenIndex < lastTokenIndex) {
390
+ addTokenToMatch();
391
+ }
392
+
393
+ state = matchGraph.MATCH;
394
+ } else {
395
+ state = matchGraph.MISMATCH;
396
+ }
397
+
398
+ break;
399
+ }
400
+
401
+ case 'Type':
402
+ case 'Property': {
403
+ const syntaxDict = state.type === 'Type' ? 'types' : 'properties';
404
+ const dictSyntax = hasOwnProperty.call(syntaxes, syntaxDict) ? syntaxes[syntaxDict][state.name] : null;
405
+
406
+ if (!dictSyntax || !dictSyntax.match) {
407
+ throw new Error(
408
+ 'Bad syntax reference: ' +
409
+ (state.type === 'Type'
410
+ ? '<' + state.name + '>'
411
+ : '<\'' + state.name + '\'>')
412
+ );
413
+ }
414
+
415
+ // stash a syntax for types with low priority
416
+ if (syntaxStash !== false && token !== null && state.type === 'Type') {
417
+ const lowPriorityMatching =
418
+ // https://drafts.csswg.org/css-values-4/#custom-idents
419
+ // When parsing positionally-ambiguous keywords in a property value, a <custom-ident> production
420
+ // can only claim the keyword if no other unfulfilled production can claim it.
421
+ (state.name === 'custom-ident' && token.type === types.Ident) ||
422
+
423
+ // https://drafts.csswg.org/css-values-4/#lengths
424
+ // ... if a `0` could be parsed as either a <number> or a <length> in a property (such as line-height),
425
+ // it must parse as a <number>
426
+ (state.name === 'length' && token.value === '0');
427
+
428
+ if (lowPriorityMatching) {
429
+ if (syntaxStash === null) {
430
+ syntaxStash = stateSnapshotFromSyntax(state, elseStack);
431
+ }
432
+
433
+ state = matchGraph.MISMATCH;
434
+ break;
435
+ }
436
+ }
437
+
438
+ openSyntax();
439
+ state = dictSyntax.matchRef || dictSyntax.match;
440
+ break;
441
+ }
442
+
443
+ case 'Keyword': {
444
+ const name = state.name;
445
+
446
+ if (token !== null) {
447
+ let keywordName = token.value;
448
+
449
+ // drop \0 and \9 hack from keyword name
450
+ if (keywordName.indexOf('\\') !== -1) {
451
+ keywordName = keywordName.replace(/\\[09].*$/, '');
452
+ }
453
+
454
+ if (areStringsEqualCaseInsensitive(keywordName, name)) {
455
+ addTokenToMatch();
456
+ state = matchGraph.MATCH;
457
+ break;
458
+ }
459
+ }
460
+
461
+ state = matchGraph.MISMATCH;
462
+ break;
463
+ }
464
+
465
+ case 'AtKeyword':
466
+ case 'Function':
467
+ if (token !== null && areStringsEqualCaseInsensitive(token.value, state.name)) {
468
+ addTokenToMatch();
469
+ state = matchGraph.MATCH;
470
+ break;
471
+ }
472
+
473
+ state = matchGraph.MISMATCH;
474
+ break;
475
+
476
+ case 'Token':
477
+ if (token !== null && token.value === state.value) {
478
+ addTokenToMatch();
479
+ state = matchGraph.MATCH;
480
+ break;
481
+ }
482
+
483
+ state = matchGraph.MISMATCH;
484
+ break;
485
+
486
+ case 'Comma':
487
+ if (token !== null && token.type === types.Comma) {
488
+ if (isCommaContextStart(matchStack.token)) {
489
+ state = matchGraph.MISMATCH;
490
+ } else {
491
+ addTokenToMatch();
492
+ state = isCommaContextEnd(token) ? matchGraph.MISMATCH : matchGraph.MATCH;
493
+ }
494
+ } else {
495
+ state = isCommaContextStart(matchStack.token) || isCommaContextEnd(token) ? matchGraph.MATCH : matchGraph.MISMATCH;
496
+ }
497
+
498
+ break;
499
+
500
+ case 'String':
501
+ let string = '';
502
+ let lastTokenIndex = tokenIndex;
503
+
504
+ for (; lastTokenIndex < tokens.length && string.length < state.value.length; lastTokenIndex++) {
505
+ string += tokens[lastTokenIndex].value;
506
+ }
507
+
508
+ if (areStringsEqualCaseInsensitive(string, state.value)) {
509
+ while (tokenIndex < lastTokenIndex) {
510
+ addTokenToMatch();
511
+ }
512
+
513
+ state = matchGraph.MATCH;
514
+ } else {
515
+ state = matchGraph.MISMATCH;
516
+ }
517
+
518
+ break;
519
+
520
+ default:
521
+ throw new Error('Unknown node type: ' + state.type);
522
+ }
523
+ }
524
+
525
+ switch (exitReason) {
526
+ case null:
527
+ console.warn('[csstree-match] BREAK after ' + ITERATION_LIMIT + ' iterations');
528
+ exitReason = EXIT_REASON_ITERATION_LIMIT;
529
+ matchStack = null;
530
+ break;
531
+
532
+ case EXIT_REASON_MATCH:
533
+ while (syntaxStack !== null) {
534
+ closeSyntax();
535
+ }
536
+ break;
537
+
538
+ default:
539
+ matchStack = null;
540
+ }
541
+
542
+ return {
543
+ tokens,
544
+ reason: exitReason,
545
+ iterations: iterationCount,
546
+ match: matchStack,
547
+ longestMatch
548
+ };
549
+ }
550
+
551
+ function matchAsList(tokens, matchGraph, syntaxes) {
552
+ const matchResult = internalMatch(tokens, matchGraph, syntaxes || {});
553
+
554
+ if (matchResult.match !== null) {
555
+ let item = reverseList(matchResult.match).prev;
556
+
557
+ matchResult.match = [];
558
+
559
+ while (item !== null) {
560
+ switch (item.type) {
561
+ case OPEN_SYNTAX:
562
+ case CLOSE_SYNTAX:
563
+ matchResult.match.push({
564
+ type: item.type,
565
+ syntax: item.syntax
566
+ });
567
+ break;
568
+
569
+ default:
570
+ matchResult.match.push({
571
+ token: item.token.value,
572
+ node: item.token.node
573
+ });
574
+ break;
575
+ }
576
+
577
+ item = item.prev;
578
+ }
579
+ }
580
+
581
+ return matchResult;
582
+ }
583
+
584
+ function matchAsTree(tokens, matchGraph, syntaxes) {
585
+ const matchResult = internalMatch(tokens, matchGraph, syntaxes || {});
586
+
587
+ if (matchResult.match === null) {
588
+ return matchResult;
589
+ }
590
+
591
+ let item = matchResult.match;
592
+ let host = matchResult.match = {
593
+ syntax: matchGraph.syntax || null,
594
+ match: []
595
+ };
596
+ const hostStack = [host];
597
+
598
+ // revert a list and start with 2nd item since 1st is a stub item
599
+ item = reverseList(item).prev;
600
+
601
+ // build a tree
602
+ while (item !== null) {
603
+ switch (item.type) {
604
+ case OPEN_SYNTAX:
605
+ host.match.push(host = {
606
+ syntax: item.syntax,
607
+ match: []
608
+ });
609
+ hostStack.push(host);
610
+ break;
611
+
612
+ case CLOSE_SYNTAX:
613
+ hostStack.pop();
614
+ host = hostStack[hostStack.length - 1];
615
+ break;
616
+
617
+ default:
618
+ host.match.push({
619
+ syntax: item.syntax || null,
620
+ token: item.token.value,
621
+ node: item.token.node
622
+ });
623
+ }
624
+
625
+ item = item.prev;
626
+ }
627
+
628
+ return matchResult;
629
+ }
630
+
631
+ exports.matchAsList = matchAsList;
632
+ exports.matchAsTree = matchAsTree;
@@ -0,0 +1,54 @@
1
+ 'use strict';
2
+
3
+ const index = require('../tokenizer/index.cjs');
4
+
5
+ const astToTokens = {
6
+ decorator(handlers) {
7
+ const tokens = [];
8
+ let curNode = null;
9
+
10
+ return {
11
+ ...handlers,
12
+ node(node) {
13
+ const tmp = curNode;
14
+ curNode = node;
15
+ handlers.node.call(this, node);
16
+ curNode = tmp;
17
+ },
18
+ emit(value, type, auto) {
19
+ tokens.push({
20
+ type,
21
+ value,
22
+ node: auto ? null : curNode
23
+ });
24
+ },
25
+ result() {
26
+ return tokens;
27
+ }
28
+ };
29
+ }
30
+ };
31
+
32
+ function stringToTokens(str) {
33
+ const tokens = [];
34
+
35
+ index.tokenize(str, (type, start, end) =>
36
+ tokens.push({
37
+ type,
38
+ value: str.slice(start, end),
39
+ node: null
40
+ })
41
+ );
42
+
43
+ return tokens;
44
+ }
45
+
46
+ function prepareTokens(value, syntax) {
47
+ if (typeof value === 'string') {
48
+ return stringToTokens(value);
49
+ }
50
+
51
+ return syntax.generate(value, astToTokens);
52
+ }
53
+
54
+ module.exports = prepareTokens;