csspool 3.0.2 → 4.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/Gemfile.lock +4 -4
  2. data/Manifest.txt +13 -0
  3. data/README.rdoc +1 -1
  4. data/lib/csspool/css/document.rb +6 -0
  5. data/lib/csspool/css/document_handler.rb +41 -7
  6. data/lib/csspool/css/document_query.rb +14 -0
  7. data/lib/csspool/css/import_rule.rb +8 -4
  8. data/lib/csspool/css/keyframes_block.rb +14 -0
  9. data/lib/csspool/css/keyframes_rule.rb +14 -0
  10. data/lib/csspool/css/media.rb +5 -3
  11. data/lib/csspool/css/namespace_rule.rb +13 -0
  12. data/lib/csspool/css/parser.rb +970 -425
  13. data/lib/csspool/css/parser.y +227 -30
  14. data/lib/csspool/css/tokenizer.rb +31 -7
  15. data/lib/csspool/css/tokenizer.rex +36 -7
  16. data/lib/csspool/css.rb +4 -0
  17. data/lib/csspool/selector.rb +5 -1
  18. data/lib/csspool/selectors/attribute.rb +6 -1
  19. data/lib/csspool/selectors/pseudo.rb +17 -0
  20. data/lib/csspool/selectors/pseudo_element.rb +13 -0
  21. data/lib/csspool/selectors/simple.rb +0 -4
  22. data/lib/csspool/selectors/type.rb +7 -0
  23. data/lib/csspool/selectors/universal.rb +7 -0
  24. data/lib/csspool/selectors.rb +1 -1
  25. data/lib/csspool/terms/math.rb +18 -0
  26. data/lib/csspool/terms.rb +1 -0
  27. data/lib/csspool/visitors/children.rb +1 -1
  28. data/lib/csspool/visitors/comparable.rb +8 -2
  29. data/lib/csspool/visitors/iterator.rb +1 -1
  30. data/lib/csspool/visitors/to_css.rb +41 -21
  31. data/lib/csspool.rb +1 -1
  32. data/test/_local_helper.rb +2 -0
  33. data/test/css/test_document_query.rb +76 -0
  34. data/test/css/test_import_rule.rb +1 -1
  35. data/test/css/test_keyframes_rule.rb +93 -0
  36. data/test/css/test_namespace_rule.rb +54 -0
  37. data/test/css/test_parser.rb +46 -1
  38. data/test/css/test_tokenizer.rb +0 -45
  39. data/test/helper.rb +6 -1
  40. data/test/sac/test_parser.rb +16 -3
  41. data/test/test_declaration.rb +39 -0
  42. data/test/test_parser.rb +26 -13
  43. data/test/test_selector.rb +205 -5
  44. data/test/test_term.rb +23 -0
  45. data/test/visitors/test_to_css.rb +34 -23
  46. metadata +136 -118
@@ -0,0 +1,39 @@
1
+ require 'helper'
2
+
3
+ module CSSPool
4
+ class TestSelector < CSSPool::TestCase
5
+
6
+ def test_multiple_semicolons
7
+ doc = CSSPool.CSS <<-eocss
8
+ a { background: red;; color: blue; }
9
+ eocss
10
+ rs = doc.rule_sets.first
11
+ assert_equal 2, rs.declarations.size
12
+ end
13
+
14
+ def test_leading_semicolon
15
+ doc = CSSPool.CSS <<-eocss
16
+ a { ; background: red; }
17
+ eocss
18
+ rs = doc.rule_sets.first
19
+ assert_equal 1, rs.declarations.size
20
+ end
21
+
22
+ def test_no_trailing_semicolon
23
+ doc = CSSPool.CSS <<-eocss
24
+ a { background: red }
25
+ eocss
26
+ rs = doc.rule_sets.first
27
+ assert_equal 1, rs.declarations.size
28
+ end
29
+
30
+ def test_only_semicolon
31
+ doc = CSSPool.CSS <<-eocss
32
+ a { ; }
33
+ eocss
34
+ rs = doc.rule_sets.first
35
+ assert_equal 0, rs.declarations.size
36
+ end
37
+
38
+ end
39
+ end
data/test/test_parser.rb CHANGED
@@ -35,7 +35,7 @@ module CSSPool
35
35
  div { background: red, blue; }
36
36
  }
37
37
  eocss
38
- assert_equal 1, doc.rule_sets.first.media.length
38
+ assert_equal 1, doc.rule_sets.first.media.media_list.length
39
39
  end
40
40
 
41
41
  def test_universal_to_css
@@ -88,24 +88,37 @@ module CSSPool
88
88
  assert_match('foo(1, 2)', doc.to_css)
89
89
  end
90
90
 
91
- def test_missing_semicolon
91
+ def test_url
92
92
  doc = CSSPool.CSS <<-eocss
93
- div { border: none }
93
+ div { background: url(http://example.com); }
94
94
  eocss
95
- assert_match('none', doc.to_css)
96
- doc = CSSPool.CSS <<-eocss
97
- div { border: none; background: #fff }
98
- eocss
99
- assert_match('none', doc.to_css)
100
- assert_match('#fff', doc.to_css)
95
+ assert_match 'http://example.com', doc.to_css
101
96
  end
102
97
 
103
- def test_whitespaces
98
+ def test_url_capitalized
104
99
  doc = CSSPool.CSS <<-eocss
105
- div { border : none; }
100
+ div { background: URL(http://example.com); }
106
101
  eocss
107
- assert_match('none', doc.to_css)
108
- assert_match('border:', doc.to_css)
102
+ assert_match 'http://example.com', doc.to_css
109
103
  end
104
+
105
+ def test_uri_linefeed_n
106
+ doc = CSSPool.CSS "div { background: url('http://\\\nexample.com/image.png') }"
107
+ # FIXME: (mt) Sort this out; these tests don't currently run, but should both run and pass
108
+ #assert_equal "http://\\\nexample.com/image.png", doc.rule_sets.first.declarations.first.expressions.first.value
109
+ end
110
+
111
+ def test_uri_linefeed_r
112
+ doc = CSSPool.CSS "div { background: url('http://\\\rexample.com/image.png') }"
113
+ # FIXME: (mt) Sort this out; these tests don't currently run, but should both run and pass
114
+ #assert_equal "http://\\\rexample.com/image.png", doc.rule_sets.first.declarations.first.expressions.first.value
115
+ end
116
+
117
+ def test_uri_linefeed_rn
118
+ doc = CSSPool.CSS "div { background: url('http://\\\r\nexample.com/image.png') }"
119
+ # FIXME: (mt) Sort this out; these tests don't currently run, but should both run and pass
120
+ #assert_equal "http://\\\r\nexample.com/image.png", doc.rule_sets.first.declarations.first.expressions.first.value
121
+ end
122
+
110
123
  end
111
124
  end
@@ -4,20 +4,24 @@ 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"]{ background: red; }
7
+ *, foo > bar, #hover, :hover, div#a, a.foo, a:hover, a[href][int="10"], :before, ::before { 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
- assert_equal [[0, 0, 1],
13
+ assert_equal [
14
+ [0, 0, 1],
14
15
  [0, 0, 2],
15
- [1, 0, 1],
16
- [0, 1, 1],
16
+ [1, 0, 0],
17
+ [0, 1, 0],
17
18
  [1, 0, 1],
18
19
  [0, 1, 1],
19
20
  [0, 1, 1],
20
- [0, 2, 1]], specs
21
+ [0, 2, 1],
22
+ [0, 0, 1],
23
+ [0, 0, 1]
24
+ ], specs
21
25
  end
22
26
 
23
27
  def test_selector_knows_its_ruleset
@@ -43,5 +47,201 @@ module CSSPool
43
47
  rs = doc.rule_sets.first
44
48
  rs.declarations.each { |del| assert_equal rs, del.rule_set }
45
49
  end
50
+
51
+ def test_general_sibling_selector
52
+ doc = CSSPool.CSS <<-eocss
53
+ a ~ b { background: red; }
54
+ eocss
55
+ rs = doc.rule_sets.first
56
+ assert_equal :~, rs.selectors.first.simple_selectors[1].combinator
57
+ end
58
+
59
+ def test_attribute_prefix_match
60
+ doc = CSSPool.CSS <<-eocss
61
+ a[href^="http"] { background: red; }
62
+ eocss
63
+ rs = doc.rule_sets.first
64
+ assert_equal Selectors::Attribute, rs.selectors.first.simple_selectors.first.additional_selectors.first.class
65
+ assert_equal Selectors::Attribute::PREFIXMATCH, rs.selectors.first.simple_selectors.first.additional_selectors.first.match_way
66
+ end
67
+
68
+ def test_attribute_suffix_match
69
+ doc = CSSPool.CSS <<-eocss
70
+ a[href$="http"] { background: red; }
71
+ eocss
72
+ rs = doc.rule_sets.first
73
+ assert_equal Selectors::Attribute, rs.selectors.first.simple_selectors.first.additional_selectors.first.class
74
+ assert_equal Selectors::Attribute::SUFFIXMATCH, rs.selectors.first.simple_selectors.first.additional_selectors.first.match_way
75
+ end
76
+
77
+ def test_attribute_substring_match
78
+ doc = CSSPool.CSS <<-eocss
79
+ a[href*="http"] { background: red; }
80
+ eocss
81
+ rs = doc.rule_sets.first
82
+ assert_equal Selectors::Attribute, rs.selectors.first.simple_selectors.first.additional_selectors.first.class
83
+ assert_equal Selectors::Attribute::SUBSTRINGMATCH, rs.selectors.first.simple_selectors.first.additional_selectors.first.match_way
84
+ end
85
+
86
+ def test_not_pseudo_class
87
+ doc = CSSPool.CSS <<-eocss
88
+ a:not(b) { background: red; }
89
+ eocss
90
+ rs = doc.rule_sets.first
91
+ assert_equal 'a', rs.selectors.first.simple_selectors.first.name
92
+ assert_equal ':not(b)', rs.selectors.first.simple_selectors.first.additional_selectors.first.to_s
93
+ end
94
+
95
+ def test_nth_integer
96
+ doc = CSSPool.CSS <<-eocss
97
+ a:nth-child(1) { background: red; }
98
+ eocss
99
+ rs = doc.rule_sets.first
100
+ assert_equal 'nth-child', rs.selectors.first.simple_selectors.first.additional_selectors.first.name
101
+ assert_equal '1', rs.selectors.first.simple_selectors.first.additional_selectors.first.extra
102
+ end
103
+
104
+ def test_nth_negative_integer
105
+ doc = CSSPool.CSS <<-eocss
106
+ a:nth-child(-1) { background: red; }
107
+ eocss
108
+ rs = doc.rule_sets.first
109
+ assert_equal 'nth-child', rs.selectors.first.simple_selectors.first.additional_selectors.first.name
110
+ assert_equal '-1', rs.selectors.first.simple_selectors.first.additional_selectors.first.extra
111
+ end
112
+
113
+ def test_nth_n_syntax
114
+ doc = CSSPool.CSS <<-eocss
115
+ a:nth-child(-2n-1) { background: red; }
116
+ eocss
117
+ rs = doc.rule_sets.first
118
+ assert_equal 'nth-child', rs.selectors.first.simple_selectors.first.additional_selectors.first.name
119
+ assert_equal '-2n-1', rs.selectors.first.simple_selectors.first.additional_selectors.first.extra
120
+ end
121
+
122
+ def test_nth_n_syntax_with_whitespace
123
+ doc = CSSPool.CSS <<-eocss
124
+ a:nth-child( -2n - 1 ) { background: red; }
125
+ eocss
126
+ rs = doc.rule_sets.first
127
+ assert_equal 'nth-child', rs.selectors.first.simple_selectors.first.additional_selectors.first.name
128
+ assert_equal ' -2n - 1 ', rs.selectors.first.simple_selectors.first.additional_selectors.first.extra
129
+ end
130
+
131
+ def test_nth_odd
132
+ doc = CSSPool.CSS <<-eocss
133
+ a:nth-child(odd) { background: red; }
134
+ eocss
135
+ rs = doc.rule_sets.first
136
+ assert_equal 'nth-child', rs.selectors.first.simple_selectors.first.additional_selectors.first.name
137
+ assert_equal 'odd', rs.selectors.first.simple_selectors.first.additional_selectors.first.extra
138
+ end
139
+
140
+ def test_nth_even
141
+ doc = CSSPool.CSS <<-eocss
142
+ a:nth-child(even) { background: red; }
143
+ eocss
144
+ rs = doc.rule_sets.first
145
+ assert_equal 'nth-child', rs.selectors.first.simple_selectors.first.additional_selectors.first.name
146
+ assert_equal 'even', rs.selectors.first.simple_selectors.first.additional_selectors.first.extra
147
+ end
148
+
149
+ def test_element_with_namespace
150
+ doc = CSSPool.CSS <<-eocss
151
+ a|b { background: red; }
152
+ eocss
153
+ rs = doc.rule_sets.first
154
+ assert_equal 'b', rs.selectors.first.simple_selectors.first.name
155
+ assert_equal 'a', rs.selectors.first.simple_selectors.first.namespace
156
+ end
157
+
158
+ def test_element_with_no_namespace
159
+ doc = CSSPool.CSS <<-eocss
160
+ |b { background: red; }
161
+ eocss
162
+ rs = doc.rule_sets.first
163
+ assert_equal 'b', rs.selectors.first.simple_selectors.first.name
164
+ assert_equal nil, rs.selectors.first.simple_selectors.first.namespace
165
+ end
166
+
167
+ def test_element_with_any_namespace
168
+ doc = CSSPool.CSS <<-eocss
169
+ *|b { background: red; }
170
+ eocss
171
+ rs = doc.rule_sets.first
172
+ assert_equal 'b', rs.selectors.first.simple_selectors.first.name
173
+ assert_equal '*', rs.selectors.first.simple_selectors.first.namespace
174
+ end
175
+
176
+ def test_universal_with_namespace
177
+ doc = CSSPool.CSS <<-eocss
178
+ a|* { background: red; }
179
+ eocss
180
+ rs = doc.rule_sets.first
181
+ assert_equal Selectors::Universal, rs.selectors.first.simple_selectors.first.class
182
+ assert_equal 'a', rs.selectors.first.simple_selectors.first.namespace
183
+ end
184
+
185
+ def test_universal_with_no_namespace
186
+ doc = CSSPool.CSS <<-eocss
187
+ |* { background: red; }
188
+ eocss
189
+ rs = doc.rule_sets.first
190
+ assert_equal Selectors::Universal, rs.selectors.first.simple_selectors.first.class
191
+ assert_equal nil, rs.selectors.first.simple_selectors.first.namespace
192
+ end
193
+
194
+ def test_universal_with_any_namespace
195
+ doc = CSSPool.CSS <<-eocss
196
+ *|* { background: red; }
197
+ eocss
198
+ rs = doc.rule_sets.first
199
+ assert_equal Selectors::Universal, rs.selectors.first.simple_selectors.first.class
200
+ assert_equal '*', rs.selectors.first.simple_selectors.first.namespace
201
+ end
202
+
203
+ def test_attribute_with_namespace
204
+ doc = CSSPool.CSS <<-eocss
205
+ a[b|c] { background: red; }
206
+ eocss
207
+ rs = doc.rule_sets.first
208
+ assert_equal 'b', rs.selectors.first.simple_selectors.first.additional_selectors.first.namespace
209
+ assert_equal 'c', rs.selectors.first.simple_selectors.first.additional_selectors.first.name
210
+ end
211
+
212
+ def test_attribute_with_no_namespace
213
+ doc = CSSPool.CSS <<-eocss
214
+ a[|c] { background: red; }
215
+ eocss
216
+ rs = doc.rule_sets.first
217
+ assert_equal nil, rs.selectors.first.simple_selectors.first.additional_selectors.first.namespace
218
+ assert_equal 'c', rs.selectors.first.simple_selectors.first.additional_selectors.first.name
219
+ end
220
+
221
+ def test_attribute_with_any_namespace
222
+ doc = CSSPool.CSS <<-eocss
223
+ a[*|c] { background: red; }
224
+ eocss
225
+ rs = doc.rule_sets.first
226
+ assert_equal '*', rs.selectors.first.simple_selectors.first.additional_selectors.first.namespace
227
+ assert_equal 'c', rs.selectors.first.simple_selectors.first.additional_selectors.first.name
228
+ end
229
+
230
+ def test_matches_pseudoclass
231
+ doc = CSSPool.CSS <<-eocss
232
+ :matches(section, article, aside, nav) { background: red; }
233
+ eocss
234
+ rs = doc.rule_sets.first
235
+ assert_equal 'section, article, aside, nav', rs.selectors.first.simple_selectors.first.additional_selectors.first.extra
236
+ end
237
+
238
+ def test_matches_pseudoclass_complex
239
+ doc = CSSPool.CSS <<-eocss
240
+ :matches(#id[attribute="selector"], #main-id[another="attribute"]) { background: red; }
241
+ eocss
242
+ rs = doc.rule_sets.first
243
+ assert_equal '#id[attribute="selector"], #main-id[another="attribute"]', rs.selectors.first.simple_selectors.first.additional_selectors.first.extra
244
+ end
245
+
46
246
  end
47
247
  end
data/test/test_term.rb ADDED
@@ -0,0 +1,23 @@
1
+ require 'helper'
2
+
3
+ module CSSPool
4
+ class TestTerm < CSSPool::TestCase
5
+
6
+ def test_math_simple
7
+ doc = CSSPool.CSS <<-eocss
8
+ a { top: calc(100% + 15px) }
9
+ eocss
10
+ rs = doc.rule_sets.first
11
+ assert_equal '100% + 15px', rs.declarations.first.expressions.first.expression
12
+ end
13
+
14
+ def test_math_complex
15
+ doc = CSSPool.CSS <<-eocss
16
+ a { top: calc(100%/3 - 2*1em - 2*1px) }
17
+ eocss
18
+ rs = doc.rule_sets.first
19
+ assert_equal '100%/3 - 2*1em - 2*1px', rs.declarations.first.expressions.first.expression
20
+ end
21
+
22
+ end
23
+ end
@@ -16,18 +16,24 @@ module CSSPool
16
16
  doc.rule_sets.first.declarations.first.to_css.strip
17
17
  end
18
18
 
19
- # FIXME: this is a bug in libcroco
20
- #def test_ident_followed_by_id
21
- # doc = CSSPool.CSS 'p#div { font: foo, #666; }'
22
- # assert_equal 'p#div', doc.rule_sets.first.selectors.first.to_css
19
+ def test_combinators
23
20
 
24
- # p doc.rule_sets.first.selectors
21
+ selectors = %w{* p #id .cl :hover ::selection [href]}
22
+ combinators = ['', ' ', ' > ', ' + ']
25
23
 
26
- # doc = CSSPool.CSS 'p #div { font: foo, #666; }'
24
+ combinations = selectors.product(combinators).map do |s,c|
25
+ if s != '*' && c != '' then
26
+ s + c
27
+ end
28
+ end.compact
29
+ combinations = combinations.product(selectors).map { |s,c| s + c}
27
30
 
28
- # p doc.rule_sets.first.selectors
29
- # assert_equal 'p #div', doc.rule_sets.first.selectors.first.to_css
30
- #end
31
+ combinations.each do |s|
32
+ doc = CSSPool.CSS s + ' { }'
33
+ assert_equal s, doc.rule_sets.first.selectors.first.to_css
34
+ end
35
+
36
+ end
31
37
 
32
38
  def test_hash_operator
33
39
  doc = CSSPool.CSS 'p { font: foo, #666; }'
@@ -99,10 +105,10 @@ module CSSPool
99
105
  div { background: red, blue; }
100
106
  }
101
107
  eocss
102
- assert_equal 1, doc.rule_sets.first.media.length
108
+ assert_equal 1, doc.rule_sets.first.media.media_list.length
103
109
 
104
110
  doc = CSSPool.CSS(doc.to_css)
105
- assert_equal 1, doc.rule_sets.first.media.length
111
+ assert_equal 1, doc.rule_sets.first.media.media_list.length
106
112
  end
107
113
 
108
114
  def test_multiple_media
@@ -115,12 +121,12 @@ module CSSPool
115
121
  div { background: red, blue; }
116
122
  }
117
123
  eocss
118
- assert_equal 2, doc.rule_sets.first.media.length
119
- assert_equal 1, doc.rule_sets[1].media.length
124
+ assert_equal 2, doc.rule_sets.first.media.media_list.length
125
+ assert_equal 1, doc.rule_sets[1].media.media_list.length
120
126
 
121
127
  doc = CSSPool.CSS(doc.to_css)
122
- assert_equal 2, doc.rule_sets.first.media.length
123
- assert_equal 1, doc.rule_sets[1].media.length
128
+ assert_equal 2, doc.rule_sets.first.media.media_list.length
129
+ assert_equal 1, doc.rule_sets[1].media.media_list.length
124
130
  end
125
131
 
126
132
  def test_import
@@ -131,12 +137,12 @@ module CSSPool
131
137
  eocss
132
138
 
133
139
  assert_equal 3, doc.import_rules.length
134
- assert_equal 2, doc.import_rules.last.media.length
140
+ assert_equal 2, doc.import_rules.last.media_list.length
135
141
 
136
142
  doc = CSSPool.CSS(doc.to_css)
137
143
 
138
144
  assert_equal 3, doc.import_rules.length
139
- assert_equal 2, doc.import_rules.last.media.length
145
+ assert_equal 2, doc.import_rules.last.media_list.length
140
146
  end
141
147
 
142
148
  def test_charsets
@@ -166,7 +172,8 @@ module CSSPool
166
172
  "new\nline" => "[new\\00000aline=\"value\"]"
167
173
  }
168
174
  input_output.each_pair do |input, output|
169
- Selectors::Attribute.new input, 'value', Selectors::Attribute::EQUALS
175
+ node = Selectors::Attribute.new input, 'value', Selectors::Attribute::EQUALS
176
+ assert_equal output, node.to_css
170
177
  end
171
178
  end
172
179
 
@@ -182,14 +189,18 @@ module CSSPool
182
189
  end
183
190
 
184
191
  input_output = {
185
- "" => ":psuedo()",
186
- "ident" => ":psuedo(ident)",
187
- " " => ":psuedo(\\ )",
188
- "\"quote\"" => ":psuedo(\\000022quoted\\000022)"
192
+ "" => ":pseudo()",
193
+ "ident" => ":pseudo(ident)",
194
+ " " => ":pseudo(\\ )",
195
+ "\"quoted\"" => ":pseudo(\\000022quoted\\000022)"
189
196
  }
190
197
  input_output.each_pair do |input, output|
191
- Selectors::Attribute.new input, 'value', Selectors::Attribute::EQUALS
198
+ node = Selectors::PseudoClass.new "pseudo", input
199
+ assert_equal output, node.to_css
192
200
  end
201
+
202
+ assert_equal "::before", Selectors::PseudoElement.new("before").to_css
203
+ assert_equal ":before", Selectors::PseudoElement.new("before", true).to_css
193
204
  end
194
205
 
195
206
  def test_selector_other