csspool 3.0.2 → 4.0.0.pre

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 (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