crass 0.2.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -0
  3. data/HISTORY.md +22 -1
  4. data/LICENSE +1 -1
  5. data/README.md +64 -72
  6. data/Rakefile +4 -0
  7. data/crass.gemspec +2 -2
  8. data/lib/crass.rb +1 -1
  9. data/lib/crass/parser.rb +231 -96
  10. data/lib/crass/scanner.rb +21 -21
  11. data/lib/crass/token-scanner.rb +8 -1
  12. data/lib/crass/tokenizer.rb +133 -131
  13. data/lib/crass/version.rb +1 -1
  14. data/test/css-parsing-tests/An+B.json +156 -0
  15. data/test/css-parsing-tests/LICENSE +8 -0
  16. data/test/css-parsing-tests/README.rst +301 -0
  17. data/test/css-parsing-tests/color3.json +142 -0
  18. data/test/css-parsing-tests/color3_hsl.json +3890 -0
  19. data/test/css-parsing-tests/color3_keywords.json +803 -0
  20. data/test/css-parsing-tests/component_value_list.json +432 -0
  21. data/test/css-parsing-tests/declaration_list.json +44 -0
  22. data/test/css-parsing-tests/make_color3_hsl.py +17 -0
  23. data/test/css-parsing-tests/make_color3_keywords.py +191 -0
  24. data/test/css-parsing-tests/one_component_value.json +27 -0
  25. data/test/css-parsing-tests/one_declaration.json +46 -0
  26. data/test/css-parsing-tests/one_rule.json +36 -0
  27. data/test/css-parsing-tests/rule_list.json +48 -0
  28. data/test/css-parsing-tests/stylesheet.json +44 -0
  29. data/test/css-parsing-tests/stylesheet_bytes.json +146 -0
  30. data/test/shared/parse_rules.rb +377 -434
  31. data/test/support/common.rb +124 -0
  32. data/test/support/serialization/animate.css +3158 -0
  33. data/test/support/serialization/html5-boilerplate.css +268 -0
  34. data/test/support/serialization/misc.css +9 -0
  35. data/test/test_css_parsing_tests.rb +150 -0
  36. data/test/test_parse_properties.rb +136 -211
  37. data/test/test_parse_rules.rb +0 -52
  38. data/test/test_parse_stylesheet.rb +0 -39
  39. data/test/test_serialization.rb +13 -4
  40. metadata +44 -7
  41. data/test/test_tokenizer.rb +0 -1562
@@ -6,156 +6,227 @@
6
6
  shared_tests_for 'parsing a list of rules' do
7
7
  it 'should parse an empty stylesheet' do
8
8
  assert_equal([], parse(''))
9
- assert_equal([], parse('foo'))
10
- assert_equal([], parse('foo 4'))
9
+ assert_equal([{:node=>:error, :value=>"invalid"}], parse('foo'))
10
+ assert_equal([{:node=>:error, :value=>"invalid"}], parse('foo 4'))
11
11
  end
12
12
 
13
13
  describe 'should parse an at-rule' do
14
14
  describe 'without a block' do
15
15
  it 'without a prelude' do
16
16
  tree = parse('@foo')
17
- rule = tree[0]
18
17
 
19
- assert_equal(1, tree.size)
20
- assert_equal(:at_rule, rule[:node])
21
- assert_equal("foo", rule[:name])
22
- assert_equal([], rule[:prelude])
23
- assert_tokens("@foo", rule[:tokens])
18
+ assert_equal([
19
+ {:node=>:at_rule,
20
+ :name=>"foo",
21
+ :prelude=>[],
22
+ :tokens=>[{:node=>:at_keyword, :pos=>0, :raw=>"@foo", :value=>"foo"}]}
23
+ ], tree)
24
24
  end
25
25
 
26
26
  it 'with a prelude followed by a comment' do
27
27
  tree = parse("@foo bar; \t/* comment */")
28
- rule = tree[0]
29
28
 
30
- assert_equal(2, tree.size)
31
- assert_equal(:at_rule, rule[:node])
32
- assert_equal("foo", rule[:name])
33
- assert_tokens(" bar", rule[:prelude], 4)
34
- assert_tokens("@foo bar;", rule[:tokens])
35
- assert_tokens(" \t", tree[1], 9)
29
+ assert_equal([
30
+ {:node=>:at_rule,
31
+ :name=>"foo",
32
+ :prelude=>
33
+ [{:node=>:whitespace, :pos=>4, :raw=>" "},
34
+ {:node=>:ident, :pos=>5, :raw=>"bar", :value=>"bar"}],
35
+ :tokens=>
36
+ [{:node=>:at_keyword, :pos=>0, :raw=>"@foo", :value=>"foo"},
37
+ {:node=>:whitespace, :pos=>4, :raw=>" "},
38
+ {:node=>:ident, :pos=>5, :raw=>"bar", :value=>"bar"},
39
+ {:node=>:semicolon, :pos=>8, :raw=>";"}]},
40
+ {:node=>:whitespace, :pos=>9, :raw=>" \t"}
41
+ ], tree)
36
42
  end
37
43
 
38
44
  it 'with a prelude followed by a comment, when :preserve_comments == true' do
39
45
  options = {:preserve_comments => true}
40
46
  tree = parse("@foo bar; \t/* comment */", options)
41
- rule = tree[0]
42
47
 
43
- assert_equal(3, tree.size)
44
- assert_equal(:at_rule, rule[:node])
45
- assert_equal("foo", rule[:name])
46
- assert_tokens(" bar", rule[:prelude], 4, options)
47
- assert_tokens("@foo bar;", rule[:tokens], 0, options)
48
- assert_tokens(" \t", tree[1], 9, options)
49
- assert_tokens("/* comment */", tree[2], 11, options)
48
+ assert_equal([
49
+ {:node=>:at_rule,
50
+ :name=>"foo",
51
+ :prelude=>
52
+ [{:node=>:whitespace, :pos=>4, :raw=>" "},
53
+ {:node=>:ident, :pos=>5, :raw=>"bar", :value=>"bar"}],
54
+ :tokens=>
55
+ [{:node=>:at_keyword, :pos=>0, :raw=>"@foo", :value=>"foo"},
56
+ {:node=>:whitespace, :pos=>4, :raw=>" "},
57
+ {:node=>:ident, :pos=>5, :raw=>"bar", :value=>"bar"},
58
+ {:node=>:semicolon, :pos=>8, :raw=>";"}]},
59
+ {:node=>:whitespace, :pos=>9, :raw=>" \t"},
60
+ {:node=>:comment, :pos=>11, :raw=>"/* comment */", :value=>" comment "}
61
+ ], tree)
50
62
  end
51
63
 
52
64
  it 'with a prelude containing a simple block' do
53
65
  tree = parse("@foo [ bar")
54
- rule = tree[0]
55
66
 
56
- assert_equal(1, tree.size)
57
- assert_equal(:at_rule, rule[:node])
58
- assert_equal("foo", rule[:name])
59
- assert_tokens("@foo [ bar", rule[:tokens])
60
-
61
- prelude = rule[:prelude]
62
- assert_equal(2, prelude.size)
63
- assert_tokens(" ", prelude[0], 4)
64
-
65
- block = prelude[1]
66
- assert_equal(:simple_block, block[:node])
67
- assert_equal("[", block[:start])
68
- assert_equal("]", block[:end])
69
- assert_tokens("[ bar", block[:tokens], 5)
70
- assert_tokens(" bar", block[:value], 6)
67
+ assert_equal([
68
+ {:node=>:at_rule,
69
+ :name=>"foo",
70
+ :prelude=>
71
+ [{:node=>:whitespace, :pos=>4, :raw=>" "},
72
+ {:node=>:simple_block,
73
+ :start=>"[",
74
+ :end=>"]",
75
+ :value=>
76
+ [{:node=>:whitespace, :pos=>6, :raw=>" "},
77
+ {:node=>:ident, :pos=>7, :raw=>"bar", :value=>"bar"}],
78
+ :tokens=>
79
+ [{:node=>:"[", :pos=>5, :raw=>"["},
80
+ {:node=>:whitespace, :pos=>6, :raw=>" "},
81
+ {:node=>:ident, :pos=>7, :raw=>"bar", :value=>"bar"}]}],
82
+ :tokens=>
83
+ [{:node=>:at_keyword, :pos=>0, :raw=>"@foo", :value=>"foo"},
84
+ {:node=>:whitespace, :pos=>4, :raw=>" "},
85
+ {:node=>:"[", :pos=>5, :raw=>"["},
86
+ {:node=>:whitespace, :pos=>6, :raw=>" "},
87
+ {:node=>:ident, :pos=>7, :raw=>"bar", :value=>"bar"}]}
88
+ ], tree)
71
89
  end
72
90
  end
73
91
 
74
92
  describe 'with a block' do
75
93
  it 'unclosed' do
76
94
  tree = parse("@foo { bar")
77
- rule = tree[0]
78
95
 
79
- assert_equal(1, tree.size)
80
- assert_equal(:at_rule, rule[:node])
81
- assert_equal("foo", rule[:name])
82
- assert_tokens(" ", rule[:prelude], 4)
83
- assert_tokens("@foo { bar", rule[:tokens])
84
-
85
- block = rule[:block]
86
- assert_equal(:simple_block, block[:node])
87
- assert_equal("{", block[:start])
88
- assert_equal("}", block[:end])
89
- assert_tokens("{ bar", block[:tokens], 5)
90
- assert_tokens(" bar", block[:value], 6)
96
+ assert_equal([
97
+ {:node=>:at_rule,
98
+ :name=>"foo",
99
+ :prelude=>[{:node=>:whitespace, :pos=>4, :raw=>" "}],
100
+ :block=>
101
+ [{:node=>:whitespace, :pos=>6, :raw=>" "},
102
+ {:node=>:ident, :pos=>7, :raw=>"bar", :value=>"bar"}],
103
+ :tokens=>
104
+ [{:node=>:at_keyword, :pos=>0, :raw=>"@foo", :value=>"foo"},
105
+ {:node=>:whitespace, :pos=>4, :raw=>" "},
106
+ {:node=>:"{", :pos=>5, :raw=>"{"},
107
+ {:node=>:whitespace, :pos=>6, :raw=>" "},
108
+ {:node=>:ident, :pos=>7, :raw=>"bar", :value=>"bar"}]}
109
+ ], tree)
91
110
  end
92
111
 
93
112
  it 'unclosed, preceded by a comment' do
94
113
  tree = parse(" /**/ @foo bar{[(4")
95
- rule = tree[2]
96
-
97
- assert_equal(3, tree.size)
98
- assert_tokens(" /**/ ", tree[0..1])
99
- assert_equal(:at_rule, rule[:node])
100
- assert_equal("foo", rule[:name])
101
- assert_tokens(" bar", rule[:prelude], 10)
102
- assert_tokens("@foo bar{[(4", rule[:tokens], 6)
103
114
 
104
- block = rule[:block]
105
- assert_equal(:simple_block, block[:node])
106
- assert_equal("{", block[:start])
107
- assert_equal("}", block[:end])
108
- assert_tokens("{[(4", block[:tokens], 14)
109
- assert_equal(1, block[:value].size)
110
-
111
- block = block[:value].first
112
- assert_equal(:simple_block, block[:node])
113
- assert_equal("[", block[:start])
114
- assert_equal("]", block[:end])
115
- assert_tokens("[(4", block[:tokens], 15)
116
- assert_equal(1, block[:value].size)
117
-
118
- block = block[:value].first
119
- assert_equal(:simple_block, block[:node])
120
- assert_equal("(", block[:start])
121
- assert_equal(")", block[:end])
122
- assert_tokens("(4", block[:tokens], 16)
123
- assert_tokens("4", block[:value], 17)
115
+ assert_equal([
116
+ {:node=>:whitespace, :pos=>0, :raw=>" "},
117
+ {:node=>:whitespace, :pos=>5, :raw=>" "},
118
+ {:node=>:at_rule,
119
+ :name=>"foo",
120
+ :prelude=>
121
+ [{:node=>:whitespace, :pos=>10, :raw=>" "},
122
+ {:node=>:ident, :pos=>11, :raw=>"bar", :value=>"bar"}],
123
+ :block=>
124
+ [{:node=>:simple_block,
125
+ :start=>"[",
126
+ :end=>"]",
127
+ :value=>
128
+ [{:node=>:simple_block,
129
+ :start=>"(",
130
+ :end=>")",
131
+ :value=>
132
+ [{:node=>:number,
133
+ :pos=>17,
134
+ :raw=>"4",
135
+ :repr=>"4",
136
+ :type=>:integer,
137
+ :value=>4}],
138
+ :tokens=>
139
+ [{:node=>:"(", :pos=>16, :raw=>"("},
140
+ {:node=>:number,
141
+ :pos=>17,
142
+ :raw=>"4",
143
+ :repr=>"4",
144
+ :type=>:integer,
145
+ :value=>4}]}],
146
+ :tokens=>
147
+ [{:node=>:"[", :pos=>15, :raw=>"["},
148
+ {:node=>:"(", :pos=>16, :raw=>"("},
149
+ {:node=>:number,
150
+ :pos=>17,
151
+ :raw=>"4",
152
+ :repr=>"4",
153
+ :type=>:integer,
154
+ :value=>4}]}],
155
+ :tokens=>
156
+ [{:node=>:at_keyword, :pos=>6, :raw=>"@foo", :value=>"foo"},
157
+ {:node=>:whitespace, :pos=>10, :raw=>" "},
158
+ {:node=>:ident, :pos=>11, :raw=>"bar", :value=>"bar"},
159
+ {:node=>:"{", :pos=>14, :raw=>"{"},
160
+ {:node=>:"[", :pos=>15, :raw=>"["},
161
+ {:node=>:"(", :pos=>16, :raw=>"("},
162
+ {:node=>:number,
163
+ :pos=>17,
164
+ :raw=>"4",
165
+ :repr=>"4",
166
+ :type=>:integer,
167
+ :value=>4}]}
168
+ ], tree)
124
169
  end
125
170
 
126
171
  it 'unclosed, preceded by a comment, when :preserve_comments == true' do
127
172
  options = {:preserve_comments => true}
128
173
  tree = parse(" /**/ @foo bar{[(4", options)
129
- rule = tree[3]
130
-
131
- assert_equal(4, tree.size)
132
- assert_tokens(" /**/ ", tree[0..2], 0, options)
133
-
134
- assert_equal(:at_rule, rule[:node])
135
- assert_equal("foo", rule[:name])
136
- assert_tokens(" bar", rule[:prelude], 10, options)
137
- assert_tokens("@foo bar{[(4", rule[:tokens], 6, options)
138
174
 
139
- block = rule[:block]
140
- assert_equal(:simple_block, block[:node])
141
- assert_equal("{", block[:start])
142
- assert_equal("}", block[:end])
143
- assert_tokens("{[(4", block[:tokens], 14, options)
144
- assert_equal(1, block[:value].size)
145
-
146
- block = block[:value].first
147
- assert_equal(:simple_block, block[:node])
148
- assert_equal("[", block[:start])
149
- assert_equal("]", block[:end])
150
- assert_tokens("[(4", block[:tokens], 15, options)
151
- assert_equal(1, block[:value].size)
152
-
153
- block = block[:value].first
154
- assert_equal(:simple_block, block[:node])
155
- assert_equal("(", block[:start])
156
- assert_equal(")", block[:end])
157
- assert_tokens("(4", block[:tokens], 16, options)
158
- assert_tokens("4", block[:value], 17, options)
175
+ assert_equal([
176
+ {:node=>:whitespace, :pos=>0, :raw=>" "},
177
+ {:node=>:comment, :pos=>1, :raw=>"/**/", :value=>""},
178
+ {:node=>:whitespace, :pos=>5, :raw=>" "},
179
+ {:node=>:at_rule,
180
+ :name=>"foo",
181
+ :prelude=>
182
+ [{:node=>:whitespace, :pos=>10, :raw=>" "},
183
+ {:node=>:ident, :pos=>11, :raw=>"bar", :value=>"bar"}],
184
+ :block=>
185
+ [{:node=>:simple_block,
186
+ :start=>"[",
187
+ :end=>"]",
188
+ :value=>
189
+ [{:node=>:simple_block,
190
+ :start=>"(",
191
+ :end=>")",
192
+ :value=>
193
+ [{:node=>:number,
194
+ :pos=>17,
195
+ :raw=>"4",
196
+ :repr=>"4",
197
+ :type=>:integer,
198
+ :value=>4}],
199
+ :tokens=>
200
+ [{:node=>:"(", :pos=>16, :raw=>"("},
201
+ {:node=>:number,
202
+ :pos=>17,
203
+ :raw=>"4",
204
+ :repr=>"4",
205
+ :type=>:integer,
206
+ :value=>4}]}],
207
+ :tokens=>
208
+ [{:node=>:"[", :pos=>15, :raw=>"["},
209
+ {:node=>:"(", :pos=>16, :raw=>"("},
210
+ {:node=>:number,
211
+ :pos=>17,
212
+ :raw=>"4",
213
+ :repr=>"4",
214
+ :type=>:integer,
215
+ :value=>4}]}],
216
+ :tokens=>
217
+ [{:node=>:at_keyword, :pos=>6, :raw=>"@foo", :value=>"foo"},
218
+ {:node=>:whitespace, :pos=>10, :raw=>" "},
219
+ {:node=>:ident, :pos=>11, :raw=>"bar", :value=>"bar"},
220
+ {:node=>:"{", :pos=>14, :raw=>"{"},
221
+ {:node=>:"[", :pos=>15, :raw=>"["},
222
+ {:node=>:"(", :pos=>16, :raw=>"("},
223
+ {:node=>:number,
224
+ :pos=>17,
225
+ :raw=>"4",
226
+ :repr=>"4",
227
+ :type=>:integer,
228
+ :value=>4}]}
229
+ ], tree)
159
230
  end
160
231
 
161
232
  end
@@ -165,259 +236,131 @@ shared_tests_for 'parsing a list of rules' do
165
236
  it 'with preceding comment, selector, block, comment' do
166
237
  tree = parse(" /**/ div > p { color: #aaa; } /**/ ")
167
238
 
168
- assert_equal(5, tree.size)
169
- assert_tokens(" /**/ ", tree[0..1])
170
- assert_tokens(" /**/ ", tree[3..4], 31)
171
-
172
- rule = tree[2]
173
- assert_equal(:style_rule, rule[:node])
174
-
175
- selector = rule[:selector]
176
- assert_equal(:selector, selector[:node])
177
- assert_equal("div > p", selector[:value])
178
- assert_tokens("div > p ", selector[:tokens], 6)
179
-
180
- children = rule[:children]
181
- assert_equal(3, children.size)
182
- assert_tokens(" ", children[0], 15)
183
- assert_tokens(" ", children[2], 28)
184
-
185
- property = children[1]
186
- assert_equal(:property, property[:node])
187
- assert_equal("color", property[:name])
188
- assert_equal("#aaa", property[:value])
189
- assert_equal(false, property[:important])
190
- assert_tokens("color: #aaa;", property[:tokens], 16)
191
-
192
239
  assert_equal([
193
- {:node=>:whitespace, :pos=>22, :raw=>" "},
194
- {:node=>:hash, :pos=>23, :raw=>"#aaa", :type=>:id, :value=>"aaa"},
195
- ], property[:children])
240
+ {:node=>:whitespace, :pos=>0, :raw=>" "},
241
+ {:node=>:whitespace, :pos=>5, :raw=>" "},
242
+ {:node=>:style_rule,
243
+ :selector=>
244
+ {:node=>:selector,
245
+ :value=>"div > p",
246
+ :tokens=>
247
+ [{:node=>:ident, :pos=>6, :raw=>"div", :value=>"div"},
248
+ {:node=>:whitespace, :pos=>9, :raw=>" "},
249
+ {:node=>:delim, :pos=>10, :raw=>">", :value=>">"},
250
+ {:node=>:whitespace, :pos=>11, :raw=>" "},
251
+ {:node=>:ident, :pos=>12, :raw=>"p", :value=>"p"},
252
+ {:node=>:whitespace, :pos=>13, :raw=>" "}]},
253
+ :children=>
254
+ [{:node=>:whitespace, :pos=>15, :raw=>" "},
255
+ {:node=>:property,
256
+ :name=>"color",
257
+ :value=>"#aaa",
258
+ :children=>
259
+ [{:node=>:whitespace, :pos=>22, :raw=>" "},
260
+ {:node=>:hash, :pos=>23, :raw=>"#aaa", :type=>:id, :value=>"aaa"}],
261
+ :important=>false,
262
+ :tokens=>
263
+ [{:node=>:ident, :pos=>16, :raw=>"color", :value=>"color"},
264
+ {:node=>:colon, :pos=>21, :raw=>":"},
265
+ {:node=>:whitespace, :pos=>22, :raw=>" "},
266
+ {:node=>:hash, :pos=>23, :raw=>"#aaa", :type=>:id, :value=>"aaa"}]},
267
+ {:node=>:semicolon, :pos=>27, :raw=>";"},
268
+ {:node=>:whitespace, :pos=>28, :raw=>" "}]},
269
+ {:node=>:whitespace, :pos=>31, :raw=>" "},
270
+ {:node=>:whitespace, :pos=>36, :raw=>" "}
271
+ ], tree)
196
272
  end
197
273
 
198
274
  it 'with preceding comment, selector, block, comment, when :preserve_comments == true' do
199
275
  options = {:preserve_comments => true}
200
276
  tree = parse(" /**/ div > p { color: #aaa; } /**/ ", options)
201
277
 
202
- assert_equal(7, tree.size)
203
- assert_tokens(" /**/ ", tree[0..2], 0, options)
204
- assert_tokens(" /**/ ", tree[4..6], 31, options)
205
-
206
- rule = tree[3]
207
- assert_equal(:style_rule, rule[:node])
208
-
209
- selector = rule[:selector]
210
- assert_equal(:selector, selector[:node])
211
- assert_equal("div > p", selector[:value])
212
- assert_tokens("div > p ", selector[:tokens], 6, options)
213
-
214
- children = rule[:children]
215
- assert_equal(3, children.size)
216
- assert_tokens(" ", children[0], 15, options)
217
- assert_tokens(" ", children[2], 28, options)
218
-
219
- property = children[1]
220
- assert_equal(:property, property[:node])
221
- assert_equal("color", property[:name])
222
- assert_equal("#aaa", property[:value])
223
- assert_equal(false, property[:important])
224
- assert_tokens("color: #aaa;", property[:tokens], 16, options)
225
-
226
- assert_equal([
227
- {:node=>:whitespace, :pos=>22, :raw=>" "},
228
- {:node=>:hash, :pos=>23, :raw=>"#aaa", :type=>:id, :value=>"aaa"}
229
- ], property[:children])
230
- end
231
-
232
- it 'unclosed, with preceding comment, no selector' do
233
- tree = parse(" /**/ { color: #aaa ")
234
-
235
- assert_equal(3, tree.size)
236
- assert_tokens(" /**/ ", tree[0..1])
237
-
238
- rule = tree[2]
239
- assert_equal(:style_rule, rule[:node])
240
-
241
- selector = rule[:selector]
242
- assert_equal(:selector, selector[:node])
243
- assert_equal("", selector[:value])
244
- assert_equal([], selector[:tokens])
245
-
246
- children = rule[:children]
247
- assert_equal(2, children.size)
248
- assert_tokens(" ", children[0], 7)
249
-
250
- property = children[1]
251
- assert_equal(:property, property[:node])
252
- assert_equal("color", property[:name])
253
- assert_equal("#aaa", property[:value])
254
- assert_equal(false, property[:important])
255
- assert_tokens("color: #aaa ", property[:tokens], 8)
256
-
257
- assert_equal([
258
- {:node=>:whitespace, :pos=>14, :raw=>" "},
259
- {:node=>:hash, :pos=>15, :raw=>"#aaa", :type=>:id, :value=>"aaa"},
260
- {:node=>:whitespace, :pos=>19, :raw=>" "}
261
- ], property[:children])
262
- end
263
-
264
- it 'unclosed, with preceding comment, no selector, when :preserve_comments == true' do
265
- options = {:preserve_comments => true}
266
- tree = parse(" /**/ { color: #aaa ", options)
267
-
268
- assert_equal(4, tree.size)
269
- assert_tokens(" /**/ ", tree[0..2], 0, options)
270
-
271
- rule = tree[3]
272
- assert_equal(:style_rule, rule[:node])
273
-
274
- selector = rule[:selector]
275
- assert_equal(:selector, selector[:node])
276
- assert_equal("", selector[:value])
277
- assert_equal([], selector[:tokens])
278
-
279
- children = rule[:children]
280
- assert_equal(2, children.size)
281
- assert_tokens(" ", children[0], 7, options)
282
-
283
- property = children[1]
284
- assert_equal(:property, property[:node])
285
- assert_equal("color", property[:name])
286
- assert_equal("#aaa", property[:value])
287
- assert_equal(false, property[:important])
288
- assert_tokens("color: #aaa ", property[:tokens], 8, options)
289
-
290
278
  assert_equal([
291
- {:node=>:whitespace, :pos=>14, :raw=>" "},
292
- {:node=>:hash, :pos=>15, :raw=>"#aaa", :type=>:id, :value=>"aaa"},
293
- {:node=>:whitespace, :pos=>19, :raw=>" "}
294
- ], property[:children])
279
+ {:node=>:whitespace, :pos=>0, :raw=>" "},
280
+ {:node=>:comment, :pos=>1, :raw=>"/**/", :value=>""},
281
+ {:node=>:whitespace, :pos=>5, :raw=>" "},
282
+ {:node=>:style_rule,
283
+ :selector=>
284
+ {:node=>:selector,
285
+ :value=>"div > p",
286
+ :tokens=>
287
+ [{:node=>:ident, :pos=>6, :raw=>"div", :value=>"div"},
288
+ {:node=>:whitespace, :pos=>9, :raw=>" "},
289
+ {:node=>:delim, :pos=>10, :raw=>">", :value=>">"},
290
+ {:node=>:whitespace, :pos=>11, :raw=>" "},
291
+ {:node=>:ident, :pos=>12, :raw=>"p", :value=>"p"},
292
+ {:node=>:whitespace, :pos=>13, :raw=>" "}]},
293
+ :children=>
294
+ [{:node=>:whitespace, :pos=>15, :raw=>" "},
295
+ {:node=>:property,
296
+ :name=>"color",
297
+ :value=>"#aaa",
298
+ :children=>
299
+ [{:node=>:whitespace, :pos=>22, :raw=>" "},
300
+ {:node=>:hash, :pos=>23, :raw=>"#aaa", :type=>:id, :value=>"aaa"}],
301
+ :important=>false,
302
+ :tokens=>
303
+ [{:node=>:ident, :pos=>16, :raw=>"color", :value=>"color"},
304
+ {:node=>:colon, :pos=>21, :raw=>":"},
305
+ {:node=>:whitespace, :pos=>22, :raw=>" "},
306
+ {:node=>:hash, :pos=>23, :raw=>"#aaa", :type=>:id, :value=>"aaa"}]},
307
+ {:node=>:semicolon, :pos=>27, :raw=>";"},
308
+ {:node=>:whitespace, :pos=>28, :raw=>" "}]},
309
+ {:node=>:whitespace, :pos=>31, :raw=>" "},
310
+ {:node=>:comment, :pos=>32, :raw=>"/**/", :value=>""},
311
+ {:node=>:whitespace, :pos=>36, :raw=>" "}
312
+ ], tree)
295
313
  end
296
314
  end
297
315
 
298
- it 'should parse multiple style rules' do
299
- tree = parse("div { color: #aaa; } p{}")
300
-
301
- assert_equal(3, tree.size)
302
-
303
- rule = tree[0]
304
- assert_equal(:style_rule, rule[:node])
305
-
306
- selector = rule[:selector]
307
- assert_equal(:selector, selector[:node])
308
- assert_equal("div", selector[:value])
309
- assert_tokens("div ", selector[:tokens])
310
-
311
- children = rule[:children]
312
- assert_equal(3, children.size)
313
- assert_tokens(" ", children[0], 5)
314
- assert_tokens(" ", children[2], 18)
315
-
316
- prop = children[1]
317
- assert_equal(:property, prop[:node])
318
- assert_equal("color", prop[:name])
319
- assert_equal("#aaa", prop[:value])
320
- assert_equal(false, prop[:important])
321
- assert_tokens("color: #aaa;", prop[:tokens], 6)
322
-
323
- assert_equal([
324
- {:node=>:whitespace, :pos=>12, :raw=>" "},
325
- {:node=>:hash, :pos=>13, :raw=>"#aaa", :type=>:id, :value=>"aaa"}
326
- ], prop[:children])
327
-
328
- assert_tokens(" ", tree[1], 20)
329
-
330
- rule = tree[2]
331
- assert_equal(:style_rule, rule[:node])
332
-
333
- selector = rule[:selector]
334
- assert_equal(:selector, selector[:node])
335
- assert_equal("p", selector[:value])
336
- assert_tokens("p", selector[:tokens], 21)
337
- end
338
-
339
- it 'should ignore a block-less selector following a selector-less style rule' do
340
- tree = parse("{}a")
341
- assert_equal(1, tree.size)
342
-
343
- rule = tree[0]
344
- assert_equal(:style_rule, rule[:node])
345
- assert_equal([], rule[:children])
346
-
347
- selector = rule[:selector]
348
- assert_equal(:selector, selector[:node])
349
- assert_equal("", selector[:value])
350
- assert_equal([], selector[:tokens])
351
- end
352
-
353
- it 'should handle an at-rule following a selector-less style rule' do
354
- tree = parse("{}@a")
355
- assert_equal(2, tree.size)
356
-
357
- rule = tree[0]
358
- assert_equal(:style_rule, rule[:node])
359
- assert_equal([], rule[:children])
360
-
361
- selector = rule[:selector]
362
- assert_equal(:selector, selector[:node])
363
- assert_equal("", selector[:value])
364
- assert_equal([], selector[:tokens])
365
-
366
- rule = tree[1]
367
- assert_equal(:at_rule, rule[:node])
368
- assert_equal("a", rule[:name])
369
- assert_equal([], rule[:prelude])
370
- assert_tokens("@a", rule[:tokens], 2)
371
- end
372
-
373
316
  it 'should parse property values containing functions' do
374
317
  tree = parse("p:before { content: a\\ttr(data-foo) \" \"; }")
375
318
 
376
319
  assert_equal([
377
320
  {:node=>:style_rule,
378
- :selector=>
379
- {:node=>:selector,
380
- :value=>"p:before",
381
- :tokens=>
382
- [{:node=>:ident, :pos=>0, :raw=>"p", :value=>"p"},
383
- {:node=>:colon, :pos=>1, :raw=>":"},
384
- {:node=>:ident, :pos=>2, :raw=>"before", :value=>"before"},
385
- {:node=>:whitespace, :pos=>8, :raw=>" "}]},
386
- :children=>
387
- [{:node=>:whitespace, :pos=>10, :raw=>" "},
388
- {:node=>:property,
389
- :name=>"content",
390
- :value=>"attr(data-foo) \" \"",
391
- :important=>false,
392
- :children=>
393
- [{:node=>:whitespace, :pos=>19, :raw=>" "},
394
- {:node=>:function,
395
- :name=>"attr",
396
- :value=>
397
- [{:node=>:ident, :pos=>26, :raw=>"data-foo", :value=>"data-foo"}],
398
- :tokens=>
399
- [{:node=>:function, :pos=>20, :raw=>"a\\ttr(", :value=>"attr"},
400
- {:node=>:ident, :pos=>26, :raw=>"data-foo", :value=>"data-foo"},
401
- {:node=>:")", :pos=>34, :raw=>")"}]},
402
- {:node=>:whitespace, :pos=>35, :raw=>" "},
403
- {:node=>:string, :pos=>36, :raw=>"\" \"", :value=>" "}],
321
+ :selector=>
322
+ {:node=>:selector,
323
+ :value=>"p:before",
404
324
  :tokens=>
405
- [{:node=>:ident, :pos=>11, :raw=>"content", :value=>"content"},
406
- {:node=>:colon, :pos=>18, :raw=>":"},
407
- {:node=>:whitespace, :pos=>19, :raw=>" "},
408
- {:node=>:function,
409
- :name=>"attr",
410
- :value=>
411
- [{:node=>:ident, :pos=>26, :raw=>"data-foo", :value=>"data-foo"}],
412
- :tokens=>
413
- [{:node=>:function, :pos=>20, :raw=>"a\\ttr(", :value=>"attr"},
414
- {:node=>:ident, :pos=>26, :raw=>"data-foo", :value=>"data-foo"},
415
- {:node=>:")", :pos=>34, :raw=>")"}]},
416
- {:node=>:whitespace, :pos=>35, :raw=>" "},
417
- {:node=>:string, :pos=>36, :raw=>"\" \"", :value=>" "},
418
- {:node=>:semicolon, :pos=>39, :raw=>";"}]},
419
- {:node=>:whitespace, :pos=>40, :raw=>" "}]}
420
- ], tree)
325
+ [{:node=>:ident, :pos=>0, :raw=>"p", :value=>"p"},
326
+ {:node=>:colon, :pos=>1, :raw=>":"},
327
+ {:node=>:ident, :pos=>2, :raw=>"before", :value=>"before"},
328
+ {:node=>:whitespace, :pos=>8, :raw=>" "}]},
329
+ :children=>
330
+ [{:node=>:whitespace, :pos=>10, :raw=>" "},
331
+ {:node=>:property,
332
+ :name=>"content",
333
+ :value=>"attr(data-foo) \" \"",
334
+ :children=>
335
+ [{:node=>:whitespace, :pos=>19, :raw=>" "},
336
+ {:node=>:function,
337
+ :name=>"attr",
338
+ :value=>
339
+ [{:node=>:ident, :pos=>26, :raw=>"data-foo", :value=>"data-foo"}],
340
+ :tokens=>
341
+ [{:node=>:function, :pos=>20, :raw=>"a\\ttr(", :value=>"attr"},
342
+ {:node=>:ident, :pos=>26, :raw=>"data-foo", :value=>"data-foo"},
343
+ {:node=>:")", :pos=>34, :raw=>")"}]},
344
+ {:node=>:whitespace, :pos=>35, :raw=>" "},
345
+ {:node=>:string, :pos=>36, :raw=>"\" \"", :value=>" "}],
346
+ :important=>false,
347
+ :tokens=>
348
+ [{:node=>:ident, :pos=>11, :raw=>"content", :value=>"content"},
349
+ {:node=>:colon, :pos=>18, :raw=>":"},
350
+ {:node=>:whitespace, :pos=>19, :raw=>" "},
351
+ {:node=>:function,
352
+ :name=>"attr",
353
+ :value=>
354
+ [{:node=>:ident, :pos=>26, :raw=>"data-foo", :value=>"data-foo"}],
355
+ :tokens=>
356
+ [{:node=>:function, :pos=>20, :raw=>"a\\ttr(", :value=>"attr"},
357
+ {:node=>:ident, :pos=>26, :raw=>"data-foo", :value=>"data-foo"},
358
+ {:node=>:")", :pos=>34, :raw=>")"}]},
359
+ {:node=>:whitespace, :pos=>35, :raw=>" "},
360
+ {:node=>:string, :pos=>36, :raw=>"\" \"", :value=>" "}]},
361
+ {:node=>:semicolon, :pos=>39, :raw=>";"},
362
+ {:node=>:whitespace, :pos=>40, :raw=>" "}]}
363
+ ], tree)
421
364
  end
422
365
 
423
366
  it 'should parse property values containing nested functions' do
@@ -425,96 +368,96 @@ shared_tests_for 'parsing a list of rules' do
425
368
 
426
369
  assert_equal([
427
370
  {:node=>:style_rule,
428
- :selector=>
429
- {:node=>:selector,
430
- :value=>"div",
431
- :tokens=>
432
- [{:node=>:ident, :pos=>0, :raw=>"div", :value=>"div"},
433
- {:node=>:whitespace, :pos=>3, :raw=>" "}]},
434
- :children=>
435
- [{:node=>:whitespace, :pos=>5, :raw=>" "},
436
- {:node=>:property,
437
- :name=>"width",
438
- :value=>"expression(alert(1))",
439
- :important=>false,
440
- :children=>
441
- [{:node=>:whitespace, :pos=>12, :raw=>" "},
442
- {:node=>:function,
443
- :name=>"expression",
444
- :value=>
445
- [{:node=>:function,
446
- :name=>"alert",
447
- :value=>
448
- [{:node=>:number,
449
- :pos=>33,
450
- :raw=>"1",
451
- :repr=>"1",
452
- :type=>:integer,
453
- :value=>1}],
454
- :tokens=>
455
- [{:node=>:function, :pos=>27, :raw=>"alert(", :value=>"alert"},
456
- {:node=>:number,
457
- :pos=>33,
458
- :raw=>"1",
459
- :repr=>"1",
460
- :type=>:integer,
461
- :value=>1},
462
- {:node=>:")", :pos=>34, :raw=>")"}]}],
463
- :tokens=>
464
- [{:node=>:function,
465
- :pos=>13,
466
- :raw=>"e\\78 pression(",
467
- :value=>"expression"},
468
- {:node=>:function, :pos=>27, :raw=>"alert(", :value=>"alert"},
469
- {:node=>:number,
470
- :pos=>33,
471
- :raw=>"1",
472
- :repr=>"1",
473
- :type=>:integer,
474
- :value=>1},
475
- {:node=>:")", :pos=>34, :raw=>")"},
476
- {:node=>:")", :pos=>35, :raw=>")"}]}],
371
+ :selector=>
372
+ {:node=>:selector,
373
+ :value=>"div",
477
374
  :tokens=>
478
- [{:node=>:ident, :pos=>6, :raw=>"width", :value=>"width"},
479
- {:node=>:colon, :pos=>11, :raw=>":"},
480
- {:node=>:whitespace, :pos=>12, :raw=>" "},
481
- {:node=>:function,
482
- :name=>"expression",
483
- :value=>
484
- [{:node=>:function,
485
- :name=>"alert",
486
- :value=>
487
- [{:node=>:number,
488
- :pos=>33,
489
- :raw=>"1",
490
- :repr=>"1",
491
- :type=>:integer,
492
- :value=>1}],
493
- :tokens=>
494
- [{:node=>:function, :pos=>27, :raw=>"alert(", :value=>"alert"},
495
- {:node=>:number,
496
- :pos=>33,
497
- :raw=>"1",
498
- :repr=>"1",
499
- :type=>:integer,
500
- :value=>1},
501
- {:node=>:")", :pos=>34, :raw=>")"}]}],
502
- :tokens=>
503
- [{:node=>:function,
504
- :pos=>13,
505
- :raw=>"e\\78 pression(",
506
- :value=>"expression"},
507
- {:node=>:function, :pos=>27, :raw=>"alert(", :value=>"alert"},
508
- {:node=>:number,
509
- :pos=>33,
510
- :raw=>"1",
511
- :repr=>"1",
512
- :type=>:integer,
513
- :value=>1},
514
- {:node=>:")", :pos=>34, :raw=>")"},
515
- {:node=>:")", :pos=>35, :raw=>")"}]},
516
- {:node=>:semicolon, :pos=>36, :raw=>";"}]},
517
- {:node=>:whitespace, :pos=>37, :raw=>" "}]}
375
+ [{:node=>:ident, :pos=>0, :raw=>"div", :value=>"div"},
376
+ {:node=>:whitespace, :pos=>3, :raw=>" "}]},
377
+ :children=>
378
+ [{:node=>:whitespace, :pos=>5, :raw=>" "},
379
+ {:node=>:property,
380
+ :name=>"width",
381
+ :value=>"expression(alert(1))",
382
+ :children=>
383
+ [{:node=>:whitespace, :pos=>12, :raw=>" "},
384
+ {:node=>:function,
385
+ :name=>"expression",
386
+ :value=>
387
+ [{:node=>:function,
388
+ :name=>"alert",
389
+ :value=>
390
+ [{:node=>:number,
391
+ :pos=>33,
392
+ :raw=>"1",
393
+ :repr=>"1",
394
+ :type=>:integer,
395
+ :value=>1}],
396
+ :tokens=>
397
+ [{:node=>:function, :pos=>27, :raw=>"alert(", :value=>"alert"},
398
+ {:node=>:number,
399
+ :pos=>33,
400
+ :raw=>"1",
401
+ :repr=>"1",
402
+ :type=>:integer,
403
+ :value=>1},
404
+ {:node=>:")", :pos=>34, :raw=>")"}]}],
405
+ :tokens=>
406
+ [{:node=>:function,
407
+ :pos=>13,
408
+ :raw=>"e\\78 pression(",
409
+ :value=>"expression"},
410
+ {:node=>:function, :pos=>27, :raw=>"alert(", :value=>"alert"},
411
+ {:node=>:number,
412
+ :pos=>33,
413
+ :raw=>"1",
414
+ :repr=>"1",
415
+ :type=>:integer,
416
+ :value=>1},
417
+ {:node=>:")", :pos=>34, :raw=>")"},
418
+ {:node=>:")", :pos=>35, :raw=>")"}]}],
419
+ :important=>false,
420
+ :tokens=>
421
+ [{:node=>:ident, :pos=>6, :raw=>"width", :value=>"width"},
422
+ {:node=>:colon, :pos=>11, :raw=>":"},
423
+ {:node=>:whitespace, :pos=>12, :raw=>" "},
424
+ {:node=>:function,
425
+ :name=>"expression",
426
+ :value=>
427
+ [{:node=>:function,
428
+ :name=>"alert",
429
+ :value=>
430
+ [{:node=>:number,
431
+ :pos=>33,
432
+ :raw=>"1",
433
+ :repr=>"1",
434
+ :type=>:integer,
435
+ :value=>1}],
436
+ :tokens=>
437
+ [{:node=>:function, :pos=>27, :raw=>"alert(", :value=>"alert"},
438
+ {:node=>:number,
439
+ :pos=>33,
440
+ :raw=>"1",
441
+ :repr=>"1",
442
+ :type=>:integer,
443
+ :value=>1},
444
+ {:node=>:")", :pos=>34, :raw=>")"}]}],
445
+ :tokens=>
446
+ [{:node=>:function,
447
+ :pos=>13,
448
+ :raw=>"e\\78 pression(",
449
+ :value=>"expression"},
450
+ {:node=>:function, :pos=>27, :raw=>"alert(", :value=>"alert"},
451
+ {:node=>:number,
452
+ :pos=>33,
453
+ :raw=>"1",
454
+ :repr=>"1",
455
+ :type=>:integer,
456
+ :value=>1},
457
+ {:node=>:")", :pos=>34, :raw=>")"},
458
+ {:node=>:")", :pos=>35, :raw=>")"}]}]},
459
+ {:node=>:semicolon, :pos=>36, :raw=>";"},
460
+ {:node=>:whitespace, :pos=>37, :raw=>" "}]}
518
461
  ], tree)
519
462
  end
520
463
  end