crass 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OGNiZTc1MDI4ZWMwYmQxZGI4ODE4Yzc1YzNkNTU2MDJjODc1NTI0Mg==
4
+ MDM3ZDU2Y2U1NDBkNGQxMDQwMzNhNGM1YTRjM2UyM2RjMTA5MGU5MA==
5
5
  data.tar.gz: !binary |-
6
- NTdlYmJkNTZlYjI3ZjE3Njc2ZDRiMzkxYWZjOTQ0OWE3ZTcxYWRiOQ==
6
+ YTMyMDVkZTViMjEyNjVlMGJkNjE2N2M0MWRhYmQ3Mzc3NGU0YzE3Mg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZjA0NTZkOTAwYTYwZmNjMDgyMzE1N2NkZDQ5ZTlkNDg0NzZmYTk4OGNiMjli
10
- MDdlNzQwNTAwZWZmMjkzY2U3N2NkMjEyOWU1ZDMyZWZlYjU1NGRjNzg1Y2Ez
11
- ZWZiYjg5ZTk2YmFhNWQ4NDk1ZDEzNmUwYjg2NDE0NjkyNzFmMjY=
9
+ ZDkwYmUyNGVkZjA5NGMwOWRlNzVlYmIwMmM5NjJlMDYxYWYxMzE0YzE2YWNl
10
+ MTYwZDU4MzZmMTkwZGVmMDk3ODI4MTMwZmE0NWQ3Y2M5ODE1MTllYjhlZWI2
11
+ NmQxMjExYmEzMmI1MTQzOWExOTk1Yjg0NjlkODNiYzM5ZDIwZjk=
12
12
  data.tar.gz: !binary |-
13
- NTE5NzI2MDViOWU5YzE4NzFmOWNlZmU0MWM5NTJhNGIyZTMyMTBkOGVjNWQ5
14
- MmQ5NDZhYWY5YjIzMTgyNzNjNzZmY2I1NDE3YzFmMzM2Njk1NGQzMzQ3OTkw
15
- MjFmODllYmM5NDQ5MTk3YjAwN2I3M2NmNzU4NDZkYzQwYzE1NWE=
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=>:style_rule,
87
- :selector=>
88
- {:node=>:selector,
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=>:whitespace, :pos=>24, :raw=>"\n "},
97
- {:node=>:property,
98
- :name=>"color",
99
- :value=>"#0d8bfa",
100
- :important=>false,
101
- :tokens=>
102
- [{:node=>:ident, :pos=>27, :raw=>"color", :value=>"color"},
103
- {:node=>:colon, :pos=>32, :raw=>":"},
104
- {:node=>:whitespace, :pos=>33, :raw=>" "},
105
- {:node=>:hash,
106
- :pos=>34,
107
- :raw=>"#0d8bfa",
108
- :type=>:unrestricted,
109
- :value=>"0d8bfa"},
110
- {:node=>:semicolon, :pos=>41, :raw=>";"}]},
111
- {:node=>:whitespace, :pos=>42, :raw=>"\n "},
112
- {:node=>:property,
113
- :name=>"text-decoration",
114
- :value=>"underline",
115
- :important=>false,
116
- :tokens=>
117
- [{:node=>:ident,
118
- :pos=>45,
119
- :raw=>"text-decoration",
120
- :value=>"text-decoration"},
121
- {:node=>:colon, :pos=>60, :raw=>":"},
122
- {:node=>:whitespace, :pos=>61, :raw=>" "},
123
- {:node=>:ident, :pos=>62, :raw=>"underline", :value=>"underline"},
124
- {:node=>:semicolon, :pos=>71, :raw=>";"}]},
125
- {:node=>:whitespace, :pos=>72, :raw=>"\n"}]},
126
- {:node=>:whitespace, :pos=>74, :raw=>"\n"}]
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:
@@ -26,7 +26,7 @@ module Crass
26
26
  Parser.new(input, options).parse_properties
27
27
  end
28
28
 
29
- # Parses a CSS rules (such as the content of a `@media` block) and returns a
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 then next
147
- when :semicolon, :eof then break
146
+ when :comment
147
+ next
148
148
 
149
- when :'{' then
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-value0
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 :'{', :'[', :'(' then consume_simple_block(input)
180
- when :function then consume_function(input)
181
- else token
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 do
307
+ function[:tokens].concat(input.collect {
295
308
  while token = input.consume
296
309
  case token[:node]
297
- when :')', :eof then break
298
- when :comment then next
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
- end)
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 true
344
- return rules unless token = @tokens.consume
345
-
359
+ while token = @tokens.consume
346
360
  case token[:node]
347
- when :comment, :whitespace then rules << token
348
- when :eof then return rules
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 || token[:node] == :eof
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 then next
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[:value])
486
+ string << parse_value(node[:tokens])
465
487
  end
466
488
 
467
489
  else
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Crass
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.0'
5
5
  end
@@ -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
@@ -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) {.foo{color:#fff;}}")[0]
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(".foo", style_rule[:selector][:value])
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.1.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-04 00:00:00.000000000 Z
11
+ date: 2013-10-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest