css_parser 1.2.2 → 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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +21 -0
- data/lib/css_parser/parser.rb +532 -185
- data/lib/css_parser/regexps.rb +220 -42
- data/lib/css_parser/rule_set.rb +491 -266
- data/lib/css_parser/version.rb +5 -0
- data/lib/css_parser.rb +56 -60
- metadata +40 -52
- data/test/fixtures/import-circular-reference.css +0 -4
- data/test/fixtures/import-with-media-types.css +0 -3
- data/test/fixtures/import1.css +0 -3
- data/test/fixtures/simple.css +0 -6
- data/test/fixtures/subdir/import2.css +0 -3
- data/test/test_css_parser_basic.rb +0 -64
- data/test/test_css_parser_loading.rb +0 -146
- data/test/test_css_parser_media_types.rb +0 -106
- data/test/test_css_parser_misc.rb +0 -164
- data/test/test_css_parser_regexps.rb +0 -69
- data/test/test_helper.rb +0 -6
- data/test/test_merging.rb +0 -110
- data/test/test_rule_set.rb +0 -90
- data/test/test_rule_set_creating_shorthand.rb +0 -143
- data/test/test_rule_set_expanding_shorthand.rb +0 -223
data/lib/css_parser.rb
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'addressable/uri'
|
|
2
4
|
require 'uri'
|
|
3
5
|
require 'net/https'
|
|
4
|
-
require 'open-uri'
|
|
5
6
|
require 'digest/md5'
|
|
6
|
-
require '
|
|
7
|
-
require 'stringio'
|
|
8
|
-
require 'iconv'
|
|
7
|
+
require 'ssrf_filter'
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
require 'css_parser/version'
|
|
10
|
+
require 'css_parser/rule_set'
|
|
11
|
+
require 'css_parser/regexps'
|
|
12
|
+
require 'css_parser/parser'
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
module CssParser
|
|
15
|
+
# Merge multiple CSS RuleSets by cascading according to the CSS 2.1 cascading rules
|
|
14
16
|
# (http://www.w3.org/TR/REC-CSS2/cascade.html#cascading-order).
|
|
15
17
|
#
|
|
16
18
|
# Takes one or more RuleSet objects.
|
|
@@ -18,14 +20,15 @@ module CssParser
|
|
|
18
20
|
# Returns a RuleSet.
|
|
19
21
|
#
|
|
20
22
|
# ==== Cascading
|
|
21
|
-
# If a RuleSet object has its +specificity+ defined, that specificity is
|
|
22
|
-
# used in the cascade calculations.
|
|
23
|
+
# If a RuleSet object has its +specificity+ defined, that specificity is
|
|
24
|
+
# used in the cascade calculations.
|
|
23
25
|
#
|
|
24
|
-
# If no specificity is explicitly set and the RuleSet has *one* selector,
|
|
26
|
+
# If no specificity is explicitly set and the RuleSet has *one* selector,
|
|
25
27
|
# the specificity is calculated using that selector.
|
|
26
28
|
#
|
|
27
|
-
# If no selectors
|
|
28
|
-
#
|
|
29
|
+
# If no selectors the specificity is treated as 0.
|
|
30
|
+
#
|
|
31
|
+
# If multiple selectors are present then the greatest specificity is used.
|
|
29
32
|
#
|
|
30
33
|
# ==== Example #1
|
|
31
34
|
# rs1 = RuleSet.new(nil, 'color: black;')
|
|
@@ -47,14 +50,12 @@ module CssParser
|
|
|
47
50
|
#--
|
|
48
51
|
# TODO: declaration_hashes should be able to contain a RuleSet
|
|
49
52
|
# this should be a Class method
|
|
50
|
-
def
|
|
51
|
-
@folded_declaration_cache = {}
|
|
52
|
-
|
|
53
|
+
def self.merge(*rule_sets)
|
|
53
54
|
# in case called like CssParser.merge([rule_set, rule_set])
|
|
54
|
-
rule_sets.flatten! if rule_sets[0].
|
|
55
|
-
|
|
56
|
-
unless rule_sets.all?
|
|
57
|
-
raise ArgumentError,
|
|
55
|
+
rule_sets.flatten! if rule_sets[0].is_a?(Array)
|
|
56
|
+
|
|
57
|
+
unless rule_sets.all?(CssParser::RuleSet)
|
|
58
|
+
raise ArgumentError, 'all parameters must be CssParser::RuleSets.'
|
|
58
59
|
end
|
|
59
60
|
|
|
60
61
|
return rule_sets[0] if rule_sets.length == 1
|
|
@@ -64,38 +65,29 @@ module CssParser
|
|
|
64
65
|
|
|
65
66
|
rule_sets.each do |rule_set|
|
|
66
67
|
rule_set.expand_shorthand!
|
|
67
|
-
|
|
68
|
+
|
|
68
69
|
specificity = rule_set.specificity
|
|
69
|
-
|
|
70
|
-
if rule_set.selectors.length == 1
|
|
71
|
-
specificity = calculate_specificity(rule_set.selectors[0])
|
|
72
|
-
else
|
|
73
|
-
specificity = 0
|
|
74
|
-
end
|
|
75
|
-
end
|
|
70
|
+
specificity ||= rule_set.selectors.filter_map { |s| calculate_specificity(s) }.max || 0
|
|
76
71
|
|
|
77
72
|
rule_set.each_declaration do |property, value, is_important|
|
|
78
73
|
# Add the property to the list to be folded per http://www.w3.org/TR/CSS21/cascade.html#cascading-order
|
|
79
|
-
if
|
|
80
|
-
properties[property] = {:
|
|
81
|
-
elsif is_important
|
|
82
|
-
properties[property]
|
|
83
|
-
|
|
74
|
+
if !properties.key?(property)
|
|
75
|
+
properties[property] = {value: value, specificity: specificity, is_important: is_important}
|
|
76
|
+
elsif is_important
|
|
77
|
+
if !properties[property][:is_important] || properties[property][:specificity] <= specificity
|
|
78
|
+
properties[property] = {value: value, specificity: specificity, is_important: is_important}
|
|
79
|
+
end
|
|
80
|
+
elsif properties[property][:specificity] < specificity || properties[property][:specificity] == specificity
|
|
84
81
|
unless properties[property][:is_important]
|
|
85
|
-
properties[property] = {:
|
|
82
|
+
properties[property] = {value: value, specificity: specificity, is_important: is_important}
|
|
86
83
|
end
|
|
87
84
|
end
|
|
88
|
-
|
|
85
|
+
end
|
|
89
86
|
end
|
|
90
87
|
|
|
91
|
-
merged = RuleSet.new(nil, nil)
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if details[:is_important]
|
|
95
|
-
merged[property.strip] = details[:value].strip.gsub(/\;\Z/, '') + '!important'
|
|
96
|
-
else
|
|
97
|
-
merged[property.strip] = details[:value].strip
|
|
98
|
-
end
|
|
88
|
+
merged = properties.each_with_object(RuleSet.new(nil, nil)) do |(property, details), rule_set|
|
|
89
|
+
value = details[:value].strip
|
|
90
|
+
rule_set[property.strip] = details[:is_important] ? "#{value.gsub(/;\Z/, '')}!important" : value
|
|
99
91
|
end
|
|
100
92
|
|
|
101
93
|
merged.create_shorthand!
|
|
@@ -113,15 +105,15 @@ module CssParser
|
|
|
113
105
|
#--
|
|
114
106
|
# Thanks to Rafael Salazar and Nick Fitzsimons on the css-discuss list for their help.
|
|
115
107
|
#++
|
|
116
|
-
def
|
|
108
|
+
def self.calculate_specificity(selector)
|
|
117
109
|
a = 0
|
|
118
|
-
b = selector.scan(
|
|
119
|
-
c = selector.scan(
|
|
120
|
-
d = selector.scan(
|
|
110
|
+
b = selector.scan('#').length
|
|
111
|
+
c = selector.scan(NON_ID_ATTRIBUTES_AND_PSEUDO_CLASSES_RX_NC).length
|
|
112
|
+
d = selector.scan(ELEMENTS_AND_PSEUDO_ELEMENTS_RX_NC).length
|
|
121
113
|
|
|
122
|
-
|
|
114
|
+
"#{a}#{b}#{c}#{d}".to_i
|
|
123
115
|
rescue
|
|
124
|
-
|
|
116
|
+
0
|
|
125
117
|
end
|
|
126
118
|
|
|
127
119
|
# Make <tt>url()</tt> links absolute.
|
|
@@ -134,26 +126,30 @@ module CssParser
|
|
|
134
126
|
# Returns a string.
|
|
135
127
|
#
|
|
136
128
|
# ==== Example
|
|
137
|
-
# CssParser.convert_uris("body { background: url('../style/yellow.png?abc=123') };",
|
|
129
|
+
# CssParser.convert_uris("body { background: url('../style/yellow.png?abc=123') };",
|
|
138
130
|
# "http://example.org/style/basic.css").inspect
|
|
139
131
|
# => "body { background: url('http://example.org/style/yellow.png?abc=123') };"
|
|
140
132
|
def self.convert_uris(css, base_uri)
|
|
141
|
-
base_uri = Addressable::URI.parse(base_uri) unless base_uri.
|
|
133
|
+
base_uri = Addressable::URI.parse(base_uri) unless base_uri.is_a?(Addressable::URI)
|
|
142
134
|
|
|
143
135
|
css.gsub(URI_RX) do
|
|
144
|
-
uri =
|
|
145
|
-
uri.gsub!(/["']+/, '')
|
|
136
|
+
uri = Regexp.last_match(1).to_s.gsub(/["']+/, '')
|
|
146
137
|
# Don't process URLs that are already absolute
|
|
147
|
-
unless uri
|
|
138
|
+
unless uri.match?(%r{^[a-z]+://}i)
|
|
148
139
|
begin
|
|
149
|
-
uri = base_uri
|
|
150
|
-
rescue
|
|
140
|
+
uri = base_uri.join(uri)
|
|
141
|
+
rescue
|
|
142
|
+
nil
|
|
143
|
+
end
|
|
151
144
|
end
|
|
152
|
-
"url('#{uri
|
|
145
|
+
"url('#{uri}')"
|
|
153
146
|
end
|
|
154
147
|
end
|
|
155
|
-
end
|
|
156
148
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
149
|
+
def self.sanitize_media_query(raw)
|
|
150
|
+
mq = raw.to_s.gsub(/\s+/, ' ')
|
|
151
|
+
mq.strip!
|
|
152
|
+
mq = 'all' if mq.empty?
|
|
153
|
+
mq.to_sym
|
|
154
|
+
end
|
|
155
|
+
end
|
metadata
CHANGED
|
@@ -1,89 +1,77 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: css_parser
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
5
|
-
prerelease:
|
|
4
|
+
version: 3.0.0
|
|
6
5
|
platform: ruby
|
|
7
6
|
authors:
|
|
8
7
|
- Alex Dunae
|
|
9
|
-
autorequire:
|
|
10
8
|
bindir: bin
|
|
11
9
|
cert_chain: []
|
|
12
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
13
11
|
dependencies:
|
|
14
12
|
- !ruby/object:Gem::Dependency
|
|
15
13
|
name: addressable
|
|
16
|
-
requirement:
|
|
17
|
-
none: false
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
18
15
|
requirements:
|
|
19
|
-
- -
|
|
16
|
+
- - ">="
|
|
20
17
|
- !ruby/object:Gem::Version
|
|
21
18
|
version: '0'
|
|
22
19
|
type: :runtime
|
|
23
20
|
prerelease: false
|
|
24
|
-
version_requirements:
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: ssrf_filter
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '1.5'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '1.5'
|
|
25
40
|
description: A set of classes for parsing CSS in Ruby.
|
|
26
41
|
email: code@dunae.ca
|
|
27
42
|
executables: []
|
|
28
43
|
extensions: []
|
|
29
44
|
extra_rdoc_files: []
|
|
30
45
|
files:
|
|
46
|
+
- MIT-LICENSE
|
|
31
47
|
- lib/css_parser.rb
|
|
32
48
|
- lib/css_parser/parser.rb
|
|
33
49
|
- lib/css_parser/regexps.rb
|
|
34
50
|
- lib/css_parser/rule_set.rb
|
|
35
|
-
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
- test/test_helper.rb
|
|
46
|
-
- test/test_merging.rb
|
|
47
|
-
- test/test_rule_set.rb
|
|
48
|
-
- test/test_rule_set_creating_shorthand.rb
|
|
49
|
-
- test/test_rule_set_expanding_shorthand.rb
|
|
50
|
-
homepage: https://github.com/alexdunae/css_parser
|
|
51
|
-
licenses: []
|
|
52
|
-
post_install_message:
|
|
53
|
-
rdoc_options:
|
|
54
|
-
- --all
|
|
55
|
-
- --inline-source
|
|
56
|
-
- --line-numbers
|
|
57
|
-
- --charset
|
|
58
|
-
- utf-8
|
|
51
|
+
- lib/css_parser/version.rb
|
|
52
|
+
homepage: https://github.com/premailer/css_parser
|
|
53
|
+
licenses:
|
|
54
|
+
- MIT
|
|
55
|
+
metadata:
|
|
56
|
+
changelog_uri: https://github.com/premailer/css_parser/blob/master/CHANGELOG.md
|
|
57
|
+
source_code_uri: https://github.com/premailer/css_parser
|
|
58
|
+
bug_tracker_uri: https://github.com/premailer/css_parser/issues
|
|
59
|
+
rubygems_mfa_required: 'true'
|
|
60
|
+
rdoc_options: []
|
|
59
61
|
require_paths:
|
|
60
62
|
- lib
|
|
61
63
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
62
|
-
none: false
|
|
63
64
|
requirements:
|
|
64
|
-
- -
|
|
65
|
+
- - ">="
|
|
65
66
|
- !ruby/object:Gem::Version
|
|
66
|
-
version: '
|
|
67
|
+
version: '3.3'
|
|
67
68
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
|
-
none: false
|
|
69
69
|
requirements:
|
|
70
|
-
- -
|
|
70
|
+
- - ">="
|
|
71
71
|
- !ruby/object:Gem::Version
|
|
72
72
|
version: '0'
|
|
73
73
|
requirements: []
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
signing_key:
|
|
77
|
-
specification_version: 3
|
|
74
|
+
rubygems_version: 4.0.3
|
|
75
|
+
specification_version: 4
|
|
78
76
|
summary: Ruby CSS parser.
|
|
79
|
-
test_files:
|
|
80
|
-
- test/test_css_parser_basic.rb
|
|
81
|
-
- test/test_css_parser_loading.rb
|
|
82
|
-
- test/test_css_parser_media_types.rb
|
|
83
|
-
- test/test_css_parser_misc.rb
|
|
84
|
-
- test/test_css_parser_regexps.rb
|
|
85
|
-
- test/test_helper.rb
|
|
86
|
-
- test/test_merging.rb
|
|
87
|
-
- test/test_rule_set.rb
|
|
88
|
-
- test/test_rule_set_creating_shorthand.rb
|
|
89
|
-
- test/test_rule_set_expanding_shorthand.rb
|
|
77
|
+
test_files: []
|
data/test/fixtures/import1.css
DELETED
data/test/fixtures/simple.css
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
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
|
|
@@ -1,146 +0,0 @@
|
|
|
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
|
|
@@ -1,106 +0,0 @@
|
|
|
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
|
-
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 test_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 test_adding_block_and_limiting_media_types1
|
|
60
|
-
css = <<-EOT
|
|
61
|
-
@import "import1.css", print
|
|
62
|
-
EOT
|
|
63
|
-
|
|
64
|
-
base_dir = File.dirname(__FILE__) + '/fixtures/'
|
|
65
|
-
|
|
66
|
-
@cp.add_block!(css, :only_media_types => :screen, :base_dir => base_dir)
|
|
67
|
-
assert @cp.find_by_selector('div').empty?
|
|
68
|
-
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def test_adding_block_and_limiting_media_types2
|
|
72
|
-
css = <<-EOT
|
|
73
|
-
@import "import1.css", print
|
|
74
|
-
EOT
|
|
75
|
-
|
|
76
|
-
base_dir = File.dirname(__FILE__) + '/fixtures/'
|
|
77
|
-
|
|
78
|
-
@cp.add_block!(css, :only_media_types => :print, :base_dir => base_dir)
|
|
79
|
-
assert_match 'color: lime', @cp.find_by_selector('div').join(' ')
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def test_adding_block_and_limiting_media_types
|
|
83
|
-
css = <<-EOT
|
|
84
|
-
@import "import1.css"
|
|
85
|
-
EOT
|
|
86
|
-
|
|
87
|
-
base_dir = File.dirname(__FILE__) + '/fixtures/'
|
|
88
|
-
|
|
89
|
-
@cp.add_block!(css, :only_media_types => :print, :base_dir => base_dir)
|
|
90
|
-
assert_match 'color: lime', @cp.find_by_selector('div').join(' ')
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
def test_adding_rule_set_with_media_type
|
|
95
|
-
@cp.add_rule!('body', 'color: black;', [:handheld,:tty])
|
|
96
|
-
@cp.add_rule!('body', 'color: blue;', :screen)
|
|
97
|
-
assert_equal 'color: black;', @cp.find_by_selector('body', :handheld).join(' ')
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def test_selecting_with_all_media_types
|
|
101
|
-
@cp.add_rule!('body', 'color: black;', [:handheld,:tty])
|
|
102
|
-
assert_equal 'color: black;', @cp.find_by_selector('body', :all).join(' ')
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
end
|