roadie 4.0.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +43 -0
- data/.solargraph.yml +16 -0
- data/Changelog.md +14 -2
- data/Gemfile +5 -2
- data/README.md +11 -13
- data/Rakefile +2 -2
- data/lib/roadie/asset_provider.rb +3 -1
- data/lib/roadie/asset_scanner.rb +6 -6
- data/lib/roadie/cached_provider.rb +1 -0
- data/lib/roadie/deduplicator.rb +1 -0
- data/lib/roadie/document.rb +7 -10
- data/lib/roadie/errors.rb +18 -14
- data/lib/roadie/filesystem_provider.rb +13 -3
- data/lib/roadie/inliner.rb +49 -19
- data/lib/roadie/markup_improver.rb +22 -31
- data/lib/roadie/net_http_provider.rb +25 -11
- data/lib/roadie/null_provider.rb +18 -5
- data/lib/roadie/null_url_rewriter.rb +6 -2
- data/lib/roadie/path_rewriter_provider.rb +4 -1
- data/lib/roadie/provider_list.rb +15 -11
- data/lib/roadie/rspec/asset_provider.rb +4 -1
- data/lib/roadie/rspec.rb +2 -2
- data/lib/roadie/selector.rb +15 -5
- data/lib/roadie/style_attribute_builder.rb +2 -1
- data/lib/roadie/style_block.rb +3 -3
- data/lib/roadie/style_property.rb +3 -2
- data/lib/roadie/stylesheet.rb +2 -13
- data/lib/roadie/url_generator.rb +24 -8
- data/lib/roadie/url_rewriter.rb +6 -3
- data/lib/roadie/utils.rb +1 -1
- data/lib/roadie/version.rb +1 -2
- data/lib/roadie.rb +23 -23
- data/roadie.gemspec +23 -25
- data/spec/hash_as_cache_store_spec.rb +1 -1
- data/spec/integration_spec.rb +41 -44
- data/spec/lib/roadie/asset_scanner_spec.rb +9 -4
- data/spec/lib/roadie/cached_provider_spec.rb +4 -4
- data/spec/lib/roadie/css_not_found_spec.rb +8 -5
- data/spec/lib/roadie/deduplicator_spec.rb +3 -3
- data/spec/lib/roadie/document_spec.rb +45 -27
- data/spec/lib/roadie/filesystem_provider_spec.rb +8 -10
- data/spec/lib/roadie/inliner_spec.rb +40 -44
- data/spec/lib/roadie/markup_improver_spec.rb +17 -25
- data/spec/lib/roadie/net_http_provider_spec.rb +8 -8
- data/spec/lib/roadie/null_provider_spec.rb +2 -2
- data/spec/lib/roadie/null_url_rewriter_spec.rb +2 -2
- data/spec/lib/roadie/path_rewriter_provider_spec.rb +4 -4
- data/spec/lib/roadie/provider_list_spec.rb +25 -21
- data/spec/lib/roadie/selector_spec.rb +4 -4
- data/spec/lib/roadie/style_attribute_builder_spec.rb +5 -5
- data/spec/lib/roadie/style_block_spec.rb +1 -1
- data/spec/lib/roadie/style_property_spec.rb +8 -8
- data/spec/lib/roadie/stylesheet_spec.rb +2 -20
- data/spec/lib/roadie/test_provider_spec.rb +4 -4
- data/spec/lib/roadie/url_generator_spec.rb +1 -1
- data/spec/lib/roadie/url_rewriter_spec.rb +6 -4
- data/spec/spec_helper.rb +8 -8
- data/spec/support/have_attribute_matcher.rb +1 -2
- data/spec/support/have_node_matcher.rb +3 -3
- data/spec/support/have_selector_matcher.rb +2 -3
- data/spec/support/have_styling_matcher.rb +10 -11
- data/spec/support/have_xpath_matcher.rb +2 -3
- metadata +22 -21
- data/.travis.yml +0 -20
@@ -1,11 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "spec_helper"
|
4
4
|
|
5
5
|
module Roadie
|
6
6
|
describe Inliner do
|
7
|
-
before { @stylesheet = ""
|
8
|
-
def use_css(css)
|
7
|
+
before { @stylesheet = "" }
|
8
|
+
def use_css(css)
|
9
|
+
@stylesheet = Stylesheet.new("example", css)
|
10
|
+
end
|
9
11
|
|
10
12
|
def rendering(html, stylesheet = @stylesheet)
|
11
13
|
dom = Nokogiri::HTML.parse html
|
@@ -15,17 +17,17 @@ module Roadie
|
|
15
17
|
|
16
18
|
describe "inlining styles" do
|
17
19
|
it "inlines simple attributes" do
|
18
|
-
use_css
|
19
|
-
expect(rendering(
|
20
|
+
use_css "p { color: green }"
|
21
|
+
expect(rendering("<p></p>")).to have_styling("color" => "green")
|
20
22
|
end
|
21
23
|
|
22
24
|
it "keeps multiple versions of the same property to support progressive enhancement" do
|
23
25
|
# https://github.com/premailer/css_parser/issues/44
|
24
26
|
pending "css_parser issue #44"
|
25
27
|
|
26
|
-
use_css
|
27
|
-
expect(rendering(
|
28
|
-
[[
|
28
|
+
use_css "p { color: #eee; color: rgba(255, 255, 255, 0.9); }"
|
29
|
+
expect(rendering("<p></p>")).to have_styling(
|
30
|
+
[["color", "green"], ["color", "rgba(255, 255, 255, 0.9)"]]
|
29
31
|
)
|
30
32
|
end
|
31
33
|
|
@@ -36,35 +38,35 @@ module Roadie
|
|
36
38
|
.positive { color: green; }
|
37
39
|
'
|
38
40
|
expect(rendering('<p class="message positive"></p>')).to have_styling(
|
39
|
-
[[
|
41
|
+
[["color", "blue"], ["color", "green"]]
|
40
42
|
)
|
41
43
|
end
|
42
44
|
|
43
45
|
it "inlines browser-prefixed attributes" do
|
44
|
-
use_css
|
45
|
-
expect(rendering(
|
46
|
+
use_css "p { -vendor-color: green }"
|
47
|
+
expect(rendering("<p></p>")).to have_styling("-vendor-color" => "green")
|
46
48
|
end
|
47
49
|
|
48
50
|
it "inlines CSS3 attributes" do
|
49
|
-
use_css
|
50
|
-
expect(rendering(
|
51
|
+
use_css "p { border-radius: 2px; }"
|
52
|
+
expect(rendering("<p></p>")).to have_styling("border-radius" => "2px")
|
51
53
|
end
|
52
54
|
|
53
55
|
it "keeps the order of the styles that are inlined" do
|
54
|
-
use_css
|
55
|
-
expect(rendering(
|
56
|
+
use_css "h1 { padding: 2px; margin: 5px; }"
|
57
|
+
expect(rendering("<h1></h1>")).to have_styling([["padding", "2px"], ["margin", "5px"]])
|
56
58
|
end
|
57
59
|
|
58
60
|
it "combines multiple selectors into one" do
|
59
61
|
use_css 'p { color: green; }
|
60
62
|
.tip { float: right; }'
|
61
|
-
expect(rendering('<p class="tip"></p>')).to have_styling([[
|
63
|
+
expect(rendering('<p class="tip"></p>')).to have_styling([["color", "green"], ["float", "right"]])
|
62
64
|
end
|
63
65
|
|
64
66
|
it "uses the attributes with the highest specificity when conflicts arises" do
|
65
67
|
use_css ".safe { color: green; }
|
66
68
|
p { color: red; }"
|
67
|
-
expect(rendering('<p class="safe"></p>')).to have_styling([[
|
69
|
+
expect(rendering('<p class="safe"></p>')).to have_styling([["color", "red"], ["color", "green"]])
|
68
70
|
end
|
69
71
|
|
70
72
|
it "sorts styles by specificity order" do
|
@@ -82,10 +84,10 @@ module Roadie
|
|
82
84
|
end
|
83
85
|
|
84
86
|
it "supports multiple selectors for the same rules" do
|
85
|
-
use_css
|
86
|
-
rendering(
|
87
|
-
expect(document).to have_styling(
|
88
|
-
expect(document).to have_styling(
|
87
|
+
use_css "p, a { color: green; }"
|
88
|
+
rendering("<p></p><a></a>").tap do |document|
|
89
|
+
expect(document).to have_styling("color" => "green").at_selector("p")
|
90
|
+
expect(document).to have_styling("color" => "green").at_selector("a")
|
89
91
|
end
|
90
92
|
end
|
91
93
|
|
@@ -93,22 +95,22 @@ module Roadie
|
|
93
95
|
use_css "a { text-decoration: underline !important; }
|
94
96
|
a.hard-to-spot { text-decoration: none; }"
|
95
97
|
expect(rendering('<a class="hard-to-spot"></a>')).to have_styling([
|
96
|
-
[
|
98
|
+
["text-decoration", "none"], ["text-decoration", "underline !important"]
|
97
99
|
])
|
98
100
|
end
|
99
101
|
|
100
102
|
it "combines with already present inline styles" do
|
101
103
|
use_css "p { color: green }"
|
102
|
-
expect(rendering('<p style="font-size: 1.1em"></p>')).to have_styling([[
|
104
|
+
expect(rendering('<p style="font-size: 1.1em"></p>')).to have_styling([["color", "green"], ["font-size", "1.1em"]])
|
103
105
|
end
|
104
106
|
|
105
107
|
it "does not override inline styles" do
|
106
108
|
use_css "p { text-transform: uppercase; color: red }"
|
107
109
|
# The two color properties are kept to make css fallbacks work correctly
|
108
110
|
expect(rendering('<p style="color: green"></p>')).to have_styling([
|
109
|
-
[
|
110
|
-
[
|
111
|
-
[
|
111
|
+
["text-transform", "uppercase"],
|
112
|
+
["color", "red"],
|
113
|
+
["color", "green"]
|
112
114
|
])
|
113
115
|
end
|
114
116
|
|
@@ -123,7 +125,7 @@ module Roadie
|
|
123
125
|
|
124
126
|
p.active { width: 100%; }
|
125
127
|
"
|
126
|
-
expect(rendering('<p class="active"></p>')).to have_styling(
|
128
|
+
expect(rendering('<p class="active"></p>')).to have_styling("width" => "100%")
|
127
129
|
end
|
128
130
|
|
129
131
|
it "does not crash on any pseudo element selectors" do
|
@@ -131,7 +133,7 @@ module Roadie
|
|
131
133
|
p.some-element { width: 100%; }
|
132
134
|
p::some-element { color: red; }
|
133
135
|
"
|
134
|
-
expect(rendering('<p class="some-element"></p>')).to have_styling(
|
136
|
+
expect(rendering('<p class="some-element"></p>')).to have_styling("width" => "100%")
|
135
137
|
end
|
136
138
|
|
137
139
|
it "warns on selectors that crash Nokogiri" do
|
@@ -140,7 +142,7 @@ module Roadie
|
|
140
142
|
stylesheet = Stylesheet.new "foo.css", "p[%^=foo] { color: red; }"
|
141
143
|
inliner = Inliner.new([stylesheet], dom)
|
142
144
|
expect(Utils).to receive(:warn).with(
|
143
|
-
%
|
145
|
+
%(Cannot inline "p[%^=foo]" from "foo.css" stylesheet. If this is valid CSS, please report a bug.)
|
144
146
|
)
|
145
147
|
inliner.inline
|
146
148
|
end
|
@@ -152,8 +154,8 @@ module Roadie
|
|
152
154
|
"
|
153
155
|
result = rendering("<p></p> <p></p>")
|
154
156
|
|
155
|
-
expect(result).to have_styling([[
|
156
|
-
expect(result).to have_styling([[
|
157
|
+
expect(result).to have_styling([["color", "red"]]).at_selector("p:first")
|
158
|
+
expect(result).to have_styling([["color", "red"], ["color", "green"]]).at_selector("p:last")
|
157
159
|
end
|
158
160
|
|
159
161
|
context "with uninlinable selectors" do
|
@@ -162,7 +164,7 @@ module Roadie
|
|
162
164
|
end
|
163
165
|
|
164
166
|
it "puts them in a new <style> element in the <head>" do
|
165
|
-
use_css
|
167
|
+
use_css "a:hover { color: red; }"
|
166
168
|
result = rendering("
|
167
169
|
<html>
|
168
170
|
<head></head>
|
@@ -174,7 +176,7 @@ module Roadie
|
|
174
176
|
end
|
175
177
|
|
176
178
|
it "puts them in <head> on unexpected inlining problems" do
|
177
|
-
use_css
|
179
|
+
use_css "p:some-future-thing { color: red; }"
|
178
180
|
result = rendering("
|
179
181
|
<html>
|
180
182
|
<head></head>
|
@@ -198,15 +200,9 @@ module Roadie
|
|
198
200
|
}'
|
199
201
|
|
200
202
|
use_css css
|
201
|
-
result = rendering(
|
203
|
+
result = rendering("<p></p>")
|
202
204
|
|
203
205
|
expect(result).to have_styling([]).at_selector("p")
|
204
|
-
|
205
|
-
# css_parser actually sees an empty @keyframes on JRuby, and nothing
|
206
|
-
# on the others
|
207
|
-
if (style_element = result.at_css("head > style"))
|
208
|
-
expect(style_element.text).to_not include "background-position"
|
209
|
-
end
|
210
206
|
end
|
211
207
|
|
212
208
|
it "ignores them if told not to keep them" do
|
@@ -225,14 +221,14 @@ module Roadie
|
|
225
221
|
end
|
226
222
|
|
227
223
|
it "puts the <style> element at the root when told so" do
|
228
|
-
stylesheet = use_css
|
224
|
+
stylesheet = use_css "a:hover { color: red; }"
|
229
225
|
dom = Nokogiri::HTML.fragment("
|
230
226
|
<a></a>
|
231
227
|
")
|
232
228
|
|
233
229
|
Inliner.new([stylesheet], dom).inline(
|
234
230
|
keep_uninlinable_css: true,
|
235
|
-
keep_uninlinable_in: :root
|
231
|
+
keep_uninlinable_in: :root
|
236
232
|
)
|
237
233
|
|
238
234
|
expect(dom).to have_xpath("./a")
|
@@ -240,7 +236,7 @@ module Roadie
|
|
240
236
|
end
|
241
237
|
|
242
238
|
it "raises error when told to save styles in an unknown place" do
|
243
|
-
stylesheet = use_css
|
239
|
+
stylesheet = use_css "a:hover { color: red; }"
|
244
240
|
dom = Nokogiri::HTML.fragment("
|
245
241
|
<a></a>
|
246
242
|
")
|
@@ -249,7 +245,7 @@ module Roadie
|
|
249
245
|
expect {
|
250
246
|
inliner.inline(
|
251
247
|
keep_uninlinable_css: true,
|
252
|
-
keep_uninlinable_in: :unknown_place
|
248
|
+
keep_uninlinable_in: :unknown_place
|
253
249
|
)
|
254
250
|
}.to raise_error(ArgumentError, /:unknown_place/)
|
255
251
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "spec_helper"
|
4
4
|
|
5
5
|
module Roadie
|
6
6
|
describe MarkupImprover do
|
@@ -10,22 +10,14 @@ module Roadie
|
|
10
10
|
dom
|
11
11
|
end
|
12
12
|
|
13
|
-
# JRuby up to at least 1.6.0 has a bug where the doctype of a document cannot be changed.
|
14
|
-
# See https://github.com/sparklemotion/nokogiri/issues/984
|
15
|
-
def pending_for_buggy_jruby
|
16
|
-
# No reason to check for version yet since no existing version has a fix.
|
17
|
-
skip "Pending until Nokogiri issue #984 is fixed and released" if defined?(JRuby)
|
18
|
-
end
|
19
|
-
|
20
13
|
describe "automatic doctype" do
|
21
14
|
it "inserts a HTML5 doctype if no doctype is present" do
|
22
|
-
pending_for_buggy_jruby
|
23
15
|
expect(improve("<html></html>").internal_subset.to_xml).to eq("<!DOCTYPE html>")
|
24
16
|
end
|
25
17
|
|
26
18
|
it "does not insert duplicate doctypes" do
|
27
|
-
html = improve(
|
28
|
-
expect(html.scan(
|
19
|
+
html = improve("<!DOCTYPE html><html><body></body></html>").to_html
|
20
|
+
expect(html.scan("DOCTYPE").size).to eq(1)
|
29
21
|
end
|
30
22
|
|
31
23
|
it "leaves other doctypes alone" do
|
@@ -39,35 +31,35 @@ module Roadie
|
|
39
31
|
it "inserts a <html> element as the root" do
|
40
32
|
expect(improve("")).to have_selector("html")
|
41
33
|
expect(improve("<h1>Hey!</h1>")).to have_selector("html h1")
|
42
|
-
expect(improve("<html></html>").css(
|
34
|
+
expect(improve("<html></html>").css("html").size).to eq(1)
|
43
35
|
end
|
44
36
|
|
45
37
|
it "inserts <head> if not present" do
|
46
|
-
expect(improve(
|
47
|
-
expect(improve(
|
48
|
-
expect(improve(
|
49
|
-
expect(improve(
|
38
|
+
expect(improve("<html><body></body></html>")).to have_selector("html > head + body")
|
39
|
+
expect(improve("<html></html>")).to have_selector("html > head")
|
40
|
+
expect(improve("Foo")).to have_selector("html > head")
|
41
|
+
expect(improve("<html><head></head></html>").css("head").size).to eq(1)
|
50
42
|
end
|
51
43
|
|
52
44
|
it "inserts <body> if not present" do
|
53
|
-
expect(improve(
|
54
|
-
expect(improve(
|
55
|
-
expect(improve(
|
45
|
+
expect(improve("<h1>Hey!</h1>")).to have_selector("html > body > h1")
|
46
|
+
expect(improve("<html><h1>Hey!</h1></html>")).to have_selector("html > body > h1")
|
47
|
+
expect(improve("<html><body><h1>Hey!</h1></body></html>").css("body").size).to eq(1)
|
56
48
|
end
|
57
49
|
end
|
58
50
|
|
59
51
|
describe "charset declaration" do
|
60
52
|
it "is inserted if missing" do
|
61
|
-
dom = improve(
|
53
|
+
dom = improve("<html><head></head><body></body></html>")
|
62
54
|
|
63
|
-
expect(dom).to have_selector(
|
64
|
-
meta = dom.at_css(
|
65
|
-
expect(meta[
|
66
|
-
expect(meta[
|
55
|
+
expect(dom).to have_selector("head meta")
|
56
|
+
meta = dom.at_css("head meta")
|
57
|
+
expect(meta["http-equiv"]).to eq("Content-Type")
|
58
|
+
expect(meta["content"]).to eq("text/html; charset=UTF-8")
|
67
59
|
end
|
68
60
|
|
69
61
|
it "is left alone when predefined" do
|
70
|
-
expect(improve(<<-HTML).xpath(
|
62
|
+
expect(improve(<<-HTML).xpath("//meta")).to have(1).item
|
71
63
|
<html>
|
72
64
|
<head>
|
73
65
|
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require "spec_helper"
|
4
|
+
require "roadie/rspec"
|
5
|
+
require "shared_examples/asset_provider"
|
6
6
|
|
7
7
|
module Roadie
|
8
8
|
describe NetHttpProvider do
|
@@ -12,7 +12,7 @@ module Roadie
|
|
12
12
|
WebMock.allow_net_connect!
|
13
13
|
end
|
14
14
|
|
15
|
-
url = "http://example.com/style.css"
|
15
|
+
url = "http://example.com/style.css"
|
16
16
|
|
17
17
|
it_behaves_like(
|
18
18
|
"roadie asset provider",
|
@@ -51,7 +51,7 @@ module Roadie
|
|
51
51
|
# use when trying to make sense of these bytes.
|
52
52
|
stub_request(:get, url).and_return(
|
53
53
|
body: (+%(p::before { content: "l\xF6ve" })).force_encoding("US-ASCII"),
|
54
|
-
headers: {"Content-Type" => "text/css;charset=ISO-8859-1"}
|
54
|
+
headers: {"Content-Type" => "text/css;charset=ISO-8859-1"}
|
55
55
|
)
|
56
56
|
|
57
57
|
# Seems like CssParser strips out the non-ascii character for some
|
@@ -67,7 +67,7 @@ module Roadie
|
|
67
67
|
it "assumes UTF-8 encoding if server headers do not specify a charset" do
|
68
68
|
stub_request(:get, url).and_return(
|
69
69
|
body: (+%(p::before { content: "Åh nej" })).force_encoding("US-ASCII"),
|
70
|
-
headers: {"Content-Type" => "text/css"}
|
70
|
+
headers: {"Content-Type" => "text/css"}
|
71
71
|
)
|
72
72
|
|
73
73
|
# Seems like CssParser strips out the non-ascii characters for some
|
@@ -119,10 +119,10 @@ module Roadie
|
|
119
119
|
provider = NetHttpProvider.new(whitelist: ["whitelisted.example.com"])
|
120
120
|
|
121
121
|
whitelisted_url = "http://whitelisted.example.com/style.css"
|
122
|
-
other_url
|
122
|
+
other_url = "http://www.example.com/style.css"
|
123
123
|
|
124
124
|
whitelisted_request = stub_request(:get, whitelisted_url).and_return(body: +"x")
|
125
|
-
other_request
|
125
|
+
other_request = stub_request(:get, other_url).and_return(body: +"x")
|
126
126
|
|
127
127
|
expect(provider.find_stylesheet(other_url)).to be_nil
|
128
128
|
expect {
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require "spec_helper"
|
4
|
+
require "roadie/rspec"
|
5
|
+
require "shared_examples/asset_provider"
|
6
6
|
|
7
7
|
module Roadie
|
8
8
|
describe PathRewriterProvider do
|
@@ -10,7 +10,7 @@ module Roadie
|
|
10
10
|
|
11
11
|
subject(:provider) do
|
12
12
|
PathRewriterProvider.new(upstream) do |path|
|
13
|
-
path.gsub(
|
13
|
+
path.gsub("well", "good")
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "spec_helper"
|
4
|
+
require "roadie/rspec"
|
5
5
|
|
6
6
|
module Roadie
|
7
7
|
describe ProviderList do
|
@@ -69,36 +69,40 @@ module Roadie
|
|
69
69
|
provider = double("Provider", to_s: "Some provider")
|
70
70
|
sublist = ProviderList.new([provider, provider])
|
71
71
|
list = ProviderList.new([provider, sublist, provider])
|
72
|
-
expect(list.to_s).to
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
72
|
+
expect(list.to_s).to eq(<<~TEXT)
|
73
|
+
ProviderList: [
|
74
|
+
\tSome provider,
|
75
|
+
\tProviderList: [
|
76
|
+
\t\tSome provider,
|
77
|
+
\t\tSome provider
|
78
|
+
\t],
|
79
|
+
\tSome provider
|
80
|
+
]
|
81
|
+
TEXT
|
82
82
|
end
|
83
83
|
|
84
84
|
it "raises a readable error message" do
|
85
85
|
provider = double("Provider", to_s: "Some provider")
|
86
86
|
allow(provider).to receive(:find_stylesheet!).and_raise(
|
87
|
-
CssNotFound.new(
|
87
|
+
CssNotFound.new(
|
88
|
+
css_name: "style.css",
|
89
|
+
message: "I tripped",
|
90
|
+
provider: provider
|
91
|
+
)
|
88
92
|
)
|
89
93
|
|
90
94
|
sublist = ProviderList.new([provider, provider])
|
91
95
|
list = ProviderList.new([provider, sublist, provider])
|
92
96
|
|
93
97
|
expect { list.find_stylesheet!("style.css") }.to raise_error { |error|
|
94
|
-
expect(error.message).to eq(
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
98
|
+
expect(error.message).to eq(<<~TEXT)
|
99
|
+
Could not find stylesheet "style.css": All providers failed
|
100
|
+
Used providers:
|
101
|
+
\tSome provider: I tripped
|
102
|
+
\tSome provider: I tripped
|
103
|
+
\tSome provider: I tripped
|
104
|
+
\tSome provider: I tripped
|
105
|
+
TEXT
|
102
106
|
}
|
103
107
|
end
|
104
108
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "spec_helper"
|
4
4
|
|
5
5
|
module Roadie
|
6
6
|
describe Selector do
|
@@ -31,15 +31,15 @@ module Roadie
|
|
31
31
|
expect(Selector.new(bad_selector)).not_to be_inlinable
|
32
32
|
end
|
33
33
|
|
34
|
-
expect(Selector.new(
|
34
|
+
expect(Selector.new("p.active")).to be_inlinable
|
35
35
|
end
|
36
36
|
|
37
37
|
it "cannot be inlined when containing pseudo elements" do
|
38
|
-
expect(Selector.new(
|
38
|
+
expect(Selector.new("p::some-element")).not_to be_inlinable
|
39
39
|
end
|
40
40
|
|
41
41
|
it "cannot be inlined when selector is an at-rule" do
|
42
|
-
expect(Selector.new(
|
42
|
+
expect(Selector.new("@keyframes progress-bar-stripes")).not_to be_inlinable
|
43
43
|
end
|
44
44
|
|
45
45
|
it "has a calculated specificity" do
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "spec_helper"
|
4
4
|
|
5
5
|
module Roadie
|
6
6
|
describe StyleAttributeBuilder do
|
@@ -17,8 +17,8 @@ module Roadie
|
|
17
17
|
it "preserves the order of added attributes with the same specificity" do
|
18
18
|
builder = StyleAttributeBuilder.new
|
19
19
|
|
20
|
-
builder << StyleProperty.new("color", "pink",
|
21
|
-
builder << StyleProperty.new("color", "red",
|
20
|
+
builder << StyleProperty.new("color", "pink", false, 50)
|
21
|
+
builder << StyleProperty.new("color", "red", false, 50)
|
22
22
|
builder << StyleProperty.new("color", "green", false, 50)
|
23
23
|
|
24
24
|
# We need one different element to trigger the problem with Ruby's
|
@@ -31,9 +31,9 @@ module Roadie
|
|
31
31
|
it "removes duplicate properties" do
|
32
32
|
builder = StyleAttributeBuilder.new
|
33
33
|
|
34
|
-
builder << StyleProperty.new("color", "pink",
|
34
|
+
builder << StyleProperty.new("color", "pink", false, 10)
|
35
35
|
builder << StyleProperty.new("color", "green", false, 20)
|
36
|
-
builder << StyleProperty.new("color", "pink",
|
36
|
+
builder << StyleProperty.new("color", "pink", false, 50)
|
37
37
|
|
38
38
|
expect(builder.attribute_string).to eq "color:green;color:pink"
|
39
39
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "spec_helper"
|
4
4
|
|
5
5
|
module Roadie
|
6
6
|
describe StyleProperty do
|
7
7
|
it "is initialized with a property, value, if it is marked as important, and the specificity" do
|
8
|
-
StyleProperty.new(
|
9
|
-
expect(declaration.property).to eq(
|
10
|
-
expect(declaration.value).to eq(
|
8
|
+
StyleProperty.new("color", "green", true, 45).tap do |declaration|
|
9
|
+
expect(declaration.property).to eq("color")
|
10
|
+
expect(declaration.value).to eq("green")
|
11
11
|
expect(declaration).to be_important
|
12
12
|
expect(declaration.specificity).to eq(45)
|
13
13
|
end
|
@@ -15,18 +15,18 @@ module Roadie
|
|
15
15
|
|
16
16
|
describe "string representation" do
|
17
17
|
it "is the property and the value joined with a colon" do
|
18
|
-
expect(StyleProperty.new(
|
19
|
-
expect(StyleProperty.new(
|
18
|
+
expect(StyleProperty.new("color", "green", false, 1).to_s).to eq("color:green")
|
19
|
+
expect(StyleProperty.new("font-size", "1.1em", false, 1).to_s).to eq("font-size:1.1em")
|
20
20
|
end
|
21
21
|
|
22
22
|
it "contains the !important flag when set" do
|
23
|
-
expect(StyleProperty.new(
|
23
|
+
expect(StyleProperty.new("color", "green", true, 1).to_s).to eq("color:green !important")
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
describe "comparing" do
|
28
28
|
def declaration(specificity, important = false)
|
29
|
-
StyleProperty.new(
|
29
|
+
StyleProperty.new("color", "green", important, specificity)
|
30
30
|
end
|
31
31
|
|
32
32
|
it "compares on specificity" do
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "spec_helper"
|
4
4
|
|
5
5
|
module Roadie
|
6
6
|
describe Stylesheet do
|
@@ -18,28 +18,10 @@ module Roadie
|
|
18
18
|
expect(stylesheet.blocks.map(&:to_s)).to eq([
|
19
19
|
"body{color:green !important;font-size:200%}",
|
20
20
|
"a{color:red}",
|
21
|
-
"i{color:red}"
|
21
|
+
"i{color:red}"
|
22
22
|
])
|
23
23
|
end
|
24
24
|
|
25
|
-
if VERSION < "4.0"
|
26
|
-
it "can iterate all inlinable blocks" do
|
27
|
-
inlinable = double(inlinable?: true, selector: "good", properties: "props")
|
28
|
-
bad = double(inlinable?: false, selector: "bad", properties: "props")
|
29
|
-
|
30
|
-
stylesheet = Stylesheet.new("example.css", "")
|
31
|
-
allow(stylesheet).to receive_messages blocks: [bad, inlinable, bad]
|
32
|
-
|
33
|
-
expect(stylesheet.each_inlinable_block.to_a).to eq([
|
34
|
-
["good", "props"],
|
35
|
-
])
|
36
|
-
end
|
37
|
-
else
|
38
|
-
it "should no longer have #each_inlinable_block" do
|
39
|
-
fail "Remove #each_inlinable_block"
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
25
|
it "has a string representation of the contents" do
|
44
26
|
stylesheet = Stylesheet.new("example.css", "body { color: green;}a{ color: red; font-size: small }")
|
45
27
|
expect(stylesheet.to_s).to eq("body{color:green}\na{color:red;font-size:small}")
|