roadie 3.2.2 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -0
- data/Changelog.md +15 -1
- data/README.md +88 -8
- data/lib/roadie/asset_scanner.rb +0 -7
- data/lib/roadie/document.rb +83 -7
- data/lib/roadie/inliner.rb +28 -11
- data/lib/roadie/net_http_provider.rb +16 -1
- data/lib/roadie/url_rewriter.rb +5 -1
- data/lib/roadie/version.rb +1 -1
- data/spec/integration_spec.rb +464 -234
- data/spec/lib/roadie/asset_scanner_spec.rb +0 -19
- data/spec/lib/roadie/document_spec.rb +82 -0
- data/spec/lib/roadie/inliner_spec.rb +31 -1
- data/spec/lib/roadie/net_http_provider_spec.rb +35 -0
- data/spec/lib/roadie/url_rewriter_spec.rb +16 -0
- data/spec/support/have_selector_matcher.rb +2 -2
- data/spec/support/have_xpath_matcher.rb +6 -0
- metadata +5 -3
@@ -192,25 +192,6 @@ module Roadie
|
|
192
192
|
expect(dom).to_not have_selector("link[href*=some]")
|
193
193
|
expect(dom).to have_selector("link[href*=other]")
|
194
194
|
end
|
195
|
-
|
196
|
-
it "removes the data-roadie-ignore markers" do
|
197
|
-
dom = dom_document <<-HTML
|
198
|
-
<html>
|
199
|
-
<head>
|
200
|
-
<link rel="stylesheet" href="/cool.css" data-roadie-ignore id="first">
|
201
|
-
</head>
|
202
|
-
<body>
|
203
|
-
<style data-roadie-ignore id="second">a { color: red; }</style>
|
204
|
-
</body>
|
205
|
-
</html>
|
206
|
-
HTML
|
207
|
-
scanner = AssetScanner.new dom, TestProvider.new, external_provider
|
208
|
-
|
209
|
-
scanner.extract_css
|
210
|
-
|
211
|
-
expect(dom.at_css("#first").attributes).to_not include("data-roadie-ignore")
|
212
|
-
expect(dom.at_css("#second").attributes).to_not include("data-roadie-ignore")
|
213
|
-
end
|
214
195
|
end
|
215
196
|
end
|
216
197
|
end
|
@@ -35,6 +35,10 @@ module Roadie
|
|
35
35
|
expect(provider).to be_instance_of(FilesystemProvider)
|
36
36
|
end
|
37
37
|
|
38
|
+
it "defaults to HTML mode" do
|
39
|
+
expect(document.mode).to eq(:html)
|
40
|
+
end
|
41
|
+
|
38
42
|
it "allows changes to the normal asset providers" do
|
39
43
|
other_provider = double "Other proider"
|
40
44
|
old_list = document.asset_providers
|
@@ -59,6 +63,20 @@ module Roadie
|
|
59
63
|
expect(document.external_asset_providers).to eq(old_list)
|
60
64
|
end
|
61
65
|
|
66
|
+
it "allows changes to the mode setting" do
|
67
|
+
document.mode = :xhtml
|
68
|
+
expect(document.mode).to eq(:xhtml)
|
69
|
+
|
70
|
+
document.mode = :html
|
71
|
+
expect(document.mode).to eq(:html)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "does not allow unknown modes" do
|
75
|
+
expect {
|
76
|
+
document.mode = :other
|
77
|
+
}.to raise_error(ArgumentError, /:other/)
|
78
|
+
end
|
79
|
+
|
62
80
|
it "can store callbacks for inlining" do
|
63
81
|
callable = double "Callable"
|
64
82
|
|
@@ -98,6 +116,48 @@ module Roadie
|
|
98
116
|
}
|
99
117
|
expect { document.transform }.to_not raise_error
|
100
118
|
end
|
119
|
+
|
120
|
+
context "in HTML mode" do
|
121
|
+
it "does not escape curly braces" do
|
122
|
+
document = Document.new "<body><a href='https://google.com/{{hello}}'>Hello</a></body>"
|
123
|
+
document.mode = :xhtml
|
124
|
+
|
125
|
+
expect(document.transform).to include("{{hello}}")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "partial transforming" do
|
131
|
+
it "runs the before and after callbacks" do
|
132
|
+
document = Document.new "<p></p>"
|
133
|
+
before = ->{}
|
134
|
+
after = ->{}
|
135
|
+
document.before_transformation = before
|
136
|
+
document.after_transformation = after
|
137
|
+
|
138
|
+
expect(before).to receive(:call).with(
|
139
|
+
instance_of(Nokogiri::HTML::DocumentFragment),
|
140
|
+
document,
|
141
|
+
).ordered
|
142
|
+
|
143
|
+
expect(Inliner).to receive(:new).ordered.and_return double.as_null_object
|
144
|
+
|
145
|
+
expect(after).to receive(:call).with(
|
146
|
+
instance_of(Nokogiri::HTML::DocumentFragment),
|
147
|
+
document,
|
148
|
+
).ordered
|
149
|
+
|
150
|
+
document.transform_partial
|
151
|
+
end
|
152
|
+
|
153
|
+
context "in HTML mode" do
|
154
|
+
it "does not escape curly braces" do
|
155
|
+
document = Document.new "<a href='https://google.com/{{hello}}'>Hello</a>"
|
156
|
+
document.mode = :xhtml
|
157
|
+
|
158
|
+
expect(document.transform_partial).to include("{{hello}}")
|
159
|
+
end
|
160
|
+
end
|
101
161
|
end
|
102
162
|
end
|
103
163
|
|
@@ -155,5 +215,27 @@ module Roadie
|
|
155
215
|
%w[text-size 2em]
|
156
216
|
]).at_selector("p")
|
157
217
|
end
|
218
|
+
|
219
|
+
it "removes data-roadie-ignore markers" do
|
220
|
+
document = Document.new <<-HTML
|
221
|
+
<html>
|
222
|
+
<head>
|
223
|
+
<link rel="stylesheet" href="/cool.css" data-roadie-ignore id="first">
|
224
|
+
</head>
|
225
|
+
<body>
|
226
|
+
<style data-roadie-ignore id="second">a { color: red; }</style>
|
227
|
+
<a href="#" data-roadie-ignore>
|
228
|
+
Hello world!
|
229
|
+
<span data-roadie-ignore></span>
|
230
|
+
</a>
|
231
|
+
</body>
|
232
|
+
</html>
|
233
|
+
HTML
|
234
|
+
|
235
|
+
result = Nokogiri::HTML.parse document.transform
|
236
|
+
|
237
|
+
expect(result).to have_selector("body > a > span")
|
238
|
+
expect(result).not_to have_selector("[data-roadie-ignore]")
|
239
|
+
end
|
158
240
|
end
|
159
241
|
end
|
@@ -219,9 +219,39 @@ module Roadie
|
|
219
219
|
<body><p></p></body>
|
220
220
|
</html>
|
221
221
|
"
|
222
|
-
Inliner.new([stylesheet], dom).inline(false)
|
222
|
+
Inliner.new([stylesheet], dom).inline(keep_uninlinable_css: false)
|
223
223
|
expect(dom).to_not have_selector("head > style")
|
224
224
|
end
|
225
|
+
|
226
|
+
it "puts the <style> element at the root when told so" do
|
227
|
+
stylesheet = use_css 'a:hover { color: red; }'
|
228
|
+
dom = Nokogiri::HTML.fragment("
|
229
|
+
<a></a>
|
230
|
+
")
|
231
|
+
|
232
|
+
Inliner.new([stylesheet], dom).inline(
|
233
|
+
keep_uninlinable_css: true,
|
234
|
+
keep_uninlinable_in: :root,
|
235
|
+
)
|
236
|
+
|
237
|
+
expect(dom).to have_xpath("./a")
|
238
|
+
expect(dom).to have_xpath("./style")
|
239
|
+
end
|
240
|
+
|
241
|
+
it "raises error when told to save styles in an unknown place" do
|
242
|
+
stylesheet = use_css 'a:hover { color: red; }'
|
243
|
+
dom = Nokogiri::HTML.fragment("
|
244
|
+
<a></a>
|
245
|
+
")
|
246
|
+
|
247
|
+
inliner = Inliner.new([stylesheet], dom)
|
248
|
+
expect {
|
249
|
+
inliner.inline(
|
250
|
+
keep_uninlinable_css: true,
|
251
|
+
keep_uninlinable_in: :unknown_place,
|
252
|
+
)
|
253
|
+
}.to raise_error(ArgumentError, /:unknown_place/)
|
254
|
+
end
|
225
255
|
end
|
226
256
|
end
|
227
257
|
end
|
@@ -43,6 +43,41 @@ module Roadie
|
|
43
43
|
}.to_not raise_error
|
44
44
|
end
|
45
45
|
|
46
|
+
it "applies encoding from the response" do
|
47
|
+
# Net::HTTP always returns the body string as a byte-encoded string
|
48
|
+
# (US-ASCII). The headers will indicate what charset the client should
|
49
|
+
# use when trying to make sense of these bytes.
|
50
|
+
stub_request(:get, url).and_return(
|
51
|
+
body: %(p::before { content: "l\xF6ve" }).force_encoding("US-ASCII"),
|
52
|
+
headers: {"Content-Type" => "text/css;charset=ISO-8859-1"},
|
53
|
+
)
|
54
|
+
|
55
|
+
# Seems like CssParser strips out the non-ascii character for some
|
56
|
+
# reason.
|
57
|
+
# stylesheet = NetHttpProvider.new.find_stylesheet!(url)
|
58
|
+
# expect(stylesheet.to_s).to eq('p::before{content:"löve"}')
|
59
|
+
|
60
|
+
allow(Stylesheet).to receive(:new).and_return(instance_double(Stylesheet))
|
61
|
+
NetHttpProvider.new.find_stylesheet!(url)
|
62
|
+
expect(Stylesheet).to have_received(:new).with(url, 'p::before { content: "löve" }')
|
63
|
+
end
|
64
|
+
|
65
|
+
it "assumes UTF-8 encoding if server headers do not specify a charset" do
|
66
|
+
stub_request(:get, url).and_return(
|
67
|
+
body: %(p::before { content: "Åh nej" }).force_encoding("US-ASCII"),
|
68
|
+
headers: {"Content-Type" => "text/css"},
|
69
|
+
)
|
70
|
+
|
71
|
+
# Seems like CssParser strips out the non-ascii characters for some
|
72
|
+
# reason.
|
73
|
+
# stylesheet = NetHttpProvider.new.find_stylesheet!(url)
|
74
|
+
# expect(stylesheet.to_s).to eq('p::before{content:"Åh nej"}')
|
75
|
+
|
76
|
+
allow(Stylesheet).to receive(:new).and_return(instance_double(Stylesheet))
|
77
|
+
NetHttpProvider.new.find_stylesheet!(url)
|
78
|
+
expect(Stylesheet).to have_received(:new).with(url, 'p::before { content: "Åh nej" }')
|
79
|
+
end
|
80
|
+
|
46
81
|
describe "error handling" do
|
47
82
|
it "handles timeouts" do
|
48
83
|
stub_request(:get, url).and_timeout
|
@@ -49,6 +49,22 @@ module Roadie
|
|
49
49
|
rewriter.transform_dom dom
|
50
50
|
}.to change { dom.at_css("div")["style"] }.to 'background-image: url("http://foo.com/image.jpg");'
|
51
51
|
end
|
52
|
+
|
53
|
+
it "skips elements with data-roadie-ignore attributes" do
|
54
|
+
allow(generator).to receive(:generate_url).and_return("http://example.com")
|
55
|
+
|
56
|
+
dom = dom_document <<-HTML
|
57
|
+
<body>
|
58
|
+
<a href="some/path.jpg" data-roadie-ignore>Image</a>
|
59
|
+
<img src="some/path.jpg" data-roadie-ignore>
|
60
|
+
<div style="background-image: url("some/path.jpg");" data-roadie-ignore>
|
61
|
+
</body>
|
62
|
+
HTML
|
63
|
+
|
64
|
+
rewriter.transform_dom dom
|
65
|
+
|
66
|
+
expect(generator).not_to have_received(:generate_url)
|
67
|
+
end
|
52
68
|
end
|
53
69
|
|
54
70
|
describe "transforming css" do
|
@@ -1,6 +1,6 @@
|
|
1
1
|
RSpec::Matchers.define :have_selector do |selector|
|
2
2
|
match { |document| !document.css(selector).empty? }
|
3
|
-
failure_message { "expected document to #{
|
4
|
-
failure_message_when_negated { "expected document to not #{
|
3
|
+
failure_message { "expected document to have selector #{selector.inspect}"}
|
4
|
+
failure_message_when_negated { "expected document to not have selector #{selector.inspect}"}
|
5
5
|
end
|
6
6
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: roadie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Magnus Bergmark
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -162,6 +162,7 @@ files:
|
|
162
162
|
- spec/support/have_node_matcher.rb
|
163
163
|
- spec/support/have_selector_matcher.rb
|
164
164
|
- spec/support/have_styling_matcher.rb
|
165
|
+
- spec/support/have_xpath_matcher.rb
|
165
166
|
- spec/support/test_provider.rb
|
166
167
|
homepage: http://github.com/Mange/roadie
|
167
168
|
licenses:
|
@@ -183,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
183
184
|
version: '0'
|
184
185
|
requirements: []
|
185
186
|
rubyforge_project:
|
186
|
-
rubygems_version: 2.6.
|
187
|
+
rubygems_version: 2.6.14
|
187
188
|
signing_key:
|
188
189
|
specification_version: 4
|
189
190
|
summary: Making HTML emails comfortable for the Ruby rockstars
|
@@ -221,4 +222,5 @@ test_files:
|
|
221
222
|
- spec/support/have_node_matcher.rb
|
222
223
|
- spec/support/have_selector_matcher.rb
|
223
224
|
- spec/support/have_styling_matcher.rb
|
225
|
+
- spec/support/have_xpath_matcher.rb
|
224
226
|
- spec/support/test_provider.rb
|