css_parser 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +33 -0
- data/LICENSE +42 -0
- data/README +60 -0
- data/lib/css_parser/parser.rb +345 -0
- data/lib/css_parser/regexps.rb +46 -0
- data/lib/css_parser/rule_set.rb +381 -0
- data/lib/css_parser.rb +149 -0
- data/test/fixtures/import-circular-reference.css +4 -0
- data/test/fixtures/import-with-media-types.css +3 -0
- data/test/fixtures/import1.css +3 -0
- data/test/fixtures/simple.css +6 -0
- data/test/fixtures/subdir/import2.css +3 -0
- data/test/test_css_parser_basic.rb +56 -0
- data/test/test_css_parser_downloading.rb +81 -0
- data/test/test_css_parser_media_types.rb +71 -0
- data/test/test_css_parser_misc.rb +143 -0
- data/test/test_css_parser_regexps.rb +68 -0
- data/test/test_helper.rb +8 -0
- data/test/test_merging.rb +88 -0
- data/test/test_rule_set.rb +74 -0
- data/test/test_rule_set_creating_shorthand.rb +90 -0
- data/test/test_rule_set_expanding_shorthand.rb +178 -0
- metadata +82 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
# Test cases for the handling of media types
|
4
|
+
class CssParserMediaTypesTests < Test::Unit::TestCase
|
5
|
+
include CssParser
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@cp = Parser.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_finding_by_media_type
|
12
|
+
# from http://www.w3.org/TR/CSS21/media.html#at-media-rule
|
13
|
+
css = <<-EOT
|
14
|
+
@media print {
|
15
|
+
body { font-size: 10pt }
|
16
|
+
}
|
17
|
+
@media screen {
|
18
|
+
body { font-size: 13px }
|
19
|
+
}
|
20
|
+
@media screen, print {
|
21
|
+
body { line-height: 1.2 }
|
22
|
+
}
|
23
|
+
EOT
|
24
|
+
|
25
|
+
@cp.add_block!(css)
|
26
|
+
|
27
|
+
assert_equal 'font-size: 10pt; line-height: 1.2;', @cp.find_by_selector('body', :print).join(' ')
|
28
|
+
assert_equal 'font-size: 13px; line-height: 1.2;', @cp.find_by_selector('body', :screen).join(' ')
|
29
|
+
end
|
30
|
+
|
31
|
+
def atest_finding_by_multiple_media_types
|
32
|
+
css = <<-EOT
|
33
|
+
@media print {
|
34
|
+
body { font-size: 10pt }
|
35
|
+
}
|
36
|
+
@media handheld {
|
37
|
+
body { font-size: 13px }
|
38
|
+
}
|
39
|
+
@media screen, print {
|
40
|
+
body { line-height: 1.2 }
|
41
|
+
}
|
42
|
+
EOT
|
43
|
+
@cp.add_block!(css)
|
44
|
+
|
45
|
+
assert_equal 'font-size: 13px; line-height: 1.2;', @cp.find_by_selector('body', [:screen,:handheld]).join(' ')
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_adding_block_with_media_types
|
49
|
+
css = <<-EOT
|
50
|
+
body { font-size: 10pt }
|
51
|
+
EOT
|
52
|
+
|
53
|
+
@cp.add_block!(css, :media_types => [:screen])
|
54
|
+
|
55
|
+
assert_equal 'font-size: 10pt;', @cp.find_by_selector('body', :screen).join(' ')
|
56
|
+
assert @cp.find_by_selector('body', :handheld).empty?
|
57
|
+
end
|
58
|
+
|
59
|
+
def atest_adding_rule_set_with_media_type
|
60
|
+
@cp.add_rule!('body', 'color: black;', [:handheld,:tty])
|
61
|
+
@cp.add_rule!('body', 'color: blue;', :screen)
|
62
|
+
assert_equal 'color: black;', @cp.find_by_selector('body', :handheld).join(' ')
|
63
|
+
end
|
64
|
+
|
65
|
+
def atest_selecting_with_all_meda_type
|
66
|
+
@cp.add_rule!('body', 'color: black;', [:handheld,:tty])
|
67
|
+
assert_equal 'color: black;', @cp.find_by_selector('body', :all).join(' ')
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
# Test cases for the CssParser.
|
4
|
+
class CssParserTests < Test::Unit::TestCase
|
5
|
+
include CssParser
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@cp = Parser.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_at_page_rule
|
12
|
+
# from http://www.w3.org/TR/CSS21/page.html#page-selectors
|
13
|
+
css = <<-EOT
|
14
|
+
@page { margin: 2cm }
|
15
|
+
|
16
|
+
@page :first {
|
17
|
+
margin-top: 10cm
|
18
|
+
}
|
19
|
+
EOT
|
20
|
+
|
21
|
+
@cp.add_block!(css)
|
22
|
+
|
23
|
+
assert_equal 'margin: 2cm;', @cp.find_by_selector('@page').join(' ')
|
24
|
+
assert_equal 'margin-top: 10cm;', @cp.find_by_selector('@page :first').join(' ')
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_should_ignore_comments
|
28
|
+
# see http://www.w3.org/Style/CSS/Test/CSS2.1/current/html4/t040109-c17-comments-00-b.htm
|
29
|
+
css =<<-EOT
|
30
|
+
/* This is a CSS comment. */
|
31
|
+
.one {color: green;} /* Another comment */
|
32
|
+
/* The following should not be used:
|
33
|
+
.one {color: red;} */
|
34
|
+
.two {color: green; /* color: yellow; */}
|
35
|
+
/**
|
36
|
+
.three {color: red;} */
|
37
|
+
.three {color: green;}
|
38
|
+
/**/
|
39
|
+
.four {color: green;}
|
40
|
+
/*********/
|
41
|
+
.five {color: green;}
|
42
|
+
/* a comment **/
|
43
|
+
.six {color: green;}
|
44
|
+
EOT
|
45
|
+
|
46
|
+
@cp.add_block!(css)
|
47
|
+
@cp.each_selector do |sel, decs, spec|
|
48
|
+
assert_equal 'color: green;', decs
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_parsing_blocks
|
53
|
+
# dervived from http://www.w3.org/TR/CSS21/syndata.html#rule-sets
|
54
|
+
css = <<-EOT
|
55
|
+
div[name='test'] {
|
56
|
+
|
57
|
+
color:
|
58
|
+
|
59
|
+
red;
|
60
|
+
|
61
|
+
}div:hover{coloR:red;
|
62
|
+
}div:first-letter{color:red;/*color:blue;}"commented out"*/}
|
63
|
+
|
64
|
+
p[example="public class foo\
|
65
|
+
{\
|
66
|
+
private string x;\
|
67
|
+
\
|
68
|
+
foo(int x) {\
|
69
|
+
this.x = 'test';\
|
70
|
+
this.x = \"test\";\
|
71
|
+
}\
|
72
|
+
\
|
73
|
+
}"] { color: red }
|
74
|
+
|
75
|
+
p { color:red}
|
76
|
+
EOT
|
77
|
+
|
78
|
+
@cp.add_block!(css)
|
79
|
+
|
80
|
+
@cp.each_selector do |sel, decs, spec|
|
81
|
+
assert_equal 'color: red;', decs
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_ignoring_malformed_declarations
|
86
|
+
flunk
|
87
|
+
# dervived from http://www.w3.org/TR/CSS21/syndata.html#parsing-errors
|
88
|
+
css = <<-EOT
|
89
|
+
p { color:green }
|
90
|
+
p { color:green; color } /* malformed declaration missing ':', value */
|
91
|
+
p { color:red; color; color:green } /* same with expected recovery */
|
92
|
+
p { color:green; color: } /* malformed declaration missing value */
|
93
|
+
p { color:red; color:; color:green } /* same with expected recovery */
|
94
|
+
p { color:green; color{;color:maroon} } /* unexpected tokens { } */
|
95
|
+
p { color:red; color{;color:maroon}; color:green } /* same with recovery */
|
96
|
+
EOT
|
97
|
+
|
98
|
+
@cp.add_block!(css)
|
99
|
+
|
100
|
+
@cp.each_selector do |sel, decs, spec|
|
101
|
+
assert_equal 'color: green;', decs
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_calculating_specificity
|
106
|
+
# from http://www.w3.org/TR/CSS21/cascade.html#specificity
|
107
|
+
assert_equal 0, CssParser.calculate_specificity('*')
|
108
|
+
assert_equal 1, CssParser.calculate_specificity('li')
|
109
|
+
assert_equal 2, CssParser.calculate_specificity('li:first-line')
|
110
|
+
assert_equal 2, CssParser.calculate_specificity('ul li')
|
111
|
+
assert_equal 3, CssParser.calculate_specificity('ul ol+li')
|
112
|
+
assert_equal 11, CssParser.calculate_specificity('h1 + *[rel=up]')
|
113
|
+
assert_equal 13, CssParser.calculate_specificity('ul ol li.red')
|
114
|
+
assert_equal 21, CssParser.calculate_specificity('li.red.level')
|
115
|
+
assert_equal 100, CssParser.calculate_specificity('#x34y')
|
116
|
+
|
117
|
+
# from http://www.hixie.ch/tests/adhoc/css/cascade/specificity/003.html
|
118
|
+
assert_equal CssParser.calculate_specificity('div *'), CssParser.calculate_specificity('p')
|
119
|
+
assert CssParser.calculate_specificity('body div *') > CssParser.calculate_specificity('div *')
|
120
|
+
|
121
|
+
# other tests
|
122
|
+
assert_equal 11, CssParser.calculate_specificity('h1[id|=123]')
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_converting_uris
|
126
|
+
base_uri = 'http://www.example.org/style/basic.css'
|
127
|
+
["body { background: url(yellow) };", "body { background: url('yellow') };",
|
128
|
+
"body { background: url('/style/yellow') };",
|
129
|
+
"body { background: url(\"../style/yellow\") };",
|
130
|
+
"body { background: url(\"lib/../../style/yellow\") };"].each do |css|
|
131
|
+
converted_css = CssParser.convert_uris(css, base_uri)
|
132
|
+
assert_equal "body { background: url('http://www.example.org/style/yellow') };", converted_css
|
133
|
+
end
|
134
|
+
|
135
|
+
converted_css = CssParser.convert_uris("body { background: url(../style/yellow-dot_symbol$.png?abc=123&def=456&ghi=789#1011) };", base_uri)
|
136
|
+
assert_equal "body { background: url('http://www.example.org/style/yellow-dot_symbol$.png?abc=123&def=456&ghi=789#1011') };", converted_css
|
137
|
+
|
138
|
+
# taken from error log: 2007-10-23 04:37:41#2399
|
139
|
+
converted_css = CssParser.convert_uris('.specs {font-family:Helvetica;font-weight:bold;font-style:italic;color:#008CA8;font-size:1.4em;list-style-image:url("images/bullet.gif");}', 'http://www.example.org/directory/file.html')
|
140
|
+
assert_equal ".specs {font-family:Helvetica;font-weight:bold;font-style:italic;color:#008CA8;font-size:1.4em;list-style-image:url('http://www.example.org/directory/images/bullet.gif');}", converted_css
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
# Test cases for CSS regular expressions
|
4
|
+
#
|
5
|
+
# see http://www.w3.org/TR/CSS21/syndata.html and
|
6
|
+
# http://www.w3.org/TR/CSS21/grammar.html
|
7
|
+
class CssParserRegexpTests < Test::Unit::TestCase
|
8
|
+
def test_strings
|
9
|
+
# complete matches
|
10
|
+
['"abcd"', '" A sd s�drcv \'dsf\' asd rfg asd"', '"A\ d??ef 123!"',
|
11
|
+
"\"this is\\\n a test\"", '"back\67round"', '"r\000065 ed"',
|
12
|
+
"'abcd'", "' A sd sedrcv \"dsf\" asd rf�&23$%#%$g asd'", "'A\\\n def 123!'",
|
13
|
+
"'this is\\\n a test'", "'back\\67round'", "'r\\000065 ed'"
|
14
|
+
].each do |str|
|
15
|
+
assert_equal str, str.match(CssParser::RE_STRING).to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
test_string = "p { background: red url(\"url\\.'p'ng\"); }"
|
19
|
+
assert_equal "\"url\\.'p'ng\"", test_string.match(CssParser::RE_STRING).to_s
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_unicode
|
24
|
+
['back\67round', 'r\000065 ed', '\00006C'].each do |str|
|
25
|
+
assert_match(Regexp.new(CssParser::RE_UNICODE), str)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_colour
|
30
|
+
['color: #fff', 'color:#f0a09c;', 'color: #04A', 'color: #04a9CE',
|
31
|
+
'color: rgb(100, -10%, 300);', 'color: rgb(10,10,10)', 'color:rgb(12.7253%, -12%,0)',
|
32
|
+
'color: black', 'color:Red;', 'color: AqUa;', 'color: blue ', 'color: transparent'
|
33
|
+
].each do |colour|
|
34
|
+
assert_match(CssParser::RE_COLOUR, colour)
|
35
|
+
end
|
36
|
+
|
37
|
+
['color: #fa', 'color:#f009c;', 'color: #04G', 'color: #04a9Cq',
|
38
|
+
'color: rgb 100, -10%, 300;', 'color: rgb 10,10,10', 'color:rgb(12px, -12%,0)',
|
39
|
+
'color:fuscia;', 'color: thick'
|
40
|
+
].each do |colour|
|
41
|
+
assert_no_match(CssParser::RE_COLOUR, colour)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_uris
|
46
|
+
crazy_uri = 'http://www.example.com:80/~/redb%20all.png?test=test&test;test+test#test!'
|
47
|
+
|
48
|
+
assert_equal "url('#{crazy_uri}')",
|
49
|
+
"li { list-style: url('#{crazy_uri}') disc }".match(CssParser::RE_URI).to_s
|
50
|
+
|
51
|
+
assert_equal "url(#{crazy_uri})",
|
52
|
+
"li { list-style: url(#{crazy_uri}) disc }".match(CssParser::RE_URI).to_s
|
53
|
+
|
54
|
+
assert_equal "url(\"#{crazy_uri}\")",
|
55
|
+
"li { list-style: url(\"#{crazy_uri}\") disc }".match(CssParser::RE_URI).to_s
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
protected
|
60
|
+
def load_test_file(filename)
|
61
|
+
fh = File.new("fixtures/#{filename}", 'r')
|
62
|
+
test_file = fh.read
|
63
|
+
fh.close
|
64
|
+
|
65
|
+
return test_file
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__), '../'))
|
2
|
+
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__), '../lib/'))
|
3
|
+
require 'rubygems'
|
4
|
+
require 'test/unit'
|
5
|
+
require 'css_parser'
|
6
|
+
require 'net/http'
|
7
|
+
require 'open-uri'
|
8
|
+
require 'WEBrick'
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class MergingTests < Test::Unit::TestCase
|
4
|
+
include CssParser
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@cp = CssParser::Parser.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_simple_merge
|
11
|
+
rs1 = RuleSet.new(nil, 'color: black;')
|
12
|
+
rs2 = RuleSet.new(nil, 'margin: 0px;')
|
13
|
+
merged = CssParser.merge(rs1, rs2)
|
14
|
+
assert_equal '0px;', merged['margin']
|
15
|
+
assert_equal 'black;', merged['color']
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_merging_array
|
19
|
+
rs1 = RuleSet.new(nil, 'color: black;')
|
20
|
+
rs2 = RuleSet.new(nil, 'margin: 0px;')
|
21
|
+
merged = CssParser.merge([rs1, rs2])
|
22
|
+
assert_equal '0px;', merged['margin']
|
23
|
+
assert_equal 'black;', merged['color']
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def test_merging_multiple
|
28
|
+
rs1 = RuleSet.new(nil, 'color: black;')
|
29
|
+
rs2 = RuleSet.new(nil, 'margin: 0px;')
|
30
|
+
rs3 = RuleSet.new(nil, 'margin: 5px;')
|
31
|
+
merged = CssParser.merge(rs1, rs2, rs3)
|
32
|
+
assert_equal '5px;', merged['margin']
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_multiple_selectors_should_have_zero_specificity
|
36
|
+
rs1 = RuleSet.new('p, a[rel="external"]', 'color: black;')
|
37
|
+
rs2 = RuleSet.new('a', 'color: blue;')
|
38
|
+
merged = CssParser.merge(rs1, rs2)
|
39
|
+
assert_equal 'blue;', merged['color']
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_setting_specificity
|
43
|
+
rs1 = RuleSet.new(nil, 'color: red;', 20)
|
44
|
+
rs2 = RuleSet.new(nil, 'color: blue;', 10)
|
45
|
+
merged = CssParser.merge(rs1, rs2)
|
46
|
+
assert_equal 'red;', merged['color']
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_properties_should_be_case_insensitive
|
50
|
+
rs1 = RuleSet.new(nil, ' CoLor : red ;', 20)
|
51
|
+
rs2 = RuleSet.new(nil, 'color: blue;', 10)
|
52
|
+
merged = CssParser.merge(rs1, rs2)
|
53
|
+
assert_equal 'red;', merged['color']
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_merging_backgrounds
|
57
|
+
rs1 = RuleSet.new(nil, 'background-color: black;')
|
58
|
+
rs2 = RuleSet.new(nil, 'background-image: none;')
|
59
|
+
merged = CssParser.merge(rs1, rs2)
|
60
|
+
assert_equal 'black none;', merged['background']
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_merging_dimensions
|
64
|
+
rs1 = RuleSet.new(nil, 'margin: 3em;')
|
65
|
+
rs2 = RuleSet.new(nil, 'margin-left: 1em;')
|
66
|
+
merged = CssParser.merge(rs1, rs2)
|
67
|
+
assert_equal '3em 3em 3em 1em;', merged['margin']
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_merging_fonts
|
71
|
+
rs1 = RuleSet.new(nil, 'font: 11px Arial;')
|
72
|
+
rs2 = RuleSet.new(nil, 'font-weight: bold;')
|
73
|
+
merged = CssParser.merge(rs1, rs2)
|
74
|
+
assert_equal 'bold 11px Arial;', merged['font']
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_raising_error_on_bad_type
|
78
|
+
assert_raise ArgumentError do
|
79
|
+
CssParser.merge([1,2,3])
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_returning_early_with_only_one_params
|
84
|
+
rs = RuleSet.new(nil, 'font-weight: bold;')
|
85
|
+
merged = CssParser.merge(rs)
|
86
|
+
assert_equal rs.object_id, merged.object_id
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
# Test cases for parsing CSS blocks
|
4
|
+
class RuleSetTests < Test::Unit::TestCase
|
5
|
+
include CssParser
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@cp = Parser.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_setting_property_values
|
12
|
+
rs = RuleSet.new(nil, nil)
|
13
|
+
|
14
|
+
rs['background-color'] = 'red'
|
15
|
+
assert_equal('red;', rs['background-color'])
|
16
|
+
|
17
|
+
rs['background-color'] = 'blue !important;'
|
18
|
+
assert_equal('blue !important;', rs['background-color'])
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_getting_property_values
|
22
|
+
rs = RuleSet.new('#content p, a', 'color: #fff;')
|
23
|
+
assert_equal('#fff;', rs['color'])
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_getting_property_value_ignoring_case
|
27
|
+
rs = RuleSet.new('#content p, a', 'color: #fff;')
|
28
|
+
assert_equal('#fff;', rs[' ColoR '])
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_each_selector
|
32
|
+
expected = [
|
33
|
+
{:selector => "#content p", :declarations => "color: #fff;", :specificity => 101},
|
34
|
+
{:selector => "a", :declarations => "color: #fff;", :specificity => 1}
|
35
|
+
]
|
36
|
+
|
37
|
+
actual = []
|
38
|
+
rs = RuleSet.new('#content p, a', 'color: #fff;')
|
39
|
+
rs.each_selector do |sel, decs, spec|
|
40
|
+
actual << {:selector => sel, :declarations => decs, :specificity => spec}
|
41
|
+
end
|
42
|
+
|
43
|
+
assert_equal(expected, actual)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_each_declaration
|
47
|
+
expected = [
|
48
|
+
{:property => 'margin', :value => '1px -0.25em', :is_important => false},
|
49
|
+
{:property => 'background', :value => 'white none no-repeat', :is_important => true},
|
50
|
+
{:property => 'color', :value => '#fff', :is_important => false}
|
51
|
+
]
|
52
|
+
|
53
|
+
actual = []
|
54
|
+
rs = RuleSet.new(nil, 'color: #fff; Background: white none no-repeat !important; margin: 1px -0.25em;')
|
55
|
+
rs.each_declaration do |prop, val, imp|
|
56
|
+
actual << {:property => prop, :value => val, :is_important => imp}
|
57
|
+
end
|
58
|
+
|
59
|
+
assert_equal(expected, actual)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_declarations_to_s
|
63
|
+
declarations = 'color: #fff; font-weight: bold;'
|
64
|
+
rs = RuleSet.new('#content p, a', declarations)
|
65
|
+
assert_equal(declarations.split(' ').sort, rs.declarations_to_s.split(' ').sort)
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_overriding_specificity
|
69
|
+
rs = RuleSet.new('#content p, a', 'color: white', 1000)
|
70
|
+
rs.each_selector do |sel, decs, spec|
|
71
|
+
assert_equal 1000, spec
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
# Test cases for reading and generating CSS shorthand properties
|
4
|
+
class RuleSetCreatingShorthandTests < Test::Unit::TestCase
|
5
|
+
include CssParser
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@cp = CssParser::Parser.new
|
9
|
+
end
|
10
|
+
|
11
|
+
# ==== Dimensions shorthand
|
12
|
+
def test_combining_dimensions_into_shorthand
|
13
|
+
properties = {'margin-right' => 'auto', 'margin-bottom' => '0px', 'margin-left' => 'auto', 'margin-top' => '0px',
|
14
|
+
'padding-right' => '1.25em', 'padding-bottom' => '11%', 'padding-left' => '3pc', 'padding-top' => '11.25ex'}
|
15
|
+
|
16
|
+
combined = create_shorthand(properties)
|
17
|
+
|
18
|
+
assert_equal('0px auto;', combined['margin'])
|
19
|
+
assert_equal('11.25ex 1.25em 11% 3pc;', combined['padding'])
|
20
|
+
|
21
|
+
# after creating shorthand, all long-hand properties should be deleted
|
22
|
+
assert_properties_are_deleted(combined, properties)
|
23
|
+
|
24
|
+
# should not combine if any properties are missing
|
25
|
+
properties.delete('margin-right')
|
26
|
+
properties.delete('padding-right')
|
27
|
+
|
28
|
+
combined = create_shorthand(properties)
|
29
|
+
|
30
|
+
assert_equal '', combined['margin']
|
31
|
+
assert_equal '', combined['padding']
|
32
|
+
end
|
33
|
+
|
34
|
+
# ==== Font shorthand
|
35
|
+
def test_combining_font_into_shorthand
|
36
|
+
# should combine if all font properties are present
|
37
|
+
properties = {"font-weight" => "300", "font-size" => "12pt",
|
38
|
+
"font-family" => "sans-serif", "line-height" => "18px",
|
39
|
+
"font-style" => "oblique", "font-variant" => "small-caps"}
|
40
|
+
|
41
|
+
combined = create_shorthand(properties)
|
42
|
+
assert_equal('oblique small-caps 300 12pt/18px sans-serif;', combined['font'])
|
43
|
+
|
44
|
+
# after creating shorthand, all long-hand properties should be deleted
|
45
|
+
assert_properties_are_deleted(combined, properties)
|
46
|
+
|
47
|
+
# should not combine if any properties are missing
|
48
|
+
properties.delete('font-weight')
|
49
|
+
combined = create_shorthand(properties)
|
50
|
+
assert_equal '', combined['font']
|
51
|
+
end
|
52
|
+
|
53
|
+
# ==== Background shorthand
|
54
|
+
def test_combining_background_into_shorthand
|
55
|
+
properties = {'background-image' => 'url(\'chess.png\')', 'background-color' => 'gray',
|
56
|
+
'background-position' => 'center -10.2%', 'background-attachment' => 'fixed',
|
57
|
+
'background-repeat' => 'no-repeat'}
|
58
|
+
|
59
|
+
combined = create_shorthand(properties)
|
60
|
+
|
61
|
+
assert_equal('gray url(\'chess.png\') no-repeat center -10.2% fixed;', combined['background'])
|
62
|
+
|
63
|
+
# after creating shorthand, all long-hand properties should be deleted
|
64
|
+
assert_properties_are_deleted(combined, properties)
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_property_values_in_url
|
68
|
+
rs = RuleSet.new('#header', "background:url(http://example.com/1528/www/top-logo.jpg) no-repeat top right; padding: 79px 0 10px 0; text-align:left;")
|
69
|
+
rs.expand_shorthand!
|
70
|
+
assert_equal('top right;', rs['background-position'])
|
71
|
+
rs.create_shorthand!
|
72
|
+
assert_equal('url(http://example.com/1528/www/top-logo.jpg) no-repeat top right;', rs['background'])
|
73
|
+
end
|
74
|
+
|
75
|
+
protected
|
76
|
+
def assert_properties_are_deleted(ruleset, properties)
|
77
|
+
properties.each do |property, value|
|
78
|
+
assert_equal '', ruleset[property]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def create_shorthand(properties)
|
83
|
+
ruleset = RuleSet.new(nil, nil)
|
84
|
+
properties.each do |property, value|
|
85
|
+
ruleset[property] = value
|
86
|
+
end
|
87
|
+
ruleset.create_shorthand!
|
88
|
+
ruleset
|
89
|
+
end
|
90
|
+
end
|