marcosinger-css_parser 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/css_parser.rb +162 -0
- data/lib/css_parser/parser.rb +454 -0
- data/lib/css_parser/regexps.rb +75 -0
- data/lib/css_parser/rule_set.rb +451 -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 +72 -0
- data/test/test_css_parser_loading.rb +139 -0
- data/test/test_css_parser_media_types.rb +106 -0
- data/test/test_css_parser_misc.rb +164 -0
- data/test/test_css_parser_regexps.rb +69 -0
- data/test/test_helper.rb +6 -0
- data/test/test_merging.rb +103 -0
- data/test/test_rule_set.rb +90 -0
- data/test/test_rule_set_creating_shorthand.rb +119 -0
- data/test/test_rule_set_expanding_shorthand.rb +198 -0
- metadata +101 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
# coding: iso-8859-1
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/test_helper')
|
3
|
+
|
4
|
+
# Test cases for CSS regular expressions
|
5
|
+
#
|
6
|
+
# see http://www.w3.org/TR/CSS21/syndata.html and
|
7
|
+
# http://www.w3.org/TR/CSS21/grammar.html
|
8
|
+
class CssParserRegexpTests < Test::Unit::TestCase
|
9
|
+
def test_strings
|
10
|
+
# complete matches
|
11
|
+
['"abcd"', '" A sd s�drcv \'dsf\' asd rfg asd"', '"A\ d??ef 123!"',
|
12
|
+
"\"this is\\\n a test\"", '"back\67round"', '"r\000065 ed"',
|
13
|
+
"'abcd'", "' A sd sedrcv \"dsf\" asd rf�&23$%#%$g asd'", "'A\\\n def 123!'",
|
14
|
+
"'this is\\\n a test'", "'back\\67round'", "'r\\000065 ed'"
|
15
|
+
].each do |str|
|
16
|
+
assert_equal str, str.match(CssParser::RE_STRING).to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
test_string = "p { background: red url(\"url\\.'p'ng\"); }"
|
20
|
+
assert_equal "\"url\\.'p'ng\"", test_string.match(CssParser::RE_STRING).to_s
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_unicode
|
25
|
+
['back\67round', 'r\000065 ed', '\00006C'].each do |str|
|
26
|
+
assert_match(Regexp.new(CssParser::RE_UNICODE), str)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_colour
|
31
|
+
['color: #fff', 'color:#f0a09c;', 'color: #04A', 'color: #04a9CE',
|
32
|
+
'color: rgb(100, -10%, 300);', 'color: rgb(10,10,10)', 'color:rgb(12.7253%, -12%,0)',
|
33
|
+
'color: black', 'color:Red;', 'color: AqUa;', 'color: blue ', 'color: transparent'
|
34
|
+
].each do |colour|
|
35
|
+
assert_match(CssParser::RE_COLOUR, colour)
|
36
|
+
end
|
37
|
+
|
38
|
+
['color: #fa', 'color:#f009c;', 'color: #04G', 'color: #04a9Cq',
|
39
|
+
'color: rgb 100, -10%, 300;', 'color: rgb 10,10,10', 'color:rgb(12px, -12%,0)',
|
40
|
+
'color:fuscia;', 'color: thick'
|
41
|
+
].each do |colour|
|
42
|
+
assert_no_match(CssParser::RE_COLOUR, colour)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_uris
|
47
|
+
crazy_uri = 'http://www.example.com:80/~/redb%20all.png?test=test&test;test+test#test!'
|
48
|
+
|
49
|
+
assert_equal "url('#{crazy_uri}')",
|
50
|
+
"li { list-style: url('#{crazy_uri}') disc }".match(CssParser::RE_URI).to_s
|
51
|
+
|
52
|
+
assert_equal "url(#{crazy_uri})",
|
53
|
+
"li { list-style: url(#{crazy_uri}) disc }".match(CssParser::RE_URI).to_s
|
54
|
+
|
55
|
+
assert_equal "url(\"#{crazy_uri}\")",
|
56
|
+
"li { list-style: url(\"#{crazy_uri}\") disc }".match(CssParser::RE_URI).to_s
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
protected
|
61
|
+
def load_test_file(filename)
|
62
|
+
fh = File.new("fixtures/#{filename}", 'r')
|
63
|
+
test_file = fh.read
|
64
|
+
fh.close
|
65
|
+
|
66
|
+
return test_file
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
require File.expand_path(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
|
+
|
89
|
+
def test_merging_important
|
90
|
+
rs1 = RuleSet.new(nil, 'color: black !important;')
|
91
|
+
rs2 = RuleSet.new(nil, 'color: red;')
|
92
|
+
merged = CssParser.merge(rs1, rs2)
|
93
|
+
assert_equal 'black !important;', merged['color']
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_merging_shorthand_important
|
97
|
+
rs1 = RuleSet.new(nil, 'background: black none !important;')
|
98
|
+
rs2 = RuleSet.new(nil, 'background-color: red;')
|
99
|
+
merged = CssParser.merge(rs1, rs2)
|
100
|
+
assert_equal 'black !important;', merged['background-color']
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/test_helper')
|
2
|
+
require "set"
|
3
|
+
|
4
|
+
# Test cases for parsing CSS blocks
|
5
|
+
class RuleSetTests < Test::Unit::TestCase
|
6
|
+
include CssParser
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@cp = Parser.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_setting_property_values
|
13
|
+
rs = RuleSet.new(nil, nil)
|
14
|
+
|
15
|
+
rs['background-color'] = 'red'
|
16
|
+
assert_equal('red;', rs['background-color'])
|
17
|
+
|
18
|
+
rs['background-color'] = 'blue !important;'
|
19
|
+
assert_equal('blue !important;', rs['background-color'])
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_getting_property_values
|
23
|
+
rs = RuleSet.new('#content p, a', 'color: #fff;')
|
24
|
+
assert_equal('#fff;', rs['color'])
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_getting_property_value_ignoring_case
|
28
|
+
rs = RuleSet.new('#content p, a', 'color: #fff;')
|
29
|
+
assert_equal('#fff;', rs[' ColoR '])
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_each_selector
|
33
|
+
expected = [
|
34
|
+
{:selector => "#content p", :declarations => "color: #fff;", :specificity => 101},
|
35
|
+
{:selector => "a", :declarations => "color: #fff;", :specificity => 1}
|
36
|
+
]
|
37
|
+
|
38
|
+
actual = []
|
39
|
+
rs = RuleSet.new('#content p, a', 'color: #fff;')
|
40
|
+
rs.each_selector do |sel, decs, spec|
|
41
|
+
actual << {:selector => sel, :declarations => decs, :specificity => spec}
|
42
|
+
end
|
43
|
+
|
44
|
+
assert_equal(expected, actual)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_each_declaration
|
48
|
+
expected = Set.new([
|
49
|
+
{:property => 'margin', :value => '1px -0.25em', :is_important => false},
|
50
|
+
{:property => 'background', :value => 'white none no-repeat', :is_important => true},
|
51
|
+
{:property => 'color', :value => '#fff', :is_important => false}
|
52
|
+
])
|
53
|
+
|
54
|
+
actual = Set.new
|
55
|
+
rs = RuleSet.new(nil, 'color: #fff; Background: white none no-repeat !important; margin: 1px -0.25em;')
|
56
|
+
rs.each_declaration do |prop, val, imp|
|
57
|
+
actual << {:property => prop, :value => val, :is_important => imp}
|
58
|
+
end
|
59
|
+
|
60
|
+
assert_equal(expected, actual)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_each_declaration_respects_order
|
64
|
+
css_fragment = "margin: 0; padding: 20px; margin-bottom: 28px;"
|
65
|
+
rs = RuleSet.new(nil, css_fragment)
|
66
|
+
expected = %w(margin padding margin-bottom)
|
67
|
+
actual = []
|
68
|
+
rs.each_declaration { |prop, val, imp| actual << prop }
|
69
|
+
assert_equal(expected, actual)
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_declarations_to_s
|
73
|
+
declarations = 'color: #fff; font-weight: bold;'
|
74
|
+
rs = RuleSet.new('#content p, a', declarations)
|
75
|
+
assert_equal(declarations.split(' ').sort, rs.declarations_to_s.split(' ').sort)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_important_declarations_to_s
|
79
|
+
declarations = 'color: #fff; font-weight: bold !important;'
|
80
|
+
rs = RuleSet.new('#content p, a', declarations)
|
81
|
+
assert_equal(declarations.split(' ').sort, rs.declarations_to_s.split(' ').sort)
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_overriding_specificity
|
85
|
+
rs = RuleSet.new('#content p, a', 'color: white', 1000)
|
86
|
+
rs.each_selector do |sel, decs, spec|
|
87
|
+
assert_equal 1000, spec
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require File.expand_path(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
|
+
# ==== Border shorthand
|
12
|
+
def test_combining_borders_into_shorthand
|
13
|
+
properties = {'border-top-width' => 'auto', 'border-right-width' => 'thin', 'border-bottom-width' => 'auto', 'border-left-width' => '0px'}
|
14
|
+
|
15
|
+
combined = create_shorthand(properties)
|
16
|
+
|
17
|
+
assert_equal('auto thin auto 0px;', combined['border-width'])
|
18
|
+
|
19
|
+
# after creating shorthand, all long-hand properties should be deleted
|
20
|
+
assert_properties_are_deleted(combined, properties)
|
21
|
+
|
22
|
+
# should not combine if any properties are missing
|
23
|
+
properties.delete('border-top-width')
|
24
|
+
|
25
|
+
combined = create_shorthand(properties)
|
26
|
+
|
27
|
+
assert_equal '', combined['border-width']
|
28
|
+
|
29
|
+
properties = {'border-width' => '22%', 'border-color' => 'black'}
|
30
|
+
combined = create_shorthand(properties)
|
31
|
+
|
32
|
+
assert_equal '22% black;', combined['border']
|
33
|
+
assert_equal '', combined['border-width']
|
34
|
+
|
35
|
+
properties = {'border-top-style' => 'none', 'border-right-style' => 'none', 'border-bottom-style' => 'none', 'border-left-style' => 'none'}
|
36
|
+
combined = create_shorthand(properties)
|
37
|
+
assert_equal 'none;', combined['border']
|
38
|
+
end
|
39
|
+
|
40
|
+
# ==== Dimensions shorthand
|
41
|
+
def test_combining_dimensions_into_shorthand
|
42
|
+
properties = {'margin-right' => 'auto', 'margin-bottom' => '0px', 'margin-left' => 'auto', 'margin-top' => '0px',
|
43
|
+
'padding-right' => '1.25em', 'padding-bottom' => '11%', 'padding-left' => '3pc', 'padding-top' => '11.25ex'}
|
44
|
+
|
45
|
+
combined = create_shorthand(properties)
|
46
|
+
|
47
|
+
assert_equal('0px auto;', combined['margin'])
|
48
|
+
assert_equal('11.25ex 1.25em 11% 3pc;', combined['padding'])
|
49
|
+
|
50
|
+
# after creating shorthand, all long-hand properties should be deleted
|
51
|
+
assert_properties_are_deleted(combined, properties)
|
52
|
+
|
53
|
+
# should not combine if any properties are missing
|
54
|
+
properties.delete('margin-right')
|
55
|
+
properties.delete('padding-right')
|
56
|
+
|
57
|
+
combined = create_shorthand(properties)
|
58
|
+
|
59
|
+
assert_equal '', combined['margin']
|
60
|
+
assert_equal '', combined['padding']
|
61
|
+
end
|
62
|
+
|
63
|
+
# ==== Font shorthand
|
64
|
+
def test_combining_font_into_shorthand
|
65
|
+
# should combine if all font properties are present
|
66
|
+
properties = {"font-weight" => "300", "font-size" => "12pt",
|
67
|
+
"font-family" => "sans-serif", "line-height" => "18px",
|
68
|
+
"font-style" => "oblique", "font-variant" => "small-caps"}
|
69
|
+
|
70
|
+
combined = create_shorthand(properties)
|
71
|
+
assert_equal('oblique small-caps 300 12pt/18px sans-serif;', combined['font'])
|
72
|
+
|
73
|
+
# after creating shorthand, all long-hand properties should be deleted
|
74
|
+
assert_properties_are_deleted(combined, properties)
|
75
|
+
|
76
|
+
# should not combine if any properties are missing
|
77
|
+
properties.delete('font-weight')
|
78
|
+
combined = create_shorthand(properties)
|
79
|
+
assert_equal '', combined['font']
|
80
|
+
end
|
81
|
+
|
82
|
+
# ==== Background shorthand
|
83
|
+
def test_combining_background_into_shorthand
|
84
|
+
properties = {'background-image' => 'url(\'chess.png\')', 'background-color' => 'gray',
|
85
|
+
'background-position' => 'center -10.2%', 'background-attachment' => 'fixed',
|
86
|
+
'background-repeat' => 'no-repeat'}
|
87
|
+
|
88
|
+
combined = create_shorthand(properties)
|
89
|
+
|
90
|
+
assert_equal('gray url(\'chess.png\') no-repeat center -10.2% fixed;', combined['background'])
|
91
|
+
|
92
|
+
# after creating shorthand, all long-hand properties should be deleted
|
93
|
+
assert_properties_are_deleted(combined, properties)
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_property_values_in_url
|
97
|
+
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;")
|
98
|
+
rs.expand_shorthand!
|
99
|
+
assert_equal('top right;', rs['background-position'])
|
100
|
+
rs.create_shorthand!
|
101
|
+
assert_equal('url(http://example.com/1528/www/top-logo.jpg) no-repeat top right;', rs['background'])
|
102
|
+
end
|
103
|
+
|
104
|
+
protected
|
105
|
+
def assert_properties_are_deleted(ruleset, properties)
|
106
|
+
properties.each do |property, value|
|
107
|
+
assert_equal '', ruleset[property]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def create_shorthand(properties)
|
112
|
+
ruleset = RuleSet.new(nil, nil)
|
113
|
+
properties.each do |property, value|
|
114
|
+
ruleset[property] = value
|
115
|
+
end
|
116
|
+
ruleset.create_shorthand!
|
117
|
+
ruleset
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/test_helper')
|
2
|
+
|
3
|
+
class RuleSetExpandingShorthandTests < Test::Unit::TestCase
|
4
|
+
include CssParser
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@cp = CssParser::Parser.new
|
8
|
+
end
|
9
|
+
|
10
|
+
# ==== Dimensions shorthand
|
11
|
+
def test_expanding_border_shorthand
|
12
|
+
declarations = expand_declarations('border: none')
|
13
|
+
assert_equal 'none', declarations['border-right-style']
|
14
|
+
|
15
|
+
declarations = expand_declarations('border: 1px solid red')
|
16
|
+
assert_equal '1px', declarations['border-top-width']
|
17
|
+
assert_equal 'solid', declarations['border-bottom-style']
|
18
|
+
|
19
|
+
declarations = expand_declarations('border-color: red hsla(255, 0, 0, 5) rgb(2% ,2%,2%)')
|
20
|
+
assert_equal 'red', declarations['border-top-color']
|
21
|
+
assert_equal 'rgb(2%,2%,2%)', declarations['border-bottom-color']
|
22
|
+
assert_equal 'hsla(255,0,0,5)', declarations['border-left-color']
|
23
|
+
|
24
|
+
declarations = expand_declarations('border: thin dot-dot-dash')
|
25
|
+
assert_equal 'dot-dot-dash', declarations['border-left-style']
|
26
|
+
assert_equal 'thin', declarations['border-left-width']
|
27
|
+
assert_nil declarations['border-left-color']
|
28
|
+
end
|
29
|
+
|
30
|
+
# ==== Dimensions shorthand
|
31
|
+
def test_getting_dimensions_from_shorthand
|
32
|
+
# test various shorthand forms
|
33
|
+
['margin: 0px auto', 'margin: 0px auto 0px', 'margin: 0px auto 0px'].each do |shorthand|
|
34
|
+
declarations = expand_declarations(shorthand)
|
35
|
+
assert_equal({"margin-right" => "auto", "margin-bottom" => "0px", "margin-left" => "auto", "margin-top" => "0px"}, declarations)
|
36
|
+
end
|
37
|
+
|
38
|
+
# test various units
|
39
|
+
['em', 'ex', 'in', 'px', 'pt', 'pc', '%'].each do |unit|
|
40
|
+
shorthand = "margin: 0% -0.123#{unit} 9px -.9pc"
|
41
|
+
declarations = expand_declarations(shorthand)
|
42
|
+
assert_equal({"margin-right" => "-0.123#{unit}", "margin-bottom" => "9px", "margin-left" => "-.9pc", "margin-top" => "0%"}, declarations)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# ==== Font shorthand
|
48
|
+
def test_getting_font_size_from_shorthand
|
49
|
+
['em', 'ex', 'in', 'px', 'pt', 'pc', '%'].each do |unit|
|
50
|
+
shorthand = "font: 300 italic 11.25#{unit}/14px verdana, helvetica, sans-serif;"
|
51
|
+
declarations = expand_declarations(shorthand)
|
52
|
+
assert_equal("11.25#{unit}", declarations['font-size'])
|
53
|
+
end
|
54
|
+
|
55
|
+
['smaller', 'small', 'medium', 'large', 'x-large', 'auto'].each do |unit|
|
56
|
+
shorthand = "font: 300 italic #{unit}/14px verdana, helvetica, sans-serif;"
|
57
|
+
declarations = expand_declarations(shorthand)
|
58
|
+
assert_equal(unit, declarations['font-size'])
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_getting_font_families_from_shorthand
|
63
|
+
shorthand = "font: 300 italic 12px/14px \"Helvetica-Neue-Light 45\", 'verdana', helvetica, sans-serif;"
|
64
|
+
declarations = expand_declarations(shorthand)
|
65
|
+
assert_equal("\"Helvetica-Neue-Light 45\", 'verdana', helvetica, sans-serif", declarations['font-family'])
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_getting_font_weight_from_shorthand
|
69
|
+
['300', 'bold', 'bolder', 'lighter', 'normal'].each do |unit|
|
70
|
+
shorthand = "font: #{unit} italic 12px sans-serif;"
|
71
|
+
declarations = expand_declarations(shorthand)
|
72
|
+
assert_equal(unit, declarations['font-weight'])
|
73
|
+
end
|
74
|
+
|
75
|
+
# ensure normal is the default state
|
76
|
+
['font: normal italic 12px sans-serif;', 'font: italic 12px sans-serif;',
|
77
|
+
'font: small-caps normal 12px sans-serif;', 'font: 12px/16px sans-serif;'].each do |shorthand|
|
78
|
+
declarations = expand_declarations(shorthand)
|
79
|
+
assert_equal('normal', declarations['font-weight'], shorthand)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_getting_font_variant_from_shorthand
|
84
|
+
shorthand = "font: small-caps italic 12px sans-serif;"
|
85
|
+
declarations = expand_declarations(shorthand)
|
86
|
+
assert_equal('small-caps', declarations['font-variant'])
|
87
|
+
|
88
|
+
# ensure normal is the default state
|
89
|
+
['font: normal italic 12px sans-serif;', 'font: italic 12px sans-serif;',
|
90
|
+
'font: normal 12px sans-serif;', 'font: 12px/16px sans-serif;'].each do |shorthand|
|
91
|
+
declarations = expand_declarations(shorthand)
|
92
|
+
assert_equal('normal', declarations['font-variant'], shorthand)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_getting_font_style_from_shorthand
|
97
|
+
['italic', 'oblique'].each do |unit|
|
98
|
+
shorthand = "font: normal #{unit} bold 12px sans-serif;"
|
99
|
+
declarations = expand_declarations(shorthand)
|
100
|
+
assert_equal(unit, declarations['font-style'])
|
101
|
+
end
|
102
|
+
|
103
|
+
# ensure normal is the default state
|
104
|
+
['font: normal bold 12px sans-serif;', 'font: small-caps 12px sans-serif;',
|
105
|
+
'font: normal 12px sans-serif;', 'font: 12px/16px sans-serif;'].each do |shorthand|
|
106
|
+
declarations = expand_declarations(shorthand)
|
107
|
+
assert_equal('normal', declarations['font-style'], shorthand)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_getting_line_height_from_shorthand
|
112
|
+
['em', 'ex', 'in', 'px', 'pt', 'pc', '%'].each do |unit|
|
113
|
+
shorthand = "font: 300 italic 12px/0.25#{unit} verdana, helvetica, sans-serif;"
|
114
|
+
declarations = expand_declarations(shorthand)
|
115
|
+
assert_equal("0.25#{unit}", declarations['line-height'])
|
116
|
+
end
|
117
|
+
|
118
|
+
# ensure normal is the default state
|
119
|
+
['font: normal bold 12px sans-serif;', 'font: small-caps 12px sans-serif;',
|
120
|
+
'font: normal 12px sans-serif;', 'font: 12px sans-serif;'].each do |shorthand|
|
121
|
+
declarations = expand_declarations(shorthand)
|
122
|
+
assert_equal('normal', declarations['line-height'], shorthand)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
# ==== Background shorthand
|
128
|
+
def test_getting_background_properties_from_shorthand
|
129
|
+
expected = {"background-image" => "url('chess.png')", "background-color" => "gray", "background-repeat" => "repeat",
|
130
|
+
"background-attachment" => "fixed", "background-position" => "50%"}
|
131
|
+
|
132
|
+
shorthand = "background: url('chess.png') gray 50% repeat fixed;"
|
133
|
+
declarations = expand_declarations(shorthand)
|
134
|
+
assert_equal expected, declarations
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_getting_background_position_from_shorthand
|
138
|
+
['em', 'ex', 'in', 'px', 'pt', 'pc', '%'].each do |unit|
|
139
|
+
shorthand = "background: url('chess.png') gray 30% -0.15#{unit} repeat fixed;"
|
140
|
+
declarations = expand_declarations(shorthand)
|
141
|
+
assert_equal("30% -0.15#{unit}", declarations['background-position'])
|
142
|
+
end
|
143
|
+
|
144
|
+
['left', 'center', 'right', 'top', 'bottom', 'inherit'].each do |position|
|
145
|
+
shorthand = "background: url('chess.png') #000fff #{position} no-repeat fixed;"
|
146
|
+
declarations = expand_declarations(shorthand)
|
147
|
+
assert_equal(position, declarations['background-position'])
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_getting_background_colour_from_shorthand
|
152
|
+
['blue', 'lime', 'rgb(10,10,10)', 'rgb ( -10%, 99, 300)', '#ffa0a0', '#03c', 'trAnsparEnt', 'inherit'].each do |colour|
|
153
|
+
shorthand = "background:#{colour} url('chess.png') center repeat fixed ;"
|
154
|
+
declarations = expand_declarations(shorthand)
|
155
|
+
assert_equal(colour, declarations['background-color'])
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_getting_background_attachment_from_shorthand
|
160
|
+
['scroll', 'fixed', 'inherit'].each do |attachment|
|
161
|
+
shorthand = "background:#0f0f0f url('chess.png') center repeat #{attachment};"
|
162
|
+
declarations = expand_declarations(shorthand)
|
163
|
+
assert_equal(attachment, declarations['background-attachment'])
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_getting_background_repeat_from_shorthand
|
168
|
+
['repeat-x', 'repeat-y', 'no-repeat', 'inherit'].each do |repeat|
|
169
|
+
shorthand = "background:#0f0f0f none #{repeat};"
|
170
|
+
declarations = expand_declarations(shorthand)
|
171
|
+
assert_equal(repeat, declarations['background-repeat'])
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_getting_background_image_from_shorthand
|
176
|
+
['url("chess.png")', 'url("https://example.org:80/~files/chess.png?123=abc&test#5")',
|
177
|
+
'url(https://example.org:80/~files/chess.png?123=abc&test#5)',
|
178
|
+
"url('https://example.org:80/~files/chess.png?123=abc&test#5')", 'none', 'inherit'].each do |image|
|
179
|
+
|
180
|
+
shorthand = "background: #0f0f0f #{image} ;"
|
181
|
+
declarations = expand_declarations(shorthand)
|
182
|
+
assert_equal(image, declarations['background-image'])
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
protected
|
188
|
+
def expand_declarations(declarations)
|
189
|
+
ruleset = RuleSet.new(nil, declarations)
|
190
|
+
ruleset.expand_shorthand!
|
191
|
+
|
192
|
+
collected = {}
|
193
|
+
ruleset.each_declaration do |prop, val, imp|
|
194
|
+
collected[prop.to_s] = val.to_s
|
195
|
+
end
|
196
|
+
collected
|
197
|
+
end
|
198
|
+
end
|