csspool 4.0.0.pre → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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