@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,165 @@
1
+ import { isCustomProperty } from '../../utils/names.js';
2
+ import {
3
+ Ident,
4
+ Hash,
5
+ Colon,
6
+ Semicolon,
7
+ Delim,
8
+ WhiteSpace
9
+ } from '../../tokenizer/index.js';
10
+
11
+ const EXCLAMATIONMARK = 0x0021; // U+0021 EXCLAMATION MARK (!)
12
+ const NUMBERSIGN = 0x0023; // U+0023 NUMBER SIGN (#)
13
+ const DOLLARSIGN = 0x0024; // U+0024 DOLLAR SIGN ($)
14
+ const AMPERSAND = 0x0026; // U+0026 AMPERSAND (&)
15
+ const ASTERISK = 0x002A; // U+002A ASTERISK (*)
16
+ const PLUSSIGN = 0x002B; // U+002B PLUS SIGN (+)
17
+ const SOLIDUS = 0x002F; // U+002F SOLIDUS (/)
18
+
19
+ function consumeValueRaw() {
20
+ return this.Raw(this.consumeUntilExclamationMarkOrSemicolon, true);
21
+ }
22
+
23
+ function consumeCustomPropertyRaw() {
24
+ return this.Raw(this.consumeUntilExclamationMarkOrSemicolon, false);
25
+ }
26
+
27
+ function consumeValue() {
28
+ const startValueToken = this.tokenIndex;
29
+ const value = this.Value();
30
+
31
+ if (value.type !== 'Raw' &&
32
+ this.eof === false &&
33
+ this.tokenType !== Semicolon &&
34
+ this.isDelim(EXCLAMATIONMARK) === false &&
35
+ this.isBalanceEdge(startValueToken) === false) {
36
+ this.error();
37
+ }
38
+
39
+ return value;
40
+ }
41
+
42
+ export const name = 'Declaration';
43
+ export const walkContext = 'declaration';
44
+ export const structure = {
45
+ important: [Boolean, String],
46
+ property: String,
47
+ value: ['Value', 'Raw']
48
+ };
49
+
50
+ export function parse() {
51
+ const start = this.tokenStart;
52
+ const startToken = this.tokenIndex;
53
+ const property = readProperty.call(this);
54
+ const customProperty = isCustomProperty(property);
55
+ const parseValue = customProperty ? this.parseCustomProperty : this.parseValue;
56
+ const consumeRaw = customProperty ? consumeCustomPropertyRaw : consumeValueRaw;
57
+ let important = false;
58
+ let value;
59
+
60
+ this.skipSC();
61
+ this.eat(Colon);
62
+
63
+ const valueStart = this.tokenIndex;
64
+
65
+ if (!customProperty) {
66
+ this.skipSC();
67
+ }
68
+
69
+ if (parseValue) {
70
+ value = this.parseWithFallback(consumeValue, consumeRaw);
71
+ } else {
72
+ value = consumeRaw.call(this, this.tokenIndex);
73
+ }
74
+
75
+ if (customProperty && value.type === 'Value' && value.children.isEmpty) {
76
+ for (let offset = valueStart - this.tokenIndex; offset <= 0; offset++) {
77
+ if (this.lookupType(offset) === WhiteSpace) {
78
+ value.children.appendData({
79
+ type: 'WhiteSpace',
80
+ loc: null,
81
+ value: ' '
82
+ });
83
+ break;
84
+ }
85
+ }
86
+ }
87
+
88
+ if (this.isDelim(EXCLAMATIONMARK)) {
89
+ important = getImportant.call(this);
90
+ this.skipSC();
91
+ }
92
+
93
+ // Do not include semicolon to range per spec
94
+ // https://drafts.csswg.org/css-syntax/#declaration-diagram
95
+
96
+ if (this.eof === false &&
97
+ this.tokenType !== Semicolon &&
98
+ this.isBalanceEdge(startToken) === false) {
99
+ this.error();
100
+ }
101
+
102
+ return {
103
+ type: 'Declaration',
104
+ loc: this.getLocation(start, this.tokenStart),
105
+ important,
106
+ property,
107
+ value
108
+ };
109
+ }
110
+
111
+ export function generate(node) {
112
+ this.token(Ident, node.property);
113
+ this.token(Colon, ':');
114
+ this.node(node.value);
115
+
116
+ if (node.important) {
117
+ this.token(Delim, '!');
118
+ this.token(Ident, node.important === true ? 'important' : node.important);
119
+ }
120
+ }
121
+
122
+ function readProperty() {
123
+ const start = this.tokenStart;
124
+
125
+ // hacks
126
+ if (this.tokenType === Delim) {
127
+ switch (this.charCodeAt(this.tokenStart)) {
128
+ case ASTERISK:
129
+ case DOLLARSIGN:
130
+ case PLUSSIGN:
131
+ case NUMBERSIGN:
132
+ case AMPERSAND:
133
+ this.next();
134
+ break;
135
+
136
+ // TODO: not sure we should support this hack
137
+ case SOLIDUS:
138
+ this.next();
139
+ if (this.isDelim(SOLIDUS)) {
140
+ this.next();
141
+ }
142
+ break;
143
+ }
144
+ }
145
+
146
+ if (this.tokenType === Hash) {
147
+ this.eat(Hash);
148
+ } else {
149
+ this.eat(Ident);
150
+ }
151
+
152
+ return this.substrToCursor(start);
153
+ }
154
+
155
+ // ! ws* important
156
+ function getImportant() {
157
+ this.eat(Delim);
158
+ this.skipSC();
159
+
160
+ const important = this.consume(Ident);
161
+
162
+ // store original value in case it differ from `important`
163
+ // for better original source restoring and hacks like `!ie` support
164
+ return important === 'important' ? true : important;
165
+ }
@@ -0,0 +1,62 @@
1
+ import {
2
+ WhiteSpace,
3
+ Comment,
4
+ Semicolon,
5
+ AtKeyword
6
+ } from '../../tokenizer/index.js';
7
+
8
+ const AMPERSAND = 0x0026; // U+0026 AMPERSAND (&)
9
+
10
+ function consumeRaw() {
11
+ return this.Raw(this.consumeUntilSemicolonIncluded, true);
12
+ }
13
+
14
+ export const name = 'DeclarationList';
15
+ export const structure = {
16
+ children: [[
17
+ 'Declaration',
18
+ 'Atrule',
19
+ 'Rule'
20
+ ]]
21
+ };
22
+
23
+ export function parse() {
24
+ const children = this.createList();
25
+
26
+ scan:
27
+ while (!this.eof) {
28
+ switch (this.tokenType) {
29
+ case WhiteSpace:
30
+ case Comment:
31
+ case Semicolon:
32
+ this.next();
33
+ break;
34
+
35
+ case AtKeyword:
36
+ children.push(this.parseWithFallback(this.Atrule.bind(this, true), consumeRaw));
37
+ break;
38
+
39
+ default:
40
+ if (this.isDelim(AMPERSAND)) {
41
+ children.push(this.parseWithFallback(this.Rule, consumeRaw));
42
+ } else {
43
+ children.push(this.parseWithFallback(this.Declaration, consumeRaw));
44
+ }
45
+ }
46
+ }
47
+
48
+ return {
49
+ type: 'DeclarationList',
50
+ loc: this.getLocationFromList(children),
51
+ children
52
+ };
53
+ }
54
+
55
+ export function generate(node) {
56
+ this.children(node, prev => {
57
+ if (prev.type === 'Declaration') {
58
+ this.token(Semicolon, ';');
59
+ }
60
+ });
61
+ }
62
+
@@ -0,0 +1,23 @@
1
+ import { Dimension } from '../../tokenizer/index.js';
2
+
3
+ export const name = 'Dimension';
4
+ export const structure = {
5
+ value: String,
6
+ unit: String
7
+ };
8
+
9
+ export function parse() {
10
+ const start = this.tokenStart;
11
+ const value = this.consumeNumber(Dimension);
12
+
13
+ return {
14
+ type: 'Dimension',
15
+ loc: this.getLocation(start, this.tokenStart),
16
+ value,
17
+ unit: this.substring(start + value.length, this.tokenStart)
18
+ };
19
+ }
20
+
21
+ export function generate(node) {
22
+ this.token(Dimension, node.value + node.unit);
23
+ }
@@ -0,0 +1,103 @@
1
+ import {
2
+ Ident,
3
+ Number,
4
+ Dimension,
5
+ Function as FunctionToken,
6
+ LeftParenthesis,
7
+ RightParenthesis,
8
+ Colon,
9
+ Delim
10
+ } from '../../tokenizer/index.js';
11
+
12
+ const SOLIDUS = 0x002F; // U+002F SOLIDUS (/)
13
+
14
+ export const name = 'Feature';
15
+ export const structure = {
16
+ kind: String,
17
+ name: String,
18
+ value: ['Identifier', 'Number', 'Dimension', 'Ratio', 'Function', null]
19
+ };
20
+
21
+ export function parse(kind) {
22
+ const start = this.tokenStart;
23
+ let name;
24
+ let value = null;
25
+
26
+ this.eat(LeftParenthesis);
27
+ this.skipSC();
28
+
29
+ name = this.consume(Ident);
30
+ this.skipSC();
31
+
32
+ if (this.tokenType !== RightParenthesis) {
33
+ this.eat(Colon);
34
+ this.skipSC();
35
+
36
+ switch (this.tokenType) {
37
+ case Number:
38
+ if (this.lookupNonWSType(1) === Delim) {
39
+ value = this.Ratio();
40
+ } else {
41
+ value = this.Number();
42
+ }
43
+
44
+ break;
45
+
46
+ case Dimension:
47
+ value = this.Dimension();
48
+ break;
49
+
50
+ case Ident:
51
+ value = this.Identifier();
52
+ break;
53
+
54
+ case FunctionToken:
55
+ value = this.parseWithFallback(
56
+ () => {
57
+ const res = this.Function(this.readSequence, this.scope.Value);
58
+
59
+ this.skipSC();
60
+
61
+ if (this.isDelim(SOLIDUS)) {
62
+ this.error();
63
+ }
64
+
65
+ return res;
66
+ },
67
+ () => {
68
+ return this.Ratio();
69
+ }
70
+ );
71
+ break;
72
+
73
+ default:
74
+ this.error('Number, dimension, ratio or identifier is expected');
75
+ }
76
+
77
+ this.skipSC();
78
+ }
79
+
80
+ if (!this.eof) {
81
+ this.eat(RightParenthesis);
82
+ }
83
+
84
+ return {
85
+ type: 'Feature',
86
+ loc: this.getLocation(start, this.tokenStart),
87
+ kind,
88
+ name,
89
+ value
90
+ };
91
+ }
92
+
93
+ export function generate(node) {
94
+ this.token(LeftParenthesis, '(');
95
+ this.token(Ident, node.name);
96
+
97
+ if (node.value !== null) {
98
+ this.token(Colon, ':');
99
+ this.node(node.value);
100
+ }
101
+
102
+ this.token(RightParenthesis, ')');
103
+ }
@@ -0,0 +1,63 @@
1
+ import {
2
+ Function as FunctionToken,
3
+ RightParenthesis
4
+ } from '../../tokenizer/index.js';
5
+
6
+ export const name = 'FeatureFunction';
7
+ export const structure = {
8
+ kind: String,
9
+ feature: String,
10
+ value: ['Declaration', 'Selector']
11
+ };
12
+
13
+ function getFeatureParser(kind, name) {
14
+ const featuresOfKind = this.features[kind] || {};
15
+ const parser = featuresOfKind[name];
16
+
17
+ if (typeof parser !== 'function') {
18
+ this.error(`Unknown feature ${name}()`);
19
+ }
20
+
21
+ return parser;
22
+ }
23
+
24
+ export function parse(kind = 'unknown') {
25
+ const start = this.tokenStart;
26
+ const functionName = this.consumeFunctionName();
27
+ const valueParser = getFeatureParser.call(this, kind, functionName.toLowerCase());
28
+
29
+ this.skipSC();
30
+
31
+ const value = this.parseWithFallback(
32
+ () => {
33
+ const startValueToken = this.tokenIndex;
34
+ const value = valueParser.call(this);
35
+
36
+ if (this.eof === false &&
37
+ this.isBalanceEdge(startValueToken) === false) {
38
+ this.error();
39
+ }
40
+
41
+ return value;
42
+ },
43
+ () => this.Raw(null, false)
44
+ );
45
+
46
+ if (!this.eof) {
47
+ this.eat(RightParenthesis);
48
+ }
49
+
50
+ return {
51
+ type: 'FeatureFunction',
52
+ loc: this.getLocation(start, this.tokenStart),
53
+ kind,
54
+ feature: functionName,
55
+ value
56
+ };
57
+ }
58
+
59
+ export function generate(node) {
60
+ this.token(FunctionToken, node.feature + '(');
61
+ this.node(node.value);
62
+ this.token(RightParenthesis, ')');
63
+ }
@@ -0,0 +1,133 @@
1
+ import {
2
+ Ident,
3
+ Number,
4
+ Dimension,
5
+ Function as FunctionToken,
6
+ LeftParenthesis,
7
+ RightParenthesis
8
+ } from '../../tokenizer/index.js';
9
+
10
+ const SOLIDUS = 0x002F; // U+002F SOLIDUS (/)
11
+ const LESSTHANSIGN = 0x003C; // U+003C LESS-THAN SIGN (<)
12
+ const EQUALSSIGN = 0x003D; // U+003D EQUALS SIGN (=)
13
+ const GREATERTHANSIGN = 0x003E; // U+003E GREATER-THAN SIGN (>)
14
+
15
+ export const name = 'FeatureRange';
16
+ export const structure = {
17
+ kind: String,
18
+ left: ['Identifier', 'Number', 'Dimension', 'Ratio', 'Function'],
19
+ leftComparison: String,
20
+ middle: ['Identifier', 'Number', 'Dimension', 'Ratio', 'Function'],
21
+ rightComparison: [String, null],
22
+ right: ['Identifier', 'Number', 'Dimension', 'Ratio', 'Function', null]
23
+ };
24
+
25
+ function readTerm() {
26
+ this.skipSC();
27
+
28
+ switch (this.tokenType) {
29
+ case Number:
30
+ if (this.isDelim(SOLIDUS, this.lookupOffsetNonSC(1))) {
31
+ return this.Ratio();
32
+ } else {
33
+ return this.Number();
34
+ }
35
+
36
+ case Dimension:
37
+ return this.Dimension();
38
+
39
+ case Ident:
40
+ return this.Identifier();
41
+
42
+ case FunctionToken:
43
+ return this.parseWithFallback(
44
+ () => {
45
+ const res = this.Function(this.readSequence, this.scope.Value);
46
+
47
+ this.skipSC();
48
+
49
+ if (this.isDelim(SOLIDUS)) {
50
+ this.error();
51
+ }
52
+
53
+ return res;
54
+ },
55
+ () => {
56
+ return this.Ratio();
57
+ }
58
+ );
59
+
60
+ default:
61
+ this.error('Number, dimension, ratio or identifier is expected');
62
+ }
63
+ }
64
+
65
+ function readComparison(expectColon) {
66
+ this.skipSC();
67
+
68
+ if (this.isDelim(LESSTHANSIGN) ||
69
+ this.isDelim(GREATERTHANSIGN)) {
70
+ const value = this.source[this.tokenStart];
71
+
72
+ this.next();
73
+
74
+ if (this.isDelim(EQUALSSIGN)) {
75
+ this.next();
76
+ return value + '=';
77
+ }
78
+
79
+ return value;
80
+ }
81
+
82
+ if (this.isDelim(EQUALSSIGN)) {
83
+ return '=';
84
+ }
85
+
86
+ this.error(`Expected ${expectColon ? '":", ' : ''}"<", ">", "=" or ")"`);
87
+ }
88
+
89
+ export function parse(kind = 'unknown') {
90
+ const start = this.tokenStart;
91
+
92
+ this.skipSC();
93
+ this.eat(LeftParenthesis);
94
+
95
+ const left = readTerm.call(this);
96
+ const leftComparison = readComparison.call(this, left.type === 'Identifier');
97
+ const middle = readTerm.call(this);
98
+ let rightComparison = null;
99
+ let right = null;
100
+
101
+ if (this.lookupNonWSType(0) !== RightParenthesis) {
102
+ rightComparison = readComparison.call(this);
103
+ right = readTerm.call(this);
104
+ }
105
+
106
+ this.skipSC();
107
+ this.eat(RightParenthesis);
108
+
109
+ return {
110
+ type: 'FeatureRange',
111
+ loc: this.getLocation(start, this.tokenStart),
112
+ kind,
113
+ left,
114
+ leftComparison,
115
+ middle,
116
+ rightComparison,
117
+ right
118
+ };
119
+ }
120
+
121
+ export function generate(node) {
122
+ this.token(LeftParenthesis, '(');
123
+ this.node(node.left);
124
+ this.tokenize(node.leftComparison);
125
+ this.node(node.middle);
126
+
127
+ if (node.right) {
128
+ this.tokenize(node.rightComparison);
129
+ this.node(node.right);
130
+ }
131
+
132
+ this.token(RightParenthesis, ')');
133
+ }
@@ -0,0 +1,41 @@
1
+ import {
2
+ Function as FunctionToken,
3
+ RightParenthesis
4
+ } from '../../tokenizer/index.js';
5
+
6
+
7
+ export const name = 'Function';
8
+ export const walkContext = 'function';
9
+ export const structure = {
10
+ name: String,
11
+ children: [[]]
12
+ };
13
+
14
+ // <function-token> <sequence> )
15
+ export function parse(readSequence, recognizer) {
16
+ const start = this.tokenStart;
17
+ const name = this.consumeFunctionName();
18
+ const nameLowerCase = name.toLowerCase();
19
+ let children;
20
+
21
+ children = recognizer.hasOwnProperty(nameLowerCase)
22
+ ? recognizer[nameLowerCase].call(this, recognizer)
23
+ : readSequence.call(this, recognizer);
24
+
25
+ if (!this.eof) {
26
+ this.eat(RightParenthesis);
27
+ }
28
+
29
+ return {
30
+ type: 'Function',
31
+ loc: this.getLocation(start, this.tokenStart),
32
+ name,
33
+ children
34
+ };
35
+ }
36
+
37
+ export function generate(node) {
38
+ this.token(FunctionToken, node.name + '(');
39
+ this.children(node);
40
+ this.token(RightParenthesis, ')');
41
+ }
@@ -0,0 +1,66 @@
1
+ import {
2
+ Function as FunctionToken,
3
+ LeftParenthesis,
4
+ RightParenthesis
5
+ } from '../../tokenizer/index.js';
6
+
7
+
8
+ export const name = 'GeneralEnclosed';
9
+ export const structure = {
10
+ kind: String,
11
+ function: [String, null],
12
+ children: [[]]
13
+ };
14
+
15
+ // <function-token> <any-value> )
16
+ // ( <any-value> )
17
+ export function parse(kind) {
18
+ const start = this.tokenStart;
19
+ let functionName = null;
20
+
21
+ if (this.tokenType === FunctionToken) {
22
+ functionName = this.consumeFunctionName();
23
+ } else {
24
+ this.eat(LeftParenthesis);
25
+ }
26
+
27
+ const children = this.parseWithFallback(
28
+ () => {
29
+ const startValueToken = this.tokenIndex;
30
+ const children = this.readSequence(this.scope.Value);
31
+
32
+ if (this.eof === false &&
33
+ this.isBalanceEdge(startValueToken) === false) {
34
+ this.error();
35
+ }
36
+
37
+ return children;
38
+ },
39
+ () => this.createSingleNodeList(
40
+ this.Raw(null, false)
41
+ )
42
+ );
43
+
44
+ if (!this.eof) {
45
+ this.eat(RightParenthesis);
46
+ }
47
+
48
+ return {
49
+ type: 'GeneralEnclosed',
50
+ loc: this.getLocation(start, this.tokenStart),
51
+ kind,
52
+ function: functionName,
53
+ children
54
+ };
55
+ }
56
+
57
+ export function generate(node) {
58
+ if (node.function) {
59
+ this.token(FunctionToken, node.function + '(');
60
+ } else {
61
+ this.token(LeftParenthesis, '(');
62
+ }
63
+
64
+ this.children(node);
65
+ this.token(RightParenthesis, ')');
66
+ }
@@ -0,0 +1,23 @@
1
+ import { Hash } from '../../tokenizer/index.js';
2
+
3
+ // '#' ident
4
+ export const xxx = 'XXX';
5
+ export const name = 'Hash';
6
+ export const structure = {
7
+ value: String
8
+ };
9
+ export function parse() {
10
+ const start = this.tokenStart;
11
+
12
+ this.eat(Hash);
13
+
14
+ return {
15
+ type: 'Hash',
16
+ loc: this.getLocation(start, this.tokenStart),
17
+ value: this.substrToCursor(start + 1)
18
+ };
19
+ }
20
+ export function generate(node) {
21
+ this.token(Hash, '#' + node.value);
22
+ }
23
+
@@ -0,0 +1,26 @@
1
+ import { Hash, Delim } from '../../tokenizer/index.js';
2
+
3
+ export const name = 'IdSelector';
4
+ export const structure = {
5
+ name: String
6
+ };
7
+
8
+ export function parse() {
9
+ const start = this.tokenStart;
10
+
11
+ // TODO: check value is an ident
12
+ this.eat(Hash);
13
+
14
+ return {
15
+ type: 'IdSelector',
16
+ loc: this.getLocation(start, this.tokenStart),
17
+ name: this.substrToCursor(start + 1)
18
+ };
19
+ }
20
+
21
+ export function generate(node) {
22
+ // Using Delim instead of Hash is a hack to avoid for a whitespace between ident and id-selector
23
+ // in safe mode (e.g. "a#id"), because IE11 doesn't allow a sequence <ident-token> <hash-token>
24
+ // without a whitespace in values (e.g. "1px solid#000")
25
+ this.token(Delim, '#' + node.name);
26
+ }