csspool 4.0.0.pre → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.rdoc +12 -0
  3. data/Gemfile.lock +6 -6
  4. data/Manifest.txt +10 -2
  5. data/Rakefile +1 -0
  6. data/lib/csspool/css/declaration.rb +1 -1
  7. data/lib/csspool/css/document.rb +5 -1
  8. data/lib/csspool/css/document_handler.rb +43 -11
  9. data/lib/csspool/css/fontface_rule.rb +13 -0
  10. data/lib/csspool/css/import_rule.rb +0 -5
  11. data/lib/csspool/css/media_feature.rb +14 -0
  12. data/lib/csspool/css/media_query.rb +19 -0
  13. data/lib/csspool/css/media_query_list.rb +41 -0
  14. data/lib/csspool/css/{media.rb → media_type.rb} +6 -4
  15. data/lib/csspool/css/parser.rb +1272 -671
  16. data/lib/csspool/css/parser.y +223 -53
  17. data/lib/csspool/css/rule_set.rb +4 -3
  18. data/lib/csspool/css/supports_rule.rb +14 -0
  19. data/lib/csspool/css/tokenizer.rb +92 -16
  20. data/lib/csspool/css/tokenizer.rex +42 -19
  21. data/lib/csspool/css.rb +6 -1
  22. data/lib/csspool/node.rb +22 -0
  23. data/lib/csspool/selector.rb +5 -4
  24. data/lib/csspool/selectors/pseudo.rb +2 -2
  25. data/lib/csspool/terms/function.rb +1 -1
  26. data/lib/csspool/terms/resolution.rb +13 -0
  27. data/lib/csspool/terms.rb +1 -0
  28. data/lib/csspool/visitors/children.rb +16 -2
  29. data/lib/csspool/visitors/comparable.rb +27 -8
  30. data/lib/csspool/visitors/iterator.rb +5 -3
  31. data/lib/csspool/visitors/to_css.rb +73 -20
  32. data/test/css/test_document_query.rb +37 -38
  33. data/test/css/test_font_face.rb +16 -0
  34. data/test/css/test_import_rule.rb +0 -3
  35. data/test/css/test_media_rule.rb +92 -0
  36. data/test/css/test_node_position.rb +81 -0
  37. data/test/css/test_parser.rb +12 -39
  38. data/test/css/test_supports_rule.rb +133 -0
  39. data/test/css/test_tokenizer.rb +4 -4
  40. data/test/css/test_variables.rb +33 -0
  41. data/test/helper.rb +3 -3
  42. data/test/sac/test_parser.rb +1 -0
  43. data/test/test_parser.rb +22 -9
  44. data/test/test_selector.rb +44 -4
  45. data/test/test_term.rb +29 -0
  46. data/test/visitors/test_comparable.rb +8 -0
  47. data/test/visitors/test_to_css.rb +89 -13
  48. metadata +54 -58
  49. data/test/_local_helper.rb +0 -2
@@ -32,9 +32,6 @@ module CSSPool
32
32
  new_doc = ir.load do |url|
33
33
  "div { background: red; }"
34
34
  end
35
- new_doc.rule_sets.each do |rs|
36
- assert_equal ir.media_list, rs.media.media_list
37
- end
38
35
  end
39
36
  end
40
37
  end
@@ -0,0 +1,92 @@
1
+ require 'helper'
2
+
3
+ # CSS @media - http://www.w3.org/TR/css3-mediaqueries/
4
+ module CSSPool
5
+ module CSS
6
+ class TestMediaRule < CSSPool::TestCase
7
+
8
+ def test_type
9
+ doc = CSSPool.CSS <<-eocss
10
+ @media print {
11
+ div { background: red, blue; }
12
+ }
13
+ eocss
14
+ assert_equal 1, doc.rule_sets.first.parent_rule.length
15
+ end
16
+
17
+ def test_expression
18
+ doc = CSSPool.CSS <<-eocss
19
+ @media (min-width:400px) {
20
+ div { background: red, blue; }
21
+ }
22
+ eocss
23
+ assert_equal 1, doc.rule_sets.first.parent_rule.length
24
+ end
25
+
26
+ def test_expression_no_space
27
+ doc = CSSPool.CSS <<-eocss
28
+ @media(min-width:400px) {
29
+ div { background: red, blue; }
30
+ }
31
+ eocss
32
+ assert_equal 1, doc.rule_sets.first.parent_rule.length
33
+ end
34
+
35
+ def test_complex
36
+ doc = CSSPool.CSS <<-eocss
37
+ @media screen and (color), projection and (color) { }
38
+ eocss
39
+ assert_equal 2, doc.rule_sets.first.parent_rule.length
40
+ end
41
+
42
+ def test_type_not
43
+ doc = CSSPool.CSS <<-eocss
44
+ @media not print {
45
+ div { background: red, blue; }
46
+ }
47
+ eocss
48
+ assert_equal 1, doc.rule_sets.first.parent_rule.length
49
+ end
50
+
51
+ def test_type_only
52
+ doc = CSSPool.CSS <<-eocss
53
+ @media only print {
54
+ div { background: red, blue; }
55
+ }
56
+ eocss
57
+ assert_equal 1, doc.rule_sets.first.parent_rule.length
58
+ end
59
+
60
+ def test_in_document_query
61
+ doc = CSSPool.CSS <<-eocss
62
+ @document domain(example.com) {
63
+ @media(max-height: 800px){.dashboard{position: absolute;}}
64
+ }
65
+ eocss
66
+ assert_equal 1, doc.rule_sets.first.parent_rule.length
67
+ end
68
+
69
+ def test_invalid_media_query_list
70
+ # needs to have space after 'and'
71
+ css = <<-eocss
72
+ @media all and(color) {
73
+ div { background: red, blue; }
74
+ }
75
+ eocss
76
+ assert_raises Racc::ParseError do
77
+ CSSPool::CSS(css)
78
+ end
79
+ end
80
+
81
+ # "and" is a reserved word in @media, but not elsewhere
82
+ def test_other_use_of_keywords
83
+ doc = CSSPool.CSS <<-eocss
84
+ /* and */
85
+ .and { display: flexbox; content: " and ";}
86
+ and { and: and; }
87
+ eocss
88
+ end
89
+
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,81 @@
1
+ require 'helper'
2
+
3
+ module CSSPool
4
+ module CSS
5
+ class TestNodePosition < CSSPool::TestCase
6
+
7
+ def test_no_whitespace
8
+ child_content = '* { color: blue !important }'
9
+ css = "@document url(\"http://www.example.com\") {#{child_content}}"
10
+ doc = CSSPool.CSS css
11
+ assert_equal 1, doc.document_queries.size
12
+ dq = doc.document_queries.first
13
+ assert !dq.outer_start_pos.nil?
14
+ assert !dq.inner_start_pos.nil?
15
+ assert !dq.inner_end_pos.nil?
16
+ assert !dq.outer_end_pos.nil?
17
+ assert_equal css, css[dq.outer_start_pos..dq.outer_end_pos-1]
18
+ assert_equal child_content, css[dq.inner_start_pos..dq.inner_end_pos-1]
19
+ end
20
+
21
+ def test_whitespace
22
+ child_content = '
23
+ * { color: blue !important }
24
+ '
25
+ css = "
26
+ @document url(\"http://www.example.com\") {#{child_content}}
27
+ "
28
+ doc = CSSPool.CSS css
29
+ assert_equal 1, doc.document_queries.size
30
+ dq = doc.document_queries.first
31
+ assert !dq.outer_start_pos.nil?
32
+ assert !dq.inner_start_pos.nil?
33
+ assert !dq.inner_end_pos.nil?
34
+ assert !dq.outer_end_pos.nil?
35
+ # the whitespace on the "outside" should not be included
36
+ assert_equal css.strip, css[dq.outer_start_pos..dq.outer_end_pos-1]
37
+ # the whitespace on the "inside" should be retained
38
+ assert_equal child_content, css[dq.inner_start_pos..dq.inner_end_pos-1]
39
+ end
40
+
41
+ def test_comments
42
+ child_content = ' /* comment two */
43
+ * { color: blue !important }
44
+ /* comment three */
45
+ '
46
+ css = " /* comment one */
47
+ @document url(\"http://www.example.com\") {#{child_content}}
48
+ /* comment four */
49
+ "
50
+ doc = CSSPool.CSS css
51
+ assert_equal 1, doc.document_queries.size
52
+ dq = doc.document_queries.first
53
+ assert !dq.outer_start_pos.nil?
54
+ assert !dq.inner_start_pos.nil?
55
+ assert !dq.inner_end_pos.nil?
56
+ assert !dq.outer_end_pos.nil?
57
+ # the comments and whitespace to the "outside" should not be retained
58
+ assert_equal css.sub('/* comment one */', '').sub('/* comment four */', '').strip, css[dq.outer_start_pos..dq.outer_end_pos-1]
59
+ # the comments and whitespace on the "inside" should be retained
60
+ assert_equal child_content, css[dq.inner_start_pos..dq.inner_end_pos-1]
61
+ end
62
+
63
+ # this only works in ruby 2+
64
+ def test_multibyte_characters
65
+ child_content = '/* â */ * { color: blue !important }'
66
+ css = "@document url(\"http://www.example.com\") {#{child_content}}"
67
+ doc = CSSPool.CSS css
68
+ assert_equal 1, doc.document_queries.size
69
+ dq = doc.document_queries.first
70
+ assert !dq.outer_start_pos.nil?
71
+ assert !dq.inner_start_pos.nil?
72
+ assert !dq.inner_end_pos.nil?
73
+ assert !dq.outer_end_pos.nil?
74
+ assert_equal css, css[dq.outer_start_pos..dq.outer_end_pos-1]
75
+ assert_equal child_content, css[dq.inner_start_pos..dq.inner_end_pos-1]
76
+ end
77
+
78
+ end
79
+ end
80
+ end
81
+
@@ -132,7 +132,7 @@ module CSSPool
132
132
  @parser.scan_str css
133
133
  property = @parser.handler.calls.find { |x|
134
134
  x.first == :property
135
- }[1][1].first
135
+ }[1][0].expressions.first
136
136
 
137
137
  term.each do |k,v|
138
138
  assert_equal v, property.send(k)
@@ -159,7 +159,7 @@ module CSSPool
159
159
  @parser.scan_str 'div { background: red; padding: 0; }'
160
160
  names = @parser.handler.calls.find_all { |x|
161
161
  x.first == :property
162
- }.map { |y| y[1].first }
162
+ }.map { |y| y[1].first.property }
163
163
  assert_equal %w{ background padding }, names
164
164
  end
165
165
 
@@ -176,7 +176,7 @@ module CSSPool
176
176
  declarations = @parser.handler.calls.find_all { |x|
177
177
  x.first == :property
178
178
  }
179
- names = declarations.map { |y| y[1].first }
179
+ names = declarations.map { |y| y[1].first.property }
180
180
  assert_equal %w{color color *color _color}, names
181
181
  # values = declarations.map { |y| y[1][1].first.to_s }
182
182
  # assert_equal %w{black green\\9 blue red}, values
@@ -284,7 +284,7 @@ module CSSPool
284
284
  end
285
285
 
286
286
  def test_ruleset_div_pseudo_function_with_arg
287
- assert_attribute 'div:foo.bar(bar) { }'
287
+ assert_attribute 'div:foo(bar) { }'
288
288
  end
289
289
 
290
290
  def test_ruleset_div_pseudo_function
@@ -363,15 +363,15 @@ module CSSPool
363
363
  def test_missing_semicolon
364
364
  @parser.scan_str 'div { border: none }'
365
365
  assert_equal 'div', doc.calls[1][1][0].join
366
- assert_equal 'border', doc.calls[2][1][0]
367
- assert_equal 'none', doc.calls[2][1][1].join
366
+ assert_equal 'border', doc.calls[2][1][0].property
367
+ assert_equal 'none', doc.calls[2][1][0].expressions.first.value
368
368
  end
369
369
 
370
370
  def test_whitespaces
371
371
  @parser.scan_str 'div { border : none }'
372
372
  assert_equal 'div', doc.calls[1][1][0].join
373
- assert_equal 'border', doc.calls[2][1][0]
374
- assert_equal 'none', doc.calls[2][1][1].join
373
+ assert_equal 'border', doc.calls[2][1][0].property
374
+ assert_equal 'none', doc.calls[2][1][0].expressions.first.value
375
375
  end
376
376
 
377
377
  def test_import_medium
@@ -389,33 +389,6 @@ module CSSPool
389
389
  assert_equal 'print', doc.calls[1][1].first[1].value
390
390
  end
391
391
 
392
- def test_document_query_url
393
- @parser.scan_str '@document url("http://example.com") { div {} }'
394
- assert_equal :start_document_query, doc.calls[1].first
395
- assert_equal 1, doc.calls[1][1][0].size
396
- assert_equal CSSPool::Terms::URI, doc.calls[1][1][0][0].class
397
- end
398
-
399
- def test_document_query_function
400
- @parser.scan_str '@document domain("example.com") { div {} }'
401
- assert_equal :start_document_query, doc.calls[1].first
402
- assert_equal 1, doc.calls[1][1][0].size
403
- assert_equal CSSPool::Terms::Function, doc.calls[1][1][0][0].class
404
- end
405
-
406
- def test_document_query_function_no_quotes
407
- @parser.scan_str '@document domain(example.com) { div {} }'
408
- assert_equal :start_document_query, doc.calls[1].first
409
- assert_equal 1, doc.calls[1][1][0].size
410
- assert_equal CSSPool::Terms::Function, doc.calls[1][1][0][0].class
411
- end
412
-
413
- def test_document_query_multiple
414
- @parser.scan_str '@document url("http://example.com"), domain("example.com") { div {} }'
415
- assert_equal :start_document_query, doc.calls[1].first
416
- assert_equal 2, doc.calls[1][1][0].size
417
- end
418
-
419
392
  def test_start_stop
420
393
  @parser.scan_str "@import 'foo';"
421
394
  assert_equal [:start_document, []], @doc.calls.first
@@ -441,12 +414,12 @@ module CSSPool
441
414
  assert_equal :property, @parser.handler.calls[2].first
442
415
  assert_equal :end_selector, @parser.handler.calls[3].first
443
416
 
444
- property = @parser.handler.calls[2][1]
445
- assert_equal name, property.first
417
+ declaration = @parser.handler.calls[2][1].first
418
+ assert_equal name, declaration.property
446
419
 
447
- assert_equal values, property[1].map { |x| x.value }
420
+ assert_equal values, declaration.expressions.map { |x| x.value }
448
421
  if ops
449
- assert_equal ops, property[1].map { |x| x.operator }
422
+ assert_equal ops, declaration.expressions.map { |x| x.operator }
450
423
  end
451
424
  end
452
425
 
@@ -0,0 +1,133 @@
1
+ require 'helper'
2
+
3
+ module CSSPool
4
+ module CSS
5
+ class TestSupportsRule < CSSPool::TestCase
6
+
7
+ def test_basic
8
+ doc = CSSPool.CSS <<-eocss
9
+ @supports ( display: flexbox ) {
10
+ body { display: flexbox; }
11
+ }
12
+ eocss
13
+ assert_equal 1, doc.supports_rules.size
14
+ assert_match '( display: flexbox )', doc.supports_rules[0].conditions
15
+ assert_equal 1, doc.supports_rules[0].rule_sets.size
16
+ end
17
+
18
+ def test_not
19
+ doc = CSSPool.CSS <<-eocss
20
+ @supports not ( display: flexbox ) {
21
+ body { display: flexbox; }
22
+ }
23
+ eocss
24
+ assert_equal 1, doc.supports_rules.size
25
+ assert_match 'not ( display: flexbox )', doc.supports_rules[0].conditions
26
+ assert_equal 1, doc.supports_rules[0].rule_sets.size
27
+ end
28
+
29
+ def test_or
30
+ doc = CSSPool.CSS <<-eocss
31
+ @supports ( display: flexbox ) or ( display: block ) {
32
+ body { display: flexbox; }
33
+ }
34
+ eocss
35
+ assert_equal 1, doc.supports_rules.size
36
+ assert_match '( display: flexbox ) or ( display: block )', doc.supports_rules[0].conditions
37
+ assert_equal 1, doc.supports_rules[0].rule_sets.size
38
+ end
39
+
40
+ def test_and
41
+ doc = CSSPool.CSS <<-eocss
42
+ @supports ( display: flexbox ) and ( display: block ) {
43
+ body { display: flexbox; }
44
+ }
45
+ eocss
46
+ assert_equal 1, doc.supports_rules.size
47
+ assert_match '( display: flexbox ) and ( display: block )', doc.supports_rules[0].conditions
48
+ assert_equal 1, doc.supports_rules[0].rule_sets.size
49
+ end
50
+
51
+ def test_complex
52
+ doc = CSSPool.CSS <<-eocss
53
+ @supports ((display: inline) or (( display: flexbox ) and ( display: block ))) {
54
+ body { display: flexbox; }
55
+ }
56
+ eocss
57
+ assert_equal 1, doc.supports_rules.size
58
+ assert_match '((display: inline) or (( display: flexbox ) and ( display: block ))', doc.supports_rules[0].conditions
59
+ assert_equal 1, doc.supports_rules[0].rule_sets.size
60
+ end
61
+
62
+ def test_double_parens
63
+ doc = CSSPool.CSS <<-eocss
64
+ @supports ((display: flexbox)) {
65
+ body { display: flexbox; }
66
+ }
67
+ eocss
68
+ assert_equal 1, doc.supports_rules.size
69
+ assert_match '((display: flexbox))', doc.supports_rules[0].conditions
70
+ assert_equal 1, doc.supports_rules[0].rule_sets.size
71
+ end
72
+
73
+ def test_important
74
+ doc = CSSPool.CSS <<-eocss
75
+ @supports ( display: flexbox !important) {
76
+ body { display: flexbox; }
77
+ }
78
+ eocss
79
+ assert_equal 1, doc.supports_rules.size
80
+ assert_match '( display: flexbox !important)', doc.supports_rules[0].conditions
81
+ assert_equal 1, doc.supports_rules[0].rule_sets.size
82
+ end
83
+
84
+ def test_other_use_of_keyword
85
+ doc = CSSPool.CSS <<-eocss
86
+ /* and */
87
+ .and { display: flexbox; content: " and ";}
88
+ and { and: and; }
89
+ eocss
90
+ end
91
+
92
+ def test_invalid_keyword_in_place_of_and_or
93
+ exception_happened = false
94
+ begin
95
+ doc = CSSPool.CSS <<-eocss
96
+ @supports ( display: flexbox ) xor ( display: block ) {
97
+ body { display: flexbox; }
98
+ }
99
+ eocss
100
+ rescue
101
+ exception_happened = true
102
+ end
103
+ assert exception_happened
104
+ end
105
+
106
+ def test_invalid_keyword_in_place_of_not
107
+ exception_happened = false
108
+ begin
109
+ doc = CSSPool.CSS <<-eocss
110
+ @supports isnt ( display: flexbox ) {
111
+ body { display: flexbox; }
112
+ }
113
+ eocss
114
+ rescue
115
+ exception_happened = true
116
+ end
117
+ assert exception_happened
118
+ end
119
+
120
+ def test_with_parens
121
+ doc = CSSPool.CSS <<-eocss
122
+ @supports ( filter: url(http://example.com) ) {
123
+ body { filter: url(http://example.com) }
124
+ }
125
+ eocss
126
+ assert_equal 1, doc.supports_rules.size
127
+ assert_match 'filter: url("http://example.com")', doc.supports_rules[0].conditions
128
+ assert_equal 1, doc.supports_rules[0].rule_sets.size
129
+ end
130
+
131
+ end
132
+ end
133
+ end
@@ -14,8 +14,8 @@ module CSSPool
14
14
  end
15
15
 
16
16
  {
17
- 'em' => :EMS,
18
- 'ex' => :EXS,
17
+ 'em' => :LENGTH,
18
+ 'ex' => :LENGTH,
19
19
  'px' => :LENGTH,
20
20
  'cm' => :LENGTH,
21
21
  'mm' => :LENGTH,
@@ -206,7 +206,7 @@ module CSSPool
206
206
  def test_scan_pseudo
207
207
  @scanner.scan('a:visited')
208
208
  assert_tokens([ [:IDENT, 'a'],
209
- [':', ':'],
209
+ [:COLON, ':'],
210
210
  [:IDENT, 'visited']
211
211
  ], @scanner)
212
212
  end
@@ -256,7 +256,7 @@ module CSSPool
256
256
  def test_scan_function_selector
257
257
  @scanner.scan('x:eq(0)')
258
258
  assert_tokens([ [:IDENT, 'x'],
259
- [':', ':'],
259
+ [:COLON, ':'],
260
260
  [:FUNCTION, 'eq('],
261
261
  [:NUMBER, "0"],
262
262
  [:RPAREN, ')'],
@@ -0,0 +1,33 @@
1
+ require 'helper'
2
+
3
+ # CSS variables - http://dev.w3.org/csswg/css-variables/
4
+ module CSSPool
5
+ module CSS
6
+ class TestVariables < CSSPool::TestCase
7
+
8
+ # just checking that there's no parse error
9
+ def test_basic
10
+ doc = CSSPool.CSS <<-eocss
11
+ :root {
12
+ --main-bg-color: brown;
13
+ }
14
+ .one {
15
+ background-color: var(--main-bg-color);
16
+ }
17
+ eocss
18
+ end
19
+
20
+ def test_var_in_calc
21
+ doc = CSSPool.CSS <<-eocss
22
+ :root {
23
+ --right-margin: 10px;
24
+ }
25
+ .one {
26
+ width: calc(100% + var(--right-margin));
27
+ }
28
+ eocss
29
+ end
30
+
31
+ end
32
+ end
33
+ end
data/test/helper.rb CHANGED
@@ -12,7 +12,7 @@ module CSSPool
12
12
  class MyDoc < CSSPool::CSS::DocumentHandler
13
13
  attr_accessor :start_documents, :end_documents
14
14
  attr_accessor :charsets, :import_styles, :document_queries, :comments, :start_selectors
15
- attr_accessor :end_selectors, :properties
15
+ attr_accessor :end_selectors, :properties, :supports_rules
16
16
 
17
17
  def initialize
18
18
  @start_documents = []
@@ -26,8 +26,8 @@ module CSSPool
26
26
  @properties = []
27
27
  end
28
28
 
29
- def property name, expression, important
30
- @properties << [name, expression]
29
+ def property declaration
30
+ @properties << [declaration.property, declaration.expressions]
31
31
  end
32
32
 
33
33
  def start_document
@@ -90,6 +90,7 @@ module CSSPool
90
90
  assert_nil simple_selector.additional_selectors.first.extra
91
91
  end
92
92
 
93
+ # div#a, a.foo, a::hover, a[href][int="10"]{ background: red; }
93
94
  def test_attribute_selector
94
95
  selectors_for_rule = @doc.start_selectors[1]
95
96
  selector = selectors_for_rule[3] # => a[href][int="10"]
data/test/test_parser.rb CHANGED
@@ -29,15 +29,6 @@ module CSSPool
29
29
  assert_equal 'background', rule_set.declarations.first.property
30
30
  end
31
31
 
32
- def test_media
33
- doc = CSSPool.CSS <<-eocss
34
- @media print {
35
- div { background: red, blue; }
36
- }
37
- eocss
38
- assert_equal 1, doc.rule_sets.first.media.media_list.length
39
- end
40
-
41
32
  def test_universal_to_css
42
33
  doc = CSSPool.CSS <<-eocss
43
34
  * { background: red, blue; }
@@ -120,5 +111,27 @@ module CSSPool
120
111
  #assert_equal "http://\\\r\nexample.com/image.png", doc.rule_sets.first.declarations.first.expressions.first.value
121
112
  end
122
113
 
114
+ def test_error_message_context
115
+ begin
116
+ doc = CSSPool.CSS "syntax } error"
117
+ # should not reach this
118
+ assert false
119
+ rescue ParseError => ex
120
+ # ensure the context around the failing token (the bracket) are included
121
+ assert_match 'syntax } error', ex.message
122
+ end
123
+ end
124
+
125
+ def test_error_message_line
126
+ begin
127
+ doc = CSSPool.CSS "\n\n\nsyntax } error"
128
+ # should not reach this
129
+ assert false
130
+ rescue ParseError => ex
131
+ # ensure the context around the failing token (the bracket) are included
132
+ assert_match 'line 4', ex.message
133
+ end
134
+ end
135
+
123
136
  end
124
137
  end
@@ -4,14 +4,14 @@ module CSSPool
4
4
  class TestSelector < CSSPool::TestCase
5
5
  def test_specificity
6
6
  doc = CSSPool.CSS <<-eocss
7
- *, foo > bar, #hover, :hover, div#a, a.foo, a:hover, a[href][int="10"], :before, ::before { background: red; }
7
+ *, foo > bar, #hover, :hover, div#a, a.foo, a:hover, a[href][int="10"], p::selection { background: red; }
8
8
  eocss
9
9
  selectors = doc.rule_sets.first.selectors
10
10
  specs = selectors.map do |sel|
11
11
  sel.specificity
12
12
  end
13
13
  assert_equal [
14
- [0, 0, 1],
14
+ [0, 0, 0],
15
15
  [0, 0, 2],
16
16
  [1, 0, 0],
17
17
  [0, 1, 0],
@@ -19,8 +19,7 @@ module CSSPool
19
19
  [0, 1, 1],
20
20
  [0, 1, 1],
21
21
  [0, 2, 1],
22
- [0, 0, 1],
23
- [0, 0, 1]
22
+ [0, 0, 2]
24
23
  ], specs
25
24
  end
26
25
 
@@ -146,6 +145,47 @@ module CSSPool
146
145
  assert_equal 'even', rs.selectors.first.simple_selectors.first.additional_selectors.first.extra
147
146
  end
148
147
 
148
+ def test_mozilla_pseudo_element
149
+ doc = CSSPool.CSS <<-eocss
150
+ treechildren::-moz-tree-line { background: red; }
151
+ eocss
152
+ rs = doc.rule_sets.first
153
+ assert_equal '-moz-tree-line', rs.selectors.first.simple_selectors.first.additional_selectors.first.name
154
+ end
155
+
156
+ def test_mozilla_pseudo_element_brackets_without_parameters
157
+ doc = CSSPool.CSS <<-eocss
158
+ treechildren::-moz-tree-line() { background: red; }
159
+ eocss
160
+ rs = doc.rule_sets.first
161
+ assert_equal '-moz-tree-line', rs.selectors.first.simple_selectors.first.additional_selectors.first.name
162
+ end
163
+
164
+ def test_mozilla_pseudo_element_single_parameter
165
+ doc = CSSPool.CSS <<-eocss
166
+ treechildren::-moz-tree-line(one) { background: red; }
167
+ eocss
168
+ rs = doc.rule_sets.first
169
+ assert_equal '-moz-tree-line', rs.selectors.first.simple_selectors.first.additional_selectors.first.name
170
+ end
171
+
172
+ def test_mozilla_pseudo_element_multiple_parameters
173
+ doc = CSSPool.CSS <<-eocss
174
+ treechildren::-moz-tree-line(one, two, three) { background: red; }
175
+ eocss
176
+ rs = doc.rule_sets.first
177
+ assert_equal '-moz-tree-line', rs.selectors.first.simple_selectors.first.additional_selectors.first.name
178
+ end
179
+
180
+ # -moz-tree-cell and -moz-tree-cell-text are both mozilla pseudo-elements, make sure we don't stop at -moz-tree-cell
181
+ def test_mozilla_pseudo_element_name_within
182
+ doc = CSSPool.CSS <<-eocss
183
+ treechildren::-moz-tree-cell-text() { background: red; }
184
+ eocss
185
+ rs = doc.rule_sets.first
186
+ assert_equal '-moz-tree-cell-text', rs.selectors.first.simple_selectors.first.additional_selectors.first.name
187
+ end
188
+
149
189
  def test_element_with_namespace
150
190
  doc = CSSPool.CSS <<-eocss
151
191
  a|b { background: red; }
data/test/test_term.rb CHANGED
@@ -19,5 +19,34 @@ module CSSPool
19
19
  assert_equal '100%/3 - 2*1em - 2*1px', rs.declarations.first.expressions.first.expression
20
20
  end
21
21
 
22
+ def test_math_with_params
23
+ doc = CSSPool.CSS <<-eocss
24
+ a { top: calc((1em + 16px) / 2) }
25
+ eocss
26
+ rs = doc.rule_sets.first
27
+ assert_equal '(1em + 16px)/2', rs.declarations.first.expressions.first.expression
28
+ end
29
+
30
+ def test_negative_multiplication
31
+ doc = CSSPool.CSS <<-eocss
32
+ a { top: calc(1.4 * -8px) }
33
+ eocss
34
+ rs = doc.rule_sets.first
35
+ assert_equal '1.4*-8px', rs.declarations.first.expressions.first.expression
36
+ end
37
+
38
+ def test_two_in_a_row
39
+ doc = CSSPool.CSS <<-eocss
40
+ a { background-size: calc(-2px + 100%) calc(-2px + 100%); }
41
+ eocss
42
+ rs = doc.rule_sets.first
43
+ assert_equal '-2px + 100%', rs.declarations.first.expressions.first.expression
44
+ end
45
+
46
+ def test_function_no_params
47
+ CSSPool.CSS <<-eocss
48
+ a { -webkit-filter: invert() }
49
+ eocss
50
+ end
22
51
  end
23
52
  end
@@ -97,6 +97,14 @@ module CSSPool
97
97
  equalitest '@import "foo.css" screen, print;'
98
98
  equalitest '@import "foo.css";'
99
99
  end
100
+
101
+ def test_media_query_list_with_empty_body
102
+ equalitest "@media screen and (min-width:400px) and (max-width:600px) {}"
103
+ end
104
+
105
+ def test_media_query_list_with_body
106
+ equalitest "@media screen and (min-width:400px) and (max-width:600px) { div { color: inherit; } }"
107
+ end
100
108
  end
101
109
  end
102
110
  end