crass 0.1.0 → 0.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.
- checksums.yaml +8 -8
- data/HISTORY.md +14 -0
- data/README.md +50 -40
- data/lib/crass/parser.rb +42 -20
- data/lib/crass/version.rb +1 -1
- data/test/shared/parse_rules.rb +175 -0
- data/test/test_parse_properties.rb +88 -0
- data/test/test_parse_rules.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MDM3ZDU2Y2U1NDBkNGQxMDQwMzNhNGM1YTRjM2UyM2RjMTA5MGU5MA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YTMyMDVkZTViMjEyNjVlMGJkNjE2N2M0MWRhYmQ3Mzc3NGU0YzE3Mg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZDkwYmUyNGVkZjA5NGMwOWRlNzVlYmIwMmM5NjJlMDYxYWYxMzE0YzE2YWNl
|
10
|
+
MTYwZDU4MzZmMTkwZGVmMDk3ODI4MTMwZmE0NWQ3Y2M5ODE1MTllYjhlZWI2
|
11
|
+
NmQxMjExYmEzMmI1MTQzOWExOTk1Yjg0NjlkODNiYzM5ZDIwZjk=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
OTQ4N2Y4MWNiYjQzNTdlN2MzMDVjMTRhY2U2NjE4YzczNDgwMzVhYzQ5ODcy
|
14
|
+
NjMwYTRhZmNiOTc5ZjViMjgyYzlhZThkOWU2Yjc5ODI4YTJlNDUzNmQ1ODAy
|
15
|
+
MTQ2YTA2ZDhmZWUzNDMwNDk2NjQ2MDk4OTBmNmI5NDdmOTNlNzE=
|
data/HISTORY.md
CHANGED
@@ -1,6 +1,20 @@
|
|
1
1
|
Crass Change History
|
2
2
|
====================
|
3
3
|
|
4
|
+
0.2.0 (2013-10-10)
|
5
|
+
------------------
|
6
|
+
|
7
|
+
* Added a `:children` field to `:property` nodes. It's an array containing all
|
8
|
+
the nodes that make up the property's value.
|
9
|
+
|
10
|
+
* Fixed: Incorrect value was given for `:property` nodes whose values contained
|
11
|
+
functions.
|
12
|
+
|
13
|
+
* Fixed: When parsing the value of an at-rule's block as a list of rules, a
|
14
|
+
selector containing a function (such as "#foo:not(.bar)") would cause that
|
15
|
+
property and the rest of the token stream to be discarded.
|
16
|
+
|
17
|
+
|
4
18
|
0.1.0 (2013-10-04)
|
5
19
|
------------------
|
6
20
|
|
data/README.md
CHANGED
@@ -83,47 +83,57 @@ This returns a big fat ugly parse tree, which looks like this:
|
|
83
83
|
```ruby
|
84
84
|
[{:node=>:comment, :pos=>0, :raw=>"/* Comment! */", :value=>" Comment! "},
|
85
85
|
{:node=>:whitespace, :pos=>14, :raw=>"\n"},
|
86
|
-
{:node=>:
|
87
|
-
:
|
88
|
-
|
89
|
-
:value=>"a:hover",
|
90
|
-
:tokens=>
|
91
|
-
[{:node=>:ident, :pos=>15, :raw=>"a", :value=>"a"},
|
92
|
-
{:node=>:colon, :pos=>16, :raw=>":"},
|
93
|
-
{:node=>:ident, :pos=>17, :raw=>"hover", :value=>"hover"},
|
94
|
-
{:node=>:whitespace, :pos=>22, :raw=>" "}]},
|
86
|
+
{:node=>:property,
|
87
|
+
:name=>"a",
|
88
|
+
:value=>"hover {\n color: #0d8bfa",
|
95
89
|
:children=>
|
96
|
-
[{:node=>:
|
97
|
-
{:node=>:
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
{:node=>:
|
112
|
-
{:node=>:
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
{:node=>:
|
90
|
+
[{:node=>:ident, :pos=>17, :raw=>"hover", :value=>"hover"},
|
91
|
+
{:node=>:whitespace, :pos=>22, :raw=>" "},
|
92
|
+
{:node=>:"{", :pos=>23, :raw=>"{"},
|
93
|
+
{:node=>:whitespace, :pos=>24, :raw=>"\n "},
|
94
|
+
{:node=>:ident, :pos=>27, :raw=>"color", :value=>"color"},
|
95
|
+
{:node=>:colon, :pos=>32, :raw=>":"},
|
96
|
+
{:node=>:whitespace, :pos=>33, :raw=>" "},
|
97
|
+
{:node=>:hash,
|
98
|
+
:pos=>34,
|
99
|
+
:raw=>"#0d8bfa",
|
100
|
+
:type=>:unrestricted,
|
101
|
+
:value=>"0d8bfa"}],
|
102
|
+
:important=>false,
|
103
|
+
:tokens=>
|
104
|
+
[{:node=>:ident, :pos=>15, :raw=>"a", :value=>"a"},
|
105
|
+
{:node=>:colon, :pos=>16, :raw=>":"},
|
106
|
+
{:node=>:ident, :pos=>17, :raw=>"hover", :value=>"hover"},
|
107
|
+
{:node=>:whitespace, :pos=>22, :raw=>" "},
|
108
|
+
{:node=>:"{", :pos=>23, :raw=>"{"},
|
109
|
+
{:node=>:whitespace, :pos=>24, :raw=>"\n "},
|
110
|
+
{:node=>:ident, :pos=>27, :raw=>"color", :value=>"color"},
|
111
|
+
{:node=>:colon, :pos=>32, :raw=>":"},
|
112
|
+
{:node=>:whitespace, :pos=>33, :raw=>" "},
|
113
|
+
{:node=>:hash,
|
114
|
+
:pos=>34,
|
115
|
+
:raw=>"#0d8bfa",
|
116
|
+
:type=>:unrestricted,
|
117
|
+
:value=>"0d8bfa"},
|
118
|
+
{:node=>:semicolon, :pos=>41, :raw=>";"}]},
|
119
|
+
{:node=>:whitespace, :pos=>42, :raw=>"\n "},
|
120
|
+
{:node=>:property,
|
121
|
+
:name=>"text-decoration",
|
122
|
+
:value=>"underline",
|
123
|
+
:children=>
|
124
|
+
[{:node=>:whitespace, :pos=>61, :raw=>" "},
|
125
|
+
{:node=>:ident, :pos=>62, :raw=>"underline", :value=>"underline"}],
|
126
|
+
:important=>false,
|
127
|
+
:tokens=>
|
128
|
+
[{:node=>:ident,
|
129
|
+
:pos=>45,
|
130
|
+
:raw=>"text-decoration",
|
131
|
+
:value=>"text-decoration"},
|
132
|
+
{:node=>:colon, :pos=>60, :raw=>":"},
|
133
|
+
{:node=>:whitespace, :pos=>61, :raw=>" "},
|
134
|
+
{:node=>:ident, :pos=>62, :raw=>"underline", :value=>"underline"},
|
135
|
+
{:node=>:semicolon, :pos=>71, :raw=>";"}]},
|
136
|
+
{:node=>:whitespace, :pos=>72, :raw=>"\n"}]
|
127
137
|
```
|
128
138
|
|
129
139
|
If you want, you can stringify the parse tree:
|
data/lib/crass/parser.rb
CHANGED
@@ -26,7 +26,7 @@ module Crass
|
|
26
26
|
Parser.new(input, options).parse_properties
|
27
27
|
end
|
28
28
|
|
29
|
-
# Parses
|
29
|
+
# Parses CSS rules (such as the content of a `@media` block) and returns a
|
30
30
|
# parse tree. The only difference from {#parse_stylesheet} is that CDO/CDC
|
31
31
|
# nodes (`<!--` and `-->`) aren't ignored.
|
32
32
|
#
|
@@ -143,10 +143,13 @@ module Crass
|
|
143
143
|
|
144
144
|
while token = input.consume
|
145
145
|
case token[:node]
|
146
|
-
when :comment
|
147
|
-
|
146
|
+
when :comment
|
147
|
+
next
|
148
148
|
|
149
|
-
when :
|
149
|
+
when :semicolon
|
150
|
+
break
|
151
|
+
|
152
|
+
when :'{'
|
150
153
|
rule[:block] = consume_simple_block(input)
|
151
154
|
break
|
152
155
|
|
@@ -171,14 +174,24 @@ module Crass
|
|
171
174
|
|
172
175
|
# Consumes a component value and returns it.
|
173
176
|
#
|
174
|
-
# http://www.w3.org/TR/2013/WD-css-syntax-3-20130919/#consume-a-component-
|
177
|
+
# http://www.w3.org/TR/2013/WD-css-syntax-3-20130919/#consume-a-component-value
|
175
178
|
def consume_component_value(input = @tokens)
|
176
179
|
return nil unless token = input.consume
|
177
180
|
|
178
181
|
case token[:node]
|
179
|
-
when :'{', :'[', :'('
|
180
|
-
|
181
|
-
|
182
|
+
when :'{', :'[', :'('
|
183
|
+
consume_simple_block(input)
|
184
|
+
|
185
|
+
when :function
|
186
|
+
if token.key?(:name)
|
187
|
+
# This is a parsed function, not a function token.
|
188
|
+
token
|
189
|
+
else
|
190
|
+
consume_function(input)
|
191
|
+
end
|
192
|
+
|
193
|
+
else
|
194
|
+
token
|
182
195
|
end
|
183
196
|
end
|
184
197
|
|
@@ -291,18 +304,21 @@ module Crass
|
|
291
304
|
:tokens => [input.current]
|
292
305
|
}
|
293
306
|
|
294
|
-
function[:tokens].concat(input.collect
|
307
|
+
function[:tokens].concat(input.collect {
|
295
308
|
while token = input.consume
|
296
309
|
case token[:node]
|
297
|
-
when :')'
|
298
|
-
|
310
|
+
when :')'
|
311
|
+
break
|
312
|
+
|
313
|
+
when :comment
|
314
|
+
next
|
299
315
|
|
300
316
|
else
|
301
317
|
input.reconsume
|
302
318
|
function[:value] << consume_component_value(input)
|
303
319
|
end
|
304
320
|
end
|
305
|
-
|
321
|
+
})
|
306
322
|
|
307
323
|
create_node(:function, function)
|
308
324
|
end
|
@@ -340,12 +356,10 @@ module Crass
|
|
340
356
|
def consume_rules(flags = {})
|
341
357
|
rules = []
|
342
358
|
|
343
|
-
while
|
344
|
-
return rules unless token = @tokens.consume
|
345
|
-
|
359
|
+
while token = @tokens.consume
|
346
360
|
case token[:node]
|
347
|
-
when :comment, :whitespace
|
348
|
-
|
361
|
+
when :comment, :whitespace
|
362
|
+
rules << token
|
349
363
|
|
350
364
|
when :cdc, :cdo
|
351
365
|
unless flags[:top_level]
|
@@ -365,6 +379,8 @@ module Crass
|
|
365
379
|
rules << rule if rule
|
366
380
|
end
|
367
381
|
end
|
382
|
+
|
383
|
+
rules
|
368
384
|
end
|
369
385
|
|
370
386
|
# Consumes and returns a simple block associated with the current input
|
@@ -384,7 +400,7 @@ module Crass
|
|
384
400
|
|
385
401
|
block[:tokens].concat(input.collect do
|
386
402
|
while token = input.consume
|
387
|
-
break if token[:node] == end_token
|
403
|
+
break if token[:node] == end_token
|
388
404
|
|
389
405
|
input.reconsume
|
390
406
|
block[:value] << consume_component_value(input)
|
@@ -435,9 +451,13 @@ module Crass
|
|
435
451
|
next
|
436
452
|
end
|
437
453
|
|
454
|
+
children = decl[:value].dup
|
455
|
+
children.pop if children.last[:node] == :semicolon
|
456
|
+
|
438
457
|
properties << create_node(:property,
|
439
458
|
:name => decl[:name],
|
440
459
|
:value => parse_value(decl[:value]),
|
460
|
+
:children => children,
|
441
461
|
:important => decl[:important] == true,
|
442
462
|
:tokens => decl[:tokens])
|
443
463
|
end
|
@@ -452,7 +472,8 @@ module Crass
|
|
452
472
|
|
453
473
|
nodes.each do |node|
|
454
474
|
case node[:node]
|
455
|
-
when :comment, :semicolon
|
475
|
+
when :comment, :semicolon
|
476
|
+
next
|
456
477
|
|
457
478
|
when :at_keyword, :ident
|
458
479
|
string << node[:value]
|
@@ -460,8 +481,9 @@ module Crass
|
|
460
481
|
when :function
|
461
482
|
if node[:value].is_a?(String)
|
462
483
|
string << node[:value]
|
484
|
+
string << '('
|
463
485
|
else
|
464
|
-
string << parse_value(node[:
|
486
|
+
string << parse_value(node[:tokens])
|
465
487
|
end
|
466
488
|
|
467
489
|
else
|
data/lib/crass/version.rb
CHANGED
data/test/shared/parse_rules.rb
CHANGED
@@ -188,6 +188,11 @@ shared_tests_for 'parsing a list of rules' do
|
|
188
188
|
assert_equal("#aaa", property[:value])
|
189
189
|
assert_equal(false, property[:important])
|
190
190
|
assert_tokens("color: #aaa;", property[:tokens], 16)
|
191
|
+
|
192
|
+
assert_equal([
|
193
|
+
{:node=>:whitespace, :pos=>22, :raw=>" "},
|
194
|
+
{:node=>:hash, :pos=>23, :raw=>"#aaa", :type=>:id, :value=>"aaa"},
|
195
|
+
], property[:children])
|
191
196
|
end
|
192
197
|
|
193
198
|
it 'with preceding comment, selector, block, comment, when :preserve_comments == true' do
|
@@ -217,6 +222,11 @@ shared_tests_for 'parsing a list of rules' do
|
|
217
222
|
assert_equal("#aaa", property[:value])
|
218
223
|
assert_equal(false, property[:important])
|
219
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])
|
220
230
|
end
|
221
231
|
|
222
232
|
it 'unclosed, with preceding comment, no selector' do
|
@@ -243,6 +253,12 @@ shared_tests_for 'parsing a list of rules' do
|
|
243
253
|
assert_equal("#aaa", property[:value])
|
244
254
|
assert_equal(false, property[:important])
|
245
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])
|
246
262
|
end
|
247
263
|
|
248
264
|
it 'unclosed, with preceding comment, no selector, when :preserve_comments == true' do
|
@@ -270,6 +286,12 @@ shared_tests_for 'parsing a list of rules' do
|
|
270
286
|
assert_equal("#aaa", property[:value])
|
271
287
|
assert_equal(false, property[:important])
|
272
288
|
assert_tokens("color: #aaa ", property[:tokens], 8, options)
|
289
|
+
|
290
|
+
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])
|
273
295
|
end
|
274
296
|
end
|
275
297
|
|
@@ -298,6 +320,11 @@ shared_tests_for 'parsing a list of rules' do
|
|
298
320
|
assert_equal(false, prop[:important])
|
299
321
|
assert_tokens("color: #aaa;", prop[:tokens], 6)
|
300
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
|
+
|
301
328
|
assert_tokens(" ", tree[1], 20)
|
302
329
|
|
303
330
|
rule = tree[2]
|
@@ -342,4 +369,152 @@ shared_tests_for 'parsing a list of rules' do
|
|
342
369
|
assert_equal([], rule[:prelude])
|
343
370
|
assert_tokens("@a", rule[:tokens], 2)
|
344
371
|
end
|
372
|
+
|
373
|
+
it 'should parse property values containing functions' do
|
374
|
+
tree = parse("p:before { content: a\\ttr(data-foo) \" \"; }")
|
375
|
+
|
376
|
+
assert_equal([
|
377
|
+
{: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=>" "}],
|
404
|
+
: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)
|
421
|
+
end
|
422
|
+
|
423
|
+
it 'should parse property values containing nested functions' do
|
424
|
+
tree = parse("div { width: e\\78 pression(alert(1)); }")
|
425
|
+
|
426
|
+
assert_equal([
|
427
|
+
{: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=>")"}]}],
|
477
|
+
: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=>" "}]}
|
518
|
+
], tree)
|
519
|
+
end
|
345
520
|
end
|
@@ -40,6 +40,10 @@ describe 'Crass::Parser' do
|
|
40
40
|
assert_equal(false, prop[:important])
|
41
41
|
assert_tokens("a:b;", prop[:tokens])
|
42
42
|
|
43
|
+
assert_equal([
|
44
|
+
{:node=>:ident, :pos=>2, :raw=>"b", :value=>"b"}
|
45
|
+
], prop[:children])
|
46
|
+
|
43
47
|
assert_tokens(" ", tree[1], 4)
|
44
48
|
|
45
49
|
prop = tree[2]
|
@@ -49,6 +53,17 @@ describe 'Crass::Parser' do
|
|
49
53
|
assert_equal(true, prop[:important])
|
50
54
|
assert_tokens("c:d 42!important;", prop[:tokens], 5)
|
51
55
|
|
56
|
+
assert_equal([
|
57
|
+
{:node=>:ident, :pos=>7, :raw=>"d", :value=>"d"},
|
58
|
+
{:node=>:whitespace, :pos=>8, :raw=>" "},
|
59
|
+
{:node=>:number,
|
60
|
+
:pos=>9,
|
61
|
+
:raw=>"42",
|
62
|
+
:repr=>"42",
|
63
|
+
:type=>:integer,
|
64
|
+
:value=>42}
|
65
|
+
], prop[:children])
|
66
|
+
|
52
67
|
assert_tokens("\n", tree[3], 22)
|
53
68
|
end
|
54
69
|
|
@@ -71,6 +86,10 @@ describe 'Crass::Parser' do
|
|
71
86
|
assert_equal(false, prop[:important])
|
72
87
|
assert_tokens("a:b;", prop[:tokens], 19)
|
73
88
|
|
89
|
+
assert_equal([
|
90
|
+
{:node=>:ident, :pos=>21, :raw=>"b", :value=>"b"}
|
91
|
+
], prop[:children])
|
92
|
+
|
74
93
|
assert_tokens(" ", tree[3], 23)
|
75
94
|
|
76
95
|
rule = tree[4]
|
@@ -115,6 +134,9 @@ describe 'Crass::Parser' do
|
|
115
134
|
assert_equal("b", prop[:value])
|
116
135
|
assert_equal(false, prop[:important])
|
117
136
|
assert_tokens("a:b;", prop[:tokens], 24)
|
137
|
+
assert_equal([
|
138
|
+
{:node=>:ident, :pos=>26, :raw=>"b", :value=>"b"}
|
139
|
+
], prop[:children])
|
118
140
|
|
119
141
|
assert_tokens("; ", tree[3..4], 28)
|
120
142
|
|
@@ -171,5 +193,71 @@ describe 'Crass::Parser' do
|
|
171
193
|
assert_equal([], block[:value])
|
172
194
|
assert_tokens("{", block[:tokens], 47)
|
173
195
|
end
|
196
|
+
|
197
|
+
it 'should parse values containing functions' do
|
198
|
+
tree = parse("content: attr(data-foo) \" \";")
|
199
|
+
|
200
|
+
assert_equal([
|
201
|
+
{:node=>:property,
|
202
|
+
:name=>"content",
|
203
|
+
:value=>"attr(data-foo) \" \"",
|
204
|
+
:important=>false,
|
205
|
+
:children=>
|
206
|
+
[{:node=>:whitespace, :pos=>8, :raw=>" "},
|
207
|
+
{:node=>:function, :pos=>9, :raw=>"attr(", :value=>"attr"},
|
208
|
+
{:node=>:ident, :pos=>14, :raw=>"data-foo", :value=>"data-foo"},
|
209
|
+
{:node=>:")", :pos=>22, :raw=>")"},
|
210
|
+
{:node=>:whitespace, :pos=>23, :raw=>" "},
|
211
|
+
{:node=>:string, :pos=>24, :raw=>"\" \"", :value=>" "}],
|
212
|
+
:tokens=>
|
213
|
+
[{:node=>:ident, :pos=>0, :raw=>"content", :value=>"content"},
|
214
|
+
{:node=>:colon, :pos=>7, :raw=>":"},
|
215
|
+
{:node=>:whitespace, :pos=>8, :raw=>" "},
|
216
|
+
{:node=>:function, :pos=>9, :raw=>"attr(", :value=>"attr"},
|
217
|
+
{:node=>:ident, :pos=>14, :raw=>"data-foo", :value=>"data-foo"},
|
218
|
+
{:node=>:")", :pos=>22, :raw=>")"},
|
219
|
+
{:node=>:whitespace, :pos=>23, :raw=>" "},
|
220
|
+
{:node=>:string, :pos=>24, :raw=>"\" \"", :value=>" "},
|
221
|
+
{:node=>:semicolon, :pos=>27, :raw=>";"}]}
|
222
|
+
], tree)
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'should parse values containing nested functions' do
|
226
|
+
tree = parse("width: expression(alert(1));")
|
227
|
+
|
228
|
+
assert_equal([
|
229
|
+
{:node=>:property,
|
230
|
+
:name=>"width",
|
231
|
+
:value=>"expression(alert(1))",
|
232
|
+
:important=>false,
|
233
|
+
:children=>
|
234
|
+
[{:node=>:whitespace, :pos=>6, :raw=>" "},
|
235
|
+
{:node=>:function, :pos=>7, :raw=>"expression(", :value=>"expression"},
|
236
|
+
{:node=>:function, :pos=>18, :raw=>"alert(", :value=>"alert"},
|
237
|
+
{:node=>:number,
|
238
|
+
:pos=>24,
|
239
|
+
:raw=>"1",
|
240
|
+
:repr=>"1",
|
241
|
+
:type=>:integer,
|
242
|
+
:value=>1},
|
243
|
+
{:node=>:")", :pos=>25, :raw=>")"},
|
244
|
+
{:node=>:")", :pos=>26, :raw=>")"}],
|
245
|
+
:tokens=>
|
246
|
+
[{:node=>:ident, :pos=>0, :raw=>"width", :value=>"width"},
|
247
|
+
{:node=>:colon, :pos=>5, :raw=>":"},
|
248
|
+
{:node=>:whitespace, :pos=>6, :raw=>" "},
|
249
|
+
{:node=>:function, :pos=>7, :raw=>"expression(", :value=>"expression"},
|
250
|
+
{:node=>:function, :pos=>18, :raw=>"alert(", :value=>"alert"},
|
251
|
+
{:node=>:number,
|
252
|
+
:pos=>24,
|
253
|
+
:raw=>"1",
|
254
|
+
:repr=>"1",
|
255
|
+
:type=>:integer,
|
256
|
+
:value=>1},
|
257
|
+
{:node=>:")", :pos=>25, :raw=>")"},
|
258
|
+
{:node=>:")", :pos=>26, :raw=>")"},
|
259
|
+
{:node=>:semicolon, :pos=>27, :raw=>";"}]}
|
260
|
+
], tree)
|
261
|
+
end
|
174
262
|
end
|
175
263
|
end
|
data/test/test_parse_rules.rb
CHANGED
@@ -52,12 +52,12 @@ describe 'Crass::Parser' do
|
|
52
52
|
end
|
53
53
|
|
54
54
|
it 'should parse the block of an at-rule' do
|
55
|
-
rule = CP.parse_stylesheet("@media (max-width: 400px) {.
|
55
|
+
rule = CP.parse_stylesheet("@media (max-width: 400px) {#foo:not(.bar){color:#fff;}}")[0]
|
56
56
|
assert_equal(:at_rule, rule[:node])
|
57
57
|
|
58
58
|
style_rule = parse(rule[:block][:value])[0]
|
59
59
|
assert_equal(:style_rule, style_rule[:node])
|
60
|
-
assert_equal(".
|
60
|
+
assert_equal("#foo:not(.bar)", style_rule[:selector][:value])
|
61
61
|
assert_equal(1, style_rule[:children].size)
|
62
62
|
|
63
63
|
prop = style_rule[:children][0]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crass
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Grove
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-10-
|
11
|
+
date: 2013-10-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|