roadie 3.2.2 → 3.3.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 +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
|