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