csspool 2.0.0 → 3.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 (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