csspool 2.0.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/.gemtest +0 -0
  2. data/CHANGELOG.rdoc +6 -0
  3. data/Manifest.txt +10 -14
  4. data/README.rdoc +8 -21
  5. data/Rakefile +36 -2
  6. data/lib/csspool/collection.rb +2 -2
  7. data/lib/csspool/css/charset.rb +8 -2
  8. data/lib/csspool/css/declaration.rb +13 -2
  9. data/lib/csspool/css/document_handler.rb +3 -3
  10. data/lib/csspool/css/import_rule.rb +15 -3
  11. data/lib/csspool/css/media.rb +8 -2
  12. data/lib/csspool/css/parser.rb +1090 -0
  13. data/lib/csspool/css/parser.y +347 -0
  14. data/lib/csspool/css/rule_set.rb +8 -3
  15. data/lib/csspool/css/tokenizer.rb +228 -0
  16. data/lib/csspool/css/tokenizer.rex +96 -0
  17. data/lib/csspool/css.rb +1 -0
  18. data/lib/csspool/node.rb +29 -1
  19. data/lib/csspool/sac/document.rb +3 -3
  20. data/lib/csspool/sac/parser.rb +6 -112
  21. data/lib/csspool/terms/function.rb +1 -1
  22. data/lib/csspool/terms/ident.rb +1 -1
  23. data/lib/csspool/terms/number.rb +1 -1
  24. data/lib/csspool/terms/rgb.rb +1 -4
  25. data/lib/csspool/terms/string.rb +1 -1
  26. data/lib/csspool/visitors/children.rb +50 -0
  27. data/lib/csspool/visitors/comparable.rb +9 -3
  28. data/lib/csspool/visitors/iterator.rb +80 -0
  29. data/lib/csspool/visitors/to_css.rb +61 -45
  30. data/lib/csspool/visitors.rb +2 -0
  31. data/lib/csspool.rb +6 -3
  32. data/test/css/test_parser.rb +412 -0
  33. data/test/css/test_tokenizer.rb +320 -0
  34. data/test/helper.rb +2 -2
  35. data/test/sac/test_parser.rb +3 -8
  36. data/test/sac/test_terms.rb +128 -34
  37. data/test/test_collection.rb +1 -1
  38. data/test/test_parser.rb +1 -1
  39. data/test/visitors/test_children.rb +20 -0
  40. data/test/visitors/test_comparable.rb +31 -1
  41. data/test/visitors/test_each.rb +19 -0
  42. data/test/visitors/test_to_css.rb +125 -1
  43. metadata +90 -68
  44. data/lib/csspool/lib_croco/cr_additional_sel.rb +0 -46
  45. data/lib/csspool/lib_croco/cr_attr_sel.rb +0 -16
  46. data/lib/csspool/lib_croco/cr_doc_handler.rb +0 -24
  47. data/lib/csspool/lib_croco/cr_num.rb +0 -13
  48. data/lib/csspool/lib_croco/cr_parser.rb +0 -11
  49. data/lib/csspool/lib_croco/cr_parsing_location.rb +0 -17
  50. data/lib/csspool/lib_croco/cr_pseudo.rb +0 -14
  51. data/lib/csspool/lib_croco/cr_rgb.rb +0 -18
  52. data/lib/csspool/lib_croco/cr_selector.rb +0 -34
  53. data/lib/csspool/lib_croco/cr_simple_sel.rb +0 -54
  54. data/lib/csspool/lib_croco/cr_term.rb +0 -97
  55. data/lib/csspool/lib_croco/glist.rb +0 -21
  56. data/lib/csspool/lib_croco.rb +0 -78
  57. data/lib/csspool/visitable.rb +0 -18
@@ -0,0 +1,320 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require "helper"
4
+
5
+ module CSSPool
6
+ module CSS
7
+ class TestTokenizer < CSSPool::TestCase
8
+ def setup
9
+ super
10
+ @scanner = Class.new(CSSPool::CSS::Tokenizer) {
11
+ def do_parse
12
+ end
13
+ }.new
14
+ end
15
+
16
+ {
17
+ 'em' => :EMS,
18
+ 'ex' => :EXS,
19
+ 'px' => :LENGTH,
20
+ 'cm' => :LENGTH,
21
+ 'mm' => :LENGTH,
22
+ 'in' => :LENGTH,
23
+ 'pt' => :LENGTH,
24
+ 'pc' => :LENGTH,
25
+ 'deg' => :ANGLE,
26
+ 'rad' => :ANGLE,
27
+ 'grad' => :ANGLE,
28
+ 'ms' => :TIME,
29
+ 's' => :TIME,
30
+ 'hz' => :FREQ,
31
+ 'khz' => :FREQ,
32
+ '%' => :PERCENTAGE,
33
+ }.each do |unit,sym|
34
+ define_method :"test_#{unit}" do
35
+ ['10', '0.1'].each do |num|
36
+ num = "#{num}#{unit}"
37
+ [num, " #{num}", "#{num} ", " #{num} "].each do |str|
38
+ @scanner.scan str
39
+ assert_tokens([[sym, str]], @scanner)
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ def test_num
46
+ ['10', '0.1'].each do |num|
47
+ [num, " #{num}", "#{num} ", " #{num} "].each do |str|
48
+ @scanner.scan str
49
+ assert_tokens([[:NUMBER, str]], @scanner)
50
+ end
51
+ end
52
+ end
53
+
54
+ def test_important
55
+ [
56
+ '!important',
57
+ ' !important',
58
+ '!important ',
59
+ '! important ',
60
+ ' ! important ',
61
+ ].each do |str|
62
+ @scanner.scan str
63
+ assert_tokens([[:IMPORTANT_SYM, str]], @scanner)
64
+ end
65
+ end
66
+
67
+ {
68
+ '@page' => :PAGE_SYM,
69
+ '@import' => :IMPORT_SYM,
70
+ '@media' => :MEDIA_SYM,
71
+ '@charset' => :CHARSET_SYM,
72
+ }.each do |k,v|
73
+ define_method(:"test_#{k.sub(/@/, '')}") do
74
+ [k, " #{k}", "#{k} ", " #{k} "].each do |str|
75
+ @scanner.scan str
76
+ assert_tokens([[v, str]], @scanner)
77
+ end
78
+ end
79
+ end
80
+
81
+ def test_invalid
82
+ str = "'internet"
83
+ @scanner.scan str
84
+ assert_tokens([[:INVALID, str]], @scanner)
85
+
86
+ str = '"internet'
87
+ @scanner.scan str
88
+ assert_tokens([[:INVALID, str]], @scanner)
89
+ end
90
+
91
+ #def test_comment
92
+ # str = "/**** Hello World ***/"
93
+ # @scanner.scan str
94
+ # assert_tokens([[:COMMENT, str]], @scanner)
95
+
96
+ # str = "/* Hello World */"
97
+ # @scanner.scan str
98
+ # assert_tokens([[:COMMENT, str]], @scanner)
99
+ #end
100
+
101
+ def test_rbrace
102
+ str = " } \n "
103
+ @scanner.scan str
104
+ assert_tokens([[:RBRACE, str]], @scanner)
105
+ end
106
+
107
+ def test_lbrace
108
+ str = " { "
109
+ @scanner.scan str
110
+ assert_tokens([[:LBRACE, str]], @scanner)
111
+ end
112
+
113
+ def test_semi
114
+ str = " ; "
115
+ @scanner.scan str
116
+ assert_tokens([[:SEMI, ';']], @scanner)
117
+ end
118
+
119
+ def test_cdc
120
+ @scanner.scan("-->")
121
+ assert_tokens([[:CDC, "-->"]], @scanner)
122
+ end
123
+
124
+ def test_cdo
125
+ @scanner.scan("<!--")
126
+ assert_tokens([[:CDO, "<!--"]], @scanner)
127
+ end
128
+
129
+ def test_unicode_range
130
+ @scanner.scan("U+0-10FFFF")
131
+ assert_tokens([[:UNICODE_RANGE, "U+0-10FFFF"]], @scanner)
132
+ end
133
+
134
+ def test_url_with_string
135
+ @scanner.scan("url('http://tlm.com')")
136
+ assert_tokens([[:URI, "url('http://tlm.com')"]], @scanner)
137
+ end
138
+
139
+ def test_url_with_others
140
+ @scanner.scan("url(http://tlm.com?f&b)")
141
+ assert_tokens([[:URI, "url(http://tlm.com?f&b)"]], @scanner)
142
+ end
143
+
144
+ def test_unicode
145
+ @scanner.scan("a日本語")
146
+ assert_tokens([[:IDENT, 'a日本語']], @scanner)
147
+ end
148
+
149
+ def test_tokenize_bad_percent
150
+ @scanner.scan("%")
151
+ assert_tokens([["%", "%"]], @scanner)
152
+ end
153
+
154
+ def test_not_equal
155
+ @scanner.scan("h1[a!='Tender Lovemaking']")
156
+ assert_tokens([ [:IDENT, 'h1'],
157
+ [:LSQUARE, '['],
158
+ [:IDENT, 'a'],
159
+ [:NOT_EQUAL, '!='],
160
+ [:STRING, "'Tender Lovemaking'"],
161
+ [:RSQUARE, ']'],
162
+ ], @scanner)
163
+ end
164
+
165
+ def test_negation
166
+ @scanner.scan("p:not(.a)")
167
+ assert_tokens([ [:IDENT, 'p'],
168
+ [:NOT, ':not('],
169
+ ['.', '.'],
170
+ [:IDENT, 'a'],
171
+ [:RPAREN, ')'],
172
+ ], @scanner)
173
+ end
174
+
175
+ def test_function
176
+ @scanner.scan("script comment()")
177
+ assert_tokens([ [:IDENT, 'script'],
178
+ [:S, ' '],
179
+ [:FUNCTION, 'comment('],
180
+ [:RPAREN, ')'],
181
+ ], @scanner)
182
+ end
183
+
184
+ def test_preceding_selector
185
+ @scanner.scan("E ~ F")
186
+ assert_tokens([ [:IDENT, 'E'],
187
+ [:TILDE, ' ~ '],
188
+ [:IDENT, 'F'],
189
+ ], @scanner)
190
+ end
191
+
192
+ def test_scan_attribute_string
193
+ @scanner.scan("h1[a='Tender Lovemaking']")
194
+ assert_tokens([ [:IDENT, 'h1'],
195
+ [:LSQUARE, '['],
196
+ [:IDENT, 'a'],
197
+ [:EQUAL, '='],
198
+ [:STRING, "'Tender Lovemaking'"],
199
+ [:RSQUARE, ']'],
200
+ ], @scanner)
201
+ @scanner.scan('h1[a="Tender Lovemaking"]')
202
+ assert_tokens([ [:IDENT, 'h1'],
203
+ [:LSQUARE, '['],
204
+ [:IDENT, 'a'],
205
+ [:EQUAL, '='],
206
+ [:STRING, '"Tender Lovemaking"'],
207
+ [:RSQUARE, ']'],
208
+ ], @scanner)
209
+ end
210
+
211
+ def test_scan_id
212
+ @scanner.scan('#foo')
213
+ assert_tokens([ [:HASH, '#foo'] ], @scanner)
214
+ end
215
+
216
+ def test_scan_pseudo
217
+ @scanner.scan('a:visited')
218
+ assert_tokens([ [:IDENT, 'a'],
219
+ [':', ':'],
220
+ [:IDENT, 'visited']
221
+ ], @scanner)
222
+ end
223
+
224
+ def test_scan_star
225
+ @scanner.scan('*')
226
+ assert_tokens([ [:STAR, '*'], ], @scanner)
227
+ end
228
+
229
+ def test_ident_with_minus
230
+ @scanner.scan('-book')
231
+ assert_tokens([ [:IDENT, '-book'], ], @scanner)
232
+ end
233
+
234
+ def test_scan_class
235
+ @scanner.scan('x.awesome')
236
+ assert_tokens([ [:IDENT, 'x'],
237
+ ['.', '.'],
238
+ [:IDENT, 'awesome'],
239
+ ], @scanner)
240
+ end
241
+
242
+ def test_scan_greater
243
+ @scanner.scan('x > y')
244
+ assert_tokens([ [:IDENT, 'x'],
245
+ [:GREATER, ' > '],
246
+ [:IDENT, 'y']
247
+ ], @scanner)
248
+ end
249
+
250
+ def test_scan_slash
251
+ @scanner.scan('x/y')
252
+ assert_tokens([ [:IDENT, 'x'],
253
+ [:SLASH, '/'],
254
+ [:IDENT, 'y']
255
+ ], @scanner)
256
+ end
257
+
258
+ def test_scan_doubleslash
259
+ @scanner.scan('x//y')
260
+ assert_tokens([ [:IDENT, 'x'],
261
+ [:DOUBLESLASH, '//'],
262
+ [:IDENT, 'y']
263
+ ], @scanner)
264
+ end
265
+
266
+ def test_scan_function_selector
267
+ @scanner.scan('x:eq(0)')
268
+ assert_tokens([ [:IDENT, 'x'],
269
+ [':', ':'],
270
+ [:FUNCTION, 'eq('],
271
+ [:NUMBER, "0"],
272
+ [:RPAREN, ')'],
273
+ ], @scanner)
274
+ end
275
+
276
+ def test_scan_an_plus_b
277
+ @scanner.scan('x:nth-child(5n+3)')
278
+ assert_tokens([ [:IDENT, 'x'],
279
+ [':', ':'],
280
+ [:FUNCTION, 'nth-child('],
281
+ [:NUMBER, '5'],
282
+ [:IDENT, 'n'],
283
+ [:PLUS, '+'],
284
+ [:NUMBER, '3'],
285
+ [:RPAREN, ')'],
286
+ ], @scanner)
287
+
288
+ @scanner.scan('x:nth-child(-1n+3)')
289
+ assert_tokens([ [:IDENT, 'x'],
290
+ [':', ':'],
291
+ [:FUNCTION, 'nth-child('],
292
+ [:MINUS, '-'],
293
+ [:NUMBER, '1'],
294
+ [:IDENT, 'n'],
295
+ [:PLUS, '+'],
296
+ [:NUMBER, '3'],
297
+ [:RPAREN, ')'],
298
+ ], @scanner)
299
+
300
+ @scanner.scan('x:nth-child(-n+3)')
301
+ assert_tokens([ [:IDENT, 'x'],
302
+ [':', ':'],
303
+ [:FUNCTION, 'nth-child('],
304
+ [:IDENT, '-n'],
305
+ [:PLUS, '+'],
306
+ [:NUMBER, '3'],
307
+ [:RPAREN, ')'],
308
+ ], @scanner)
309
+ end
310
+
311
+ def assert_tokens(tokens, scanner)
312
+ toks = []
313
+ while tok = @scanner.next_token
314
+ toks << tok
315
+ end
316
+ assert_equal(tokens, toks)
317
+ end
318
+ end
319
+ end
320
+ end
data/test/helper.rb CHANGED
@@ -9,7 +9,7 @@ module CSSPool
9
9
 
10
10
  ASSET_DIR = File.join(File.dirname(__FILE__), 'files')
11
11
 
12
- class MyDoc < CSSPool::SAC::Document
12
+ class MyDoc < CSSPool::CSS::DocumentHandler
13
13
  attr_accessor :start_documents, :end_documents
14
14
  attr_accessor :charsets, :import_styles, :comments, :start_selectors
15
15
  attr_accessor :end_selectors, :properties
@@ -41,7 +41,7 @@ module CSSPool
41
41
  @charsets << [name, location]
42
42
  end
43
43
 
44
- def import_style media_list, uri, default_ns, location
44
+ def import_style media_list, uri, default_ns = nil, location = {}
45
45
  @import_styles << [media_list, uri, default_ns, location]
46
46
  end
47
47
 
@@ -35,15 +35,13 @@ module CSSPool
35
35
  end
36
36
 
37
37
  def test_charset
38
- assert_equal(
39
- [["UTF-8", { :line => 1, :byte_offset => 10, :column => 11}]],
40
- @doc.charsets)
38
+ assert_equal("UTF-8", @doc.charsets.first.first)
41
39
  end
42
40
 
43
41
  def test_import_style
44
42
  styles = @doc.import_styles.first
45
- assert_equal ["screen"], styles.first
46
- assert_equal "foo.css", styles[1]
43
+ assert_equal "screen", styles.first.first.value
44
+ assert_equal "foo.css", styles[1].value
47
45
  assert_nil styles[2]
48
46
  end
49
47
 
@@ -57,9 +55,6 @@ module CSSPool
57
55
  selectors_for_rule = @doc.start_selectors.first
58
56
  selector = selectors_for_rule.first # => div a.foo
59
57
  assert_equal 2, selector.simple_selectors.length
60
- selector.simple_selectors.each do |ss|
61
- assert ss.parse_location
62
- end
63
58
  end
64
59
 
65
60
  def test_additional_selector_list
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  require 'helper'
2
3
 
3
4
  module CSSPool
@@ -21,23 +22,21 @@ module CSSPool
21
22
  div { border: rgb(1,2,3); }
22
23
  eocss
23
24
  color = @doc.properties.first[1].first
24
- assert_equal 1, color.red
25
- assert_equal 2, color.green
26
- assert_equal 3, color.blue
27
- assert !color.percentage?
28
- assert_match('rgb(1,2,3)', color.to_css)
25
+ assert_equal 1, color.red.value
26
+ assert_equal 2, color.green.value
27
+ assert_equal 3, color.blue.value
28
+ assert_match('rgb(1, 2, 3)', color.to_css)
29
29
  end
30
30
 
31
31
  def test_rgb_with_percentage
32
32
  @parser.parse <<-eocss
33
- div { border: rgb(100%,2%,3%); }
33
+ div { border: rgb(100%, 2%, 3%); }
34
34
  eocss
35
35
  color = @doc.properties.first[1].first
36
- assert_equal 100, color.red
37
- assert_equal 2, color.green
38
- assert_equal 3, color.blue
39
- assert color.percentage?
40
- assert_match('rgb(100%,2%,3%)', color.to_css)
36
+ assert_equal 100, color.red.value
37
+ assert_equal 2, color.green.value
38
+ assert_equal 3, color.blue.value
39
+ assert_match('rgb(100%, 2%, 3%)', color.to_css)
41
40
  end
42
41
 
43
42
  def test_negative_number
@@ -48,8 +47,8 @@ module CSSPool
48
47
  size = @doc.properties.first[1].first
49
48
  assert_equal :minus, size.unary_operator
50
49
  assert_equal 1, size.value
51
- assert_equal '-1.0px', size.to_s
52
- assert_equal '-1.0px', size.to_css
50
+ assert_equal '-1px', size.to_s
51
+ assert_equal '-1px', size.to_css
53
52
  end
54
53
 
55
54
  def test_positive_number
@@ -59,13 +58,12 @@ module CSSPool
59
58
  assert_equal 1, @doc.properties.length
60
59
  size = @doc.properties.first[1].first
61
60
  assert_equal 1, size.value
62
- assert_equal '1.0px', size.to_s
61
+ assert_equal '1px', size.to_s
63
62
  end
64
63
 
65
64
  %w{
66
65
  1 1em 1ex 1px 1in 1cm 1mm 1pt 1pc 1% 1deg 1rad 1ms 1s 1Hz 1kHz
67
66
  }.each do |num|
68
- expected = num.sub(/1/, '1.0')
69
67
  define_method(:"test_num_#{num}") do
70
68
  @parser.parse <<-eocss
71
69
  div { border: #{num}; }
@@ -73,19 +71,68 @@ module CSSPool
73
71
  assert_equal 1, @doc.properties.length
74
72
  size = @doc.properties.first[1].first
75
73
  assert_equal 1, size.value
76
- assert_equal expected, size.to_s
77
- assert_equal expected, size.to_css
74
+ assert_equal num, size.to_s
75
+ assert_equal num, size.to_css
78
76
  end
79
77
  end
80
78
 
79
+ def test_selector_attribute
80
+ @parser.parse <<-eocss
81
+ div[attr = value] { }
82
+ div[attr\\== value] { }
83
+ div[attr="\\"quotes\\""] { }
84
+ div[attr = unicode\\ \\1D11E\\BF ] { }
85
+ eocss
86
+
87
+ attrs = @doc.end_selectors.flatten.map(&:simple_selectors).flatten.map(&:additional_selectors).flatten
88
+ assert_equal 4, attrs.length
89
+
90
+ attrs.shift.tap do |attr|
91
+ assert_equal "attr", attr.name,
92
+ "Interprets name."
93
+ assert_equal "value", attr.value,
94
+ "Interprets bare value."
95
+ end
96
+
97
+ assert_equal "attr=", attrs.shift.name,
98
+ "Interprets identifier escapes."
99
+
100
+ assert_equal "\"quotes\"", attrs.shift.value,
101
+ "Interprets quoted values."
102
+
103
+ assert_equal "unicode \360\235\204\236\302\277", attrs.shift.value,
104
+ "Interprets unicode escapes."
105
+ end
106
+
81
107
  def test_string_term
82
108
  @parser.parse <<-eocss
83
- div { border: "hello"; }
109
+ div { content: "basic"; }
110
+ div { content: "\\"quotes\\""; }
111
+ div { content: "unicode \\1D11E\\BF "; }
112
+ div { content: "contin\\\nuation"; }
113
+ div { content: "new\\aline"; }
114
+ div { content: "\\11FFFF "; }
84
115
  eocss
85
- assert_equal 1, @doc.properties.length
86
- string = @doc.properties.first[1].first
87
- assert_equal 'hello', string.value
88
- assert_equal '"hello"', string.to_css
116
+ terms = @doc.properties.map {|s| s[1].first}
117
+ assert_equal 6, terms.length
118
+
119
+ assert_equal 'basic', terms.shift.value,
120
+ "Recognizes a basic string"
121
+
122
+ assert_equal "\"quotes\"", terms.shift.value,
123
+ "Recognizes strings containing quotes."
124
+
125
+ assert_equal "unicode \360\235\204\236\302\277", terms.shift.value,
126
+ "Interprets unicode escapes."
127
+
128
+ assert_equal "continuation", terms.shift.value,
129
+ "Supports line continuation."
130
+
131
+ assert_equal "new\nline", terms.shift.value,
132
+ "Interprets newline escape."
133
+
134
+ assert_equal "\357\277\275", terms.shift.value,
135
+ "Kills absurd characters."
89
136
  end
90
137
 
91
138
  def test_inherit
@@ -108,26 +155,73 @@ module CSSPool
108
155
  assert_equal 'inherit', string.to_css
109
156
  end
110
157
 
158
+ def test_declaration
159
+ @parser.parse <<-eocss
160
+ div { property: value; }
161
+ div { colon\\:: value; }
162
+ div { space\\ : value; }
163
+ eocss
164
+ properties = @doc.properties.map {|s| s[0]}
165
+ assert_equal 3, properties.length
166
+
167
+ assert_equal 'property', properties.shift,
168
+ "Recognizes basic function."
169
+
170
+ assert_equal 'colon:', properties.shift,
171
+ "Recognizes property with escaped COLON."
172
+
173
+ assert_equal 'space ', properties.shift,
174
+ "Recognizes property with escaped SPACE."
175
+ end
176
+
111
177
  def test_function
112
178
  @parser.parse <<-eocss
113
- div { border: foo("hello"); }
179
+ div { content: attr(\"value\", ident); }
180
+ div { content: \\30(\"value\", ident); }
181
+ div { content: a\\ function(\"value\", ident); }
182
+ div { content: a\\((\"value\", ident); }
114
183
  eocss
115
- assert_equal 1, @doc.properties.length
116
- func = @doc.properties.first[1].first
117
- assert_equal 'foo', func.name
118
- assert_equal 1, func.params.length
119
- assert_equal 'hello', func.params.first.value
120
- assert_match 'foo("hello")', func.to_css
184
+ terms = @doc.properties.map {|s| s[1].first}
185
+ assert_equal 4, terms.length
186
+
187
+ assert_equal 'attr', terms.shift.name,
188
+ "Recognizes basic function."
189
+
190
+ assert_equal '0', terms.shift.name,
191
+ "Recognizes numeric function."
192
+
193
+ assert_equal 'a function', terms.shift.name,
194
+ "Recognizes function with escaped SPACE."
195
+
196
+ assert_equal 'a(', terms.shift.name,
197
+ "Recognizes function with escaped LPAREN."
121
198
  end
122
199
 
123
200
  def test_uri
124
201
  @parser.parse <<-eocss
125
- div { border: url(http://tenderlovemaking.com/); }
202
+ div { background: url(http://example.com/); }
203
+ div { background: url( http://example.com/ ); }
204
+ div { background: url("http://example.com/"); }
205
+ div { background: url( " http://example.com/ " ); }
206
+ div { background: url(http://example.com/\\"); }
126
207
  eocss
127
- assert_equal 1, @doc.properties.length
128
- url = @doc.properties.first[1].first
129
- assert_equal 'http://tenderlovemaking.com/', url.value
130
- assert_match 'url(http://tenderlovemaking.com/)', url.to_css
208
+ terms = @doc.properties.map {|s| s[1].first}
209
+ assert_equal 5, terms.length
210
+
211
+ assert_equal 'http://example.com/', terms.shift.value,
212
+ "Recognizes bare URI."
213
+
214
+ assert_equal 'http://example.com/', terms.shift.value,
215
+ "Recognize URI with spaces"
216
+
217
+ assert_equal 'http://example.com/', terms.shift.value,
218
+ "Recognize quoted URI"
219
+
220
+ assert_equal ' http://example.com/ ', terms.shift.value,
221
+ "Recognize quoted URI"
222
+
223
+ assert_equal 'http://example.com/"', terms.shift.value,
224
+ "Recognizes bare URI with quotes"
131
225
  end
132
226
  end
133
227
  end
@@ -65,7 +65,7 @@ module CSSPool
65
65
  }
66
66
 
67
67
  collection = CSSPool::Collection.new do |url|
68
- css[url] || raise
68
+ css[url] || raise(url.inspect)
69
69
  end
70
70
 
71
71
  collection << '@import url(foo.css);'
data/test/test_parser.rb CHANGED
@@ -85,7 +85,7 @@ module CSSPool
85
85
  doc = CSSPool.CSS <<-eocss
86
86
  div { border: foo(1, 2); }
87
87
  eocss
88
- assert_match('foo(1.0, 2.0)', doc.to_css)
88
+ assert_match('foo(1, 2)', doc.to_css)
89
89
  end
90
90
  end
91
91
  end
@@ -0,0 +1,20 @@
1
+ require 'helper'
2
+
3
+ module CSSPool
4
+ module Visitors
5
+ class TestChildren < CSSPool::TestCase
6
+ def test_iterate
7
+ doc = CSSPool.CSS <<-eocss
8
+ @charset "UTF-8";
9
+ @import url("foo.css") screen;
10
+ div#a, a.foo, a:hover, a[href][int="10"]{ background: red; }
11
+ eocss
12
+
13
+ stack = [doc]
14
+ until stack.empty? do
15
+ stack += stack.pop.children
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -7,6 +7,21 @@ module CSSPool
7
7
  doc1 = CSSPool.CSS css
8
8
  doc2 = CSSPool.CSS css
9
9
  assert_equal doc1, doc2
10
+
11
+ list1 = []
12
+ list2 = []
13
+
14
+ doc1.each { |node| list1 << node }
15
+ doc2.each { |node| list2 << node }
16
+
17
+ assert_equal list1, list2
18
+
19
+ stack = [doc1]
20
+ until stack.empty? do
21
+ stack += stack.pop.children
22
+ end
23
+
24
+ assert_equal doc1.hash, doc2.hash
10
25
  end
11
26
 
12
27
  def test_not_equal
@@ -18,6 +33,22 @@ module CSSPool
18
33
  equalitest 'div { border: #123; }'
19
34
  end
20
35
 
36
+ def test_div_with_id
37
+ equalitest 'div#foo { border: #123; }'
38
+ end
39
+
40
+ def test_div_with_pseudo
41
+ equalitest 'div:foo { border: #123; }'
42
+ end
43
+
44
+ def test_div_with_universal
45
+ equalitest '* { border: #123; }'
46
+ end
47
+
48
+ def test_simple
49
+ equalitest '.foo { border: #123; }'
50
+ end
51
+
21
52
  def test_rgb
22
53
  equalitest 'div { border: rgb(1,2,3); }'
23
54
  end
@@ -37,7 +68,6 @@ module CSSPool
37
68
  %w{
38
69
  1 1em 1ex 1px 1in 1cm 1mm 1pt 1pc 1% 1deg 1rad 1ms 1s 1Hz 1kHz
39
70
  }.each do |num|
40
- expected = num.sub(/1/, '1.0')
41
71
  define_method(:"test_num_#{num}") do
42
72
  equalitest "div { border: #{num}; }"
43
73
  end