kajabi-css_parser 1.2.7

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.
@@ -0,0 +1,4 @@
1
+ @import "import-circular-reference.css";
2
+
3
+ body { color: black; background: white; }
4
+ p { margin: 0px; }
@@ -0,0 +1,3 @@
1
+ @import "simple.css" print, tv, screen;
2
+
3
+ div { color: lime; }
@@ -0,0 +1,3 @@
1
+ @import 'subdir/import2.css';
2
+
3
+ div { color: lime; }
@@ -0,0 +1,6 @@
1
+ body {
2
+ color: black;
3
+ background: white;
4
+ }
5
+
6
+ p { margin: 0px; }
@@ -0,0 +1,3 @@
1
+ @import "../simple.css";
2
+
3
+ a { text-decoration: none; }
@@ -0,0 +1,64 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
+
3
+ # Test cases for reading and generating CSS shorthand properties
4
+ class CssParserBasicTests < Test::Unit::TestCase
5
+ include CssParser
6
+
7
+ def setup
8
+ @cp = CssParser::Parser.new
9
+ @css = <<-EOT
10
+ html, body, p { margin: 0px; }
11
+ p { padding: 0px; }
12
+ #content { font: 12px/normal sans-serif; }
13
+ .content { color: red; }
14
+ EOT
15
+ end
16
+
17
+ def test_finding_by_selector
18
+ @cp.add_block!(@css)
19
+ assert_equal 'margin: 0px;', @cp.find_by_selector('body').join(' ')
20
+ assert_equal 'margin: 0px; padding: 0px;', @cp.find_by_selector('p').join(' ')
21
+ assert_equal 'font: 12px/normal sans-serif;', @cp.find_by_selector('#content').join(' ')
22
+ assert_equal 'color: red;', @cp.find_by_selector('.content').join(' ')
23
+ end
24
+
25
+ def test_adding_block
26
+ @cp.add_block!(@css)
27
+ assert_equal 'margin: 0px;', @cp.find_by_selector('body').join
28
+ end
29
+
30
+ def test_adding_block_without_closing_brace
31
+ @cp.add_block!('p { color: red;')
32
+ assert_equal 'color: red;', @cp.find_by_selector('p').join
33
+ end
34
+
35
+ def test_adding_a_rule
36
+ @cp.add_rule!('div', 'color: blue;')
37
+ assert_equal 'color: blue;', @cp.find_by_selector('div').join(' ')
38
+ end
39
+
40
+ def test_adding_a_rule_set
41
+ rs = CssParser::RuleSet.new('div', 'color: blue;')
42
+ @cp.add_rule_set!(rs)
43
+ assert_equal 'color: blue;', @cp.find_by_selector('div').join(' ')
44
+ end
45
+
46
+ def test_toggling_uri_conversion
47
+ # with conversion
48
+ cp_with_conversion = Parser.new(:absolute_paths => true)
49
+ cp_with_conversion.add_block!("body { background: url('../style/yellow.png?abc=123') };",
50
+ :base_uri => 'http://example.org/style/basic.css')
51
+
52
+ assert_equal "background: url('http://example.org/style/yellow.png?abc=123');",
53
+ cp_with_conversion['body'].join(' ')
54
+
55
+ # without conversion
56
+ cp_without_conversion = Parser.new(:absolute_paths => false)
57
+ cp_without_conversion.add_block!("body { background: url('../style/yellow.png?abc=123') };",
58
+ :base_uri => 'http://example.org/style/basic.css')
59
+
60
+ assert_equal "background: url('../style/yellow.png?abc=123');",
61
+ cp_without_conversion['body'].join(' ')
62
+ end
63
+
64
+ end
@@ -0,0 +1,146 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
+
3
+ # Test cases for the CssParser's loading functions.
4
+ class CssParserLoadingTests < Test::Unit::TestCase
5
+ include CssParser
6
+ include WEBrick
7
+
8
+ def setup
9
+ # from http://nullref.se/blog/2006/5/17/testing-with-webrick
10
+ @cp = Parser.new
11
+
12
+ @uri_base = 'http://localhost:12000'
13
+
14
+ @www_root = File.dirname(__FILE__) + '/fixtures/'
15
+
16
+ @server_thread = Thread.new do
17
+ s = WEBrick::HTTPServer.new(:Port => 12000, :DocumentRoot => @www_root, :Logger => Log.new(nil, BasicLog::FATAL), :AccessLog => [])
18
+ @port = s.config[:Port]
19
+ begin
20
+ s.start
21
+ ensure
22
+ s.shutdown
23
+ end
24
+ end
25
+
26
+ sleep 1 # ensure the server has time to load
27
+ end
28
+
29
+ def teardown
30
+ @server_thread.kill
31
+ @server_thread.join(5)
32
+ @server_thread = nil
33
+ end
34
+
35
+ def test_loading_a_local_file
36
+ file_name = File.dirname(__FILE__) + '/fixtures/simple.css'
37
+ @cp.load_file!(file_name)
38
+ assert_equal 'margin: 0px;', @cp.find_by_selector('p').join(' ')
39
+ end
40
+
41
+ def test_loading_a_local_file_with_scheme
42
+ file_name = 'file://' + File.expand_path(File.dirname(__FILE__)) + '/fixtures/simple.css'
43
+ @cp.load_uri!(file_name)
44
+ assert_equal 'margin: 0px;', @cp.find_by_selector('p').join(' ')
45
+ end
46
+
47
+ def test_loading_a_remote_file
48
+ @cp.load_uri!("#{@uri_base}/simple.css")
49
+ assert_equal 'margin: 0px;', @cp.find_by_selector('p').join(' ')
50
+ end
51
+
52
+ # http://github.com/alexdunae/css_parser/issues#issue/4
53
+ def test_loading_a_remote_file_over_ssl
54
+ # TODO: test SSL locally
55
+ @cp.load_uri!("https://dialect.ca/inc/screen.css")
56
+ assert_match /margin\: 0\;/, @cp.find_by_selector('body').join(' ')
57
+ end
58
+
59
+
60
+ def test_following_at_import_rules_local
61
+ base_dir = File.dirname(__FILE__) + '/fixtures'
62
+ @cp.load_file!('import1.css', base_dir)
63
+
64
+ # from '/import1.css'
65
+ assert_equal 'color: lime;', @cp.find_by_selector('div').join(' ')
66
+
67
+ # from '/subdir/import2.css'
68
+ assert_equal 'text-decoration: none;', @cp.find_by_selector('a').join(' ')
69
+
70
+ # from '/subdir/../simple.css'
71
+ assert_equal 'margin: 0px;', @cp.find_by_selector('p').join(' ')
72
+ end
73
+
74
+ def test_following_at_import_rules_remote
75
+ @cp.load_uri!("#{@uri_base}/import1.css")
76
+
77
+ # from '/import1.css'
78
+ assert_equal 'color: lime;', @cp.find_by_selector('div').join(' ')
79
+
80
+ # from '/subdir/import2.css'
81
+ assert_equal 'text-decoration: none;', @cp.find_by_selector('a').join(' ')
82
+
83
+ # from '/subdir/../simple.css'
84
+ assert_equal 'margin: 0px;', @cp.find_by_selector('p').join(' ')
85
+ end
86
+
87
+ def test_following_badly_escaped_import_rules
88
+ css_block = '@import "http://example.com/css?family=Droid+Sans:regular,bold|Droid+Serif:regular,italic,bold,bolditalic&subset=latin";'
89
+
90
+ assert_nothing_raised do
91
+ @cp.add_block!(css_block, :base_uri => "#{@uri_base}/subdir/")
92
+ end
93
+ end
94
+
95
+ def test_following_at_import_rules_from_add_block
96
+ css_block = '@import "../simple.css";'
97
+
98
+ @cp.add_block!(css_block, :base_uri => "#{@uri_base}/subdir/")
99
+
100
+ # from 'simple.css'
101
+ assert_equal 'margin: 0px;', @cp.find_by_selector('p').join(' ')
102
+ end
103
+
104
+ def test_importing_with_media_types
105
+ @cp.load_uri!("#{@uri_base}/import-with-media-types.css")
106
+
107
+ # from simple.css with :screen media type
108
+ assert_equal 'margin: 0px;', @cp.find_by_selector('p', :screen).join(' ')
109
+ assert_equal '', @cp.find_by_selector('p', :tty).join(' ')
110
+ end
111
+
112
+ def test_local_circular_reference_exception
113
+ assert_raise CircularReferenceError do
114
+ @cp.load_file!(File.dirname(__FILE__) + '/fixtures/import-circular-reference.css')
115
+ end
116
+ end
117
+
118
+ def test_remote_circular_reference_exception
119
+ assert_raise CircularReferenceError do
120
+ @cp.load_uri!("#{@uri_base}/import-circular-reference.css")
121
+ end
122
+ end
123
+
124
+ def test_suppressing_circular_reference_exceptions
125
+ cp_without_exceptions = Parser.new(:io_exceptions => false)
126
+
127
+ assert_nothing_raised CircularReferenceError do
128
+ cp_without_exceptions.load_uri!("#{@uri_base}/import-circular-reference.css")
129
+ end
130
+ end
131
+
132
+ def test_toggling_not_found_exceptions
133
+ cp_with_exceptions = Parser.new(:io_exceptions => true)
134
+
135
+ assert_raise RemoteFileError do
136
+ cp_with_exceptions.load_uri!("#{@uri_base}/no-exist.xyz")
137
+ end
138
+
139
+ cp_without_exceptions = Parser.new(:io_exceptions => false)
140
+
141
+ assert_nothing_raised RemoteFileError do
142
+ cp_without_exceptions.load_uri!("#{@uri_base}/no-exist.xyz")
143
+ end
144
+ end
145
+
146
+ end
@@ -0,0 +1,114 @@
1
+ require File.expand_path(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
+ @media screen, 3d-glasses, print and resolution > 90dpi {
24
+ body { color: blue; }
25
+ }
26
+ EOT
27
+
28
+ @cp.add_block!(css)
29
+
30
+ assert_equal 'font-size: 10pt; line-height: 1.2;', @cp.find_by_selector('body', :print).join(' ')
31
+ assert_equal 'font-size: 13px; line-height: 1.2; color: blue;', @cp.find_by_selector('body', :screen).join(' ')
32
+ assert_equal 'color: blue;', @cp.find_by_selector('body', 'print and resolution > 90dpi'.to_sym).join(' ')
33
+ end
34
+
35
+ def test_finding_by_multiple_media_types
36
+ css = <<-EOT
37
+ @media print {
38
+ body { font-size: 10pt }
39
+ }
40
+ @media handheld {
41
+ body { font-size: 13px }
42
+ }
43
+ @media screen, print {
44
+ body { line-height: 1.2 }
45
+ }
46
+ EOT
47
+ @cp.add_block!(css)
48
+
49
+ assert_equal 'font-size: 13px; line-height: 1.2;', @cp.find_by_selector('body', [:screen,:handheld]).join(' ')
50
+ end
51
+
52
+ def test_adding_block_with_media_types
53
+ css = <<-EOT
54
+ body { font-size: 10pt }
55
+ EOT
56
+
57
+ @cp.add_block!(css, :media_types => [:screen])
58
+
59
+ assert_equal 'font-size: 10pt;', @cp.find_by_selector('body', :screen).join(' ')
60
+ assert @cp.find_by_selector('body', :handheld).empty?
61
+ end
62
+
63
+ def test_adding_block_and_limiting_media_types1
64
+ css = <<-EOT
65
+ @import "import1.css", print
66
+ EOT
67
+
68
+ base_dir = File.dirname(__FILE__) + '/fixtures/'
69
+
70
+ @cp.add_block!(css, :only_media_types => :screen, :base_dir => base_dir)
71
+ assert @cp.find_by_selector('div').empty?
72
+
73
+ end
74
+
75
+ def test_adding_block_and_limiting_media_types2
76
+ css = <<-EOT
77
+ @import "import1.css", print and (color)
78
+ EOT
79
+
80
+ base_dir = File.dirname(__FILE__) + '/fixtures/'
81
+
82
+ @cp.add_block!(css, :only_media_types => 'print and (color)', :base_dir => base_dir)
83
+ assert_match 'color: lime', @cp.find_by_selector('div').join(' ')
84
+ end
85
+
86
+ def test_adding_block_and_limiting_media_types
87
+ css = <<-EOT
88
+ @import "import1.css"
89
+ EOT
90
+
91
+ base_dir = File.dirname(__FILE__) + '/fixtures/'
92
+ @cp.add_block!(css, :only_media_types => :print, :base_dir => base_dir)
93
+ assert_match '', @cp.find_by_selector('div').join(' ')
94
+ end
95
+
96
+ def test_adding_rule_set_with_media_type
97
+ @cp.add_rule!('body', 'color: black;', [:handheld,:tty])
98
+ @cp.add_rule!('body', 'color: blue;', :screen)
99
+ assert_equal 'color: black;', @cp.find_by_selector('body', :handheld).join(' ')
100
+ end
101
+
102
+ def test_adding_rule_set_with_media_query
103
+ @cp.add_rule!('body', 'color: black;', 'aural and (device-aspect-ratio: 16/9)')
104
+ assert_equal 'color: black;', @cp.find_by_selector('body', 'aural and (device-aspect-ratio: 16/9)').join(' ')
105
+ assert_equal 'color: black;', @cp.find_by_selector('body', :all).join(' ')
106
+ end
107
+
108
+ def test_selecting_with_all_media_types
109
+ @cp.add_rule!('body', 'color: black;', [:handheld,:tty])
110
+ assert_equal 'color: black;', @cp.find_by_selector('body', :all).join(' ')
111
+ end
112
+
113
+
114
+ end
@@ -0,0 +1,164 @@
1
+ require File.expand_path(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
+ # dervived from http://www.w3.org/TR/CSS21/syndata.html#parsing-errors
87
+ css = <<-EOT
88
+ p { color:green }
89
+ p { color:green; color } /* malformed declaration missing ':', value */
90
+ p { color:red; color; color:green } /* same with expected recovery */
91
+ p { color:green; color: } /* malformed declaration missing value */
92
+ p { color:red; color:; color:green } /* same with expected recovery */
93
+ p { color:green; color{;color:maroon} } /* unexpected tokens { } */
94
+ p { color:red; color{;color:maroon}; color:green } /* same with recovery */
95
+ EOT
96
+
97
+ @cp.add_block!(css)
98
+
99
+ @cp.each_selector do |sel, decs, spec|
100
+ assert_equal 'color: green;', decs
101
+ end
102
+ end
103
+
104
+ def test_calculating_specificity
105
+ # from http://www.w3.org/TR/CSS21/cascade.html#specificity
106
+ assert_equal 0, CssParser.calculate_specificity('*')
107
+ assert_equal 1, CssParser.calculate_specificity('li')
108
+ assert_equal 2, CssParser.calculate_specificity('li:first-line')
109
+ assert_equal 2, CssParser.calculate_specificity('ul li')
110
+ assert_equal 3, CssParser.calculate_specificity('ul ol+li')
111
+ assert_equal 11, CssParser.calculate_specificity('h1 + *[rel=up]')
112
+ assert_equal 13, CssParser.calculate_specificity('ul ol li.red')
113
+ assert_equal 21, CssParser.calculate_specificity('li.red.level')
114
+ assert_equal 100, CssParser.calculate_specificity('#x34y')
115
+
116
+ # from http://www.hixie.ch/tests/adhoc/css/cascade/specificity/003.html
117
+ assert_equal CssParser.calculate_specificity('div *'), CssParser.calculate_specificity('p')
118
+ assert CssParser.calculate_specificity('body div *') > CssParser.calculate_specificity('div *')
119
+
120
+ # other tests
121
+ assert_equal 11, CssParser.calculate_specificity('h1[id|=123]')
122
+ end
123
+
124
+ def test_converting_uris
125
+ base_uri = 'http://www.example.org/style/basic.css'
126
+ ["body { background: url(yellow) };", "body { background: url('yellow') };",
127
+ "body { background: url('/style/yellow') };",
128
+ "body { background: url(\"../style/yellow\") };",
129
+ "body { background: url(\"lib/../../style/yellow\") };"].each do |css|
130
+ converted_css = CssParser.convert_uris(css, base_uri)
131
+ assert_equal "body { background: url('http://www.example.org/style/yellow') };", converted_css
132
+ end
133
+
134
+ converted_css = CssParser.convert_uris("body { background: url(../style/yellow-dot_symbol$.png?abc=123&amp;def=456&ghi=789#1011) };", base_uri)
135
+ assert_equal "body { background: url('http://www.example.org/style/yellow-dot_symbol$.png?abc=123&amp;def=456&ghi=789#1011') };", converted_css
136
+
137
+ # taken from error log: 2007-10-23 04:37:41#2399
138
+ 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')
139
+ 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
140
+ end
141
+
142
+ def test_ruleset_with_braces
143
+ =begin
144
+ parser = Parser.new
145
+ parser.add_block!("div { background-color: black !important; }")
146
+ parser.add_block!("div { background-color: red; }")
147
+
148
+ rulesets = []
149
+
150
+ parser['div'].each do |declaration|
151
+ rulesets << RuleSet.new('div', declaration)
152
+ end
153
+
154
+ merged = CssParser.merge(rulesets)
155
+
156
+ result: # merged.to_s => "{ background-color: black !important; }"
157
+ =end
158
+
159
+ new_rule = RuleSet.new('div', "{ background-color: black !important; }")
160
+
161
+ assert_equal 'div { background-color: black !important; }', new_rule.to_s
162
+ end
163
+
164
+ end