roadie 3.4.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/main.yml +43 -0
- data/.rubocop.yml +5 -0
- data/.solargraph.yml +16 -0
- data/Changelog.md +37 -3
- data/Gemfile +7 -2
- data/README.md +12 -14
- data/Rakefile +4 -3
- data/lib/roadie/asset_provider.rb +5 -1
- data/lib/roadie/asset_scanner.rb +8 -6
- data/lib/roadie/cached_provider.rb +3 -0
- data/lib/roadie/deduplicator.rb +3 -0
- data/lib/roadie/document.rb +10 -11
- data/lib/roadie/errors.rb +22 -16
- data/lib/roadie/filesystem_provider.rb +15 -3
- data/lib/roadie/inliner.rb +51 -19
- data/lib/roadie/markup_improver.rb +27 -27
- data/lib/roadie/net_http_provider.rb +27 -12
- data/lib/roadie/null_provider.rb +20 -5
- data/lib/roadie/null_url_rewriter.rb +11 -3
- data/lib/roadie/path_rewriter_provider.rb +6 -1
- data/lib/roadie/provider_list.rb +17 -11
- data/lib/roadie/rspec/asset_provider.rb +6 -1
- data/lib/roadie/rspec/cache_store.rb +2 -0
- data/lib/roadie/rspec.rb +4 -2
- data/lib/roadie/selector.rb +17 -5
- data/lib/roadie/style_attribute_builder.rb +4 -1
- data/lib/roadie/style_block.rb +5 -3
- data/lib/roadie/style_property.rb +5 -2
- data/lib/roadie/stylesheet.rb +4 -13
- data/lib/roadie/url_generator.rb +26 -8
- data/lib/roadie/url_rewriter.rb +12 -9
- data/lib/roadie/utils.rb +3 -1
- data/lib/roadie/version.rb +3 -1
- data/lib/roadie.rb +25 -23
- data/roadie.gemspec +23 -23
- data/spec/hash_as_cache_store_spec.rb +3 -1
- data/spec/integration_spec.rb +43 -44
- data/spec/lib/roadie/asset_scanner_spec.rb +11 -5
- data/spec/lib/roadie/cached_provider_spec.rb +6 -4
- data/spec/lib/roadie/css_not_found_spec.rb +10 -5
- data/spec/lib/roadie/deduplicator_spec.rb +5 -3
- data/spec/lib/roadie/document_spec.rb +47 -28
- data/spec/lib/roadie/filesystem_provider_spec.rb +10 -11
- data/spec/lib/roadie/inliner_spec.rb +42 -45
- data/spec/lib/roadie/markup_improver_spec.rb +20 -26
- data/spec/lib/roadie/net_http_provider_spec.rb +16 -14
- data/spec/lib/roadie/null_provider_spec.rb +4 -3
- data/spec/lib/roadie/null_url_rewriter_spec.rb +4 -3
- data/spec/lib/roadie/path_rewriter_provider_spec.rb +6 -4
- data/spec/lib/roadie/provider_list_spec.rb +27 -22
- data/spec/lib/roadie/selector_spec.rb +6 -5
- data/spec/lib/roadie/style_attribute_builder_spec.rb +7 -5
- data/spec/lib/roadie/style_block_spec.rb +3 -2
- data/spec/lib/roadie/style_property_spec.rb +10 -8
- data/spec/lib/roadie/stylesheet_spec.rb +4 -21
- data/spec/lib/roadie/test_provider_spec.rb +6 -4
- data/spec/lib/roadie/url_generator_spec.rb +3 -2
- data/spec/lib/roadie/url_rewriter_spec.rb +10 -7
- data/spec/lib/roadie/utils_spec.rb +2 -0
- data/spec/shared_examples/asset_provider.rb +2 -0
- data/spec/shared_examples/url_rewriter.rb +5 -3
- data/spec/spec_helper.rb +10 -8
- data/spec/support/have_attribute_matcher.rb +3 -2
- data/spec/support/have_node_matcher.rb +5 -3
- data/spec/support/have_selector_matcher.rb +4 -3
- data/spec/support/have_styling_matcher.rb +12 -11
- data/spec/support/have_xpath_matcher.rb +4 -3
- data/spec/support/test_provider.rb +2 -0
- metadata +26 -11
- data/.travis.yml +0 -23
data/lib/roadie/version.rb
CHANGED
data/lib/roadie.rb
CHANGED
@@ -1,30 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Roadie
|
2
4
|
end
|
3
5
|
|
4
|
-
require
|
5
|
-
require
|
6
|
+
require "roadie/version"
|
7
|
+
require "roadie/errors"
|
6
8
|
|
7
|
-
require
|
8
|
-
require
|
9
|
+
require "roadie/utils"
|
10
|
+
require "roadie/deduplicator"
|
9
11
|
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
12
|
+
require "roadie/stylesheet"
|
13
|
+
require "roadie/selector"
|
14
|
+
require "roadie/style_property"
|
15
|
+
require "roadie/style_attribute_builder"
|
16
|
+
require "roadie/style_block"
|
15
17
|
|
16
|
-
require
|
17
|
-
require
|
18
|
-
require
|
19
|
-
require
|
20
|
-
require
|
21
|
-
require
|
22
|
-
require
|
18
|
+
require "roadie/asset_provider"
|
19
|
+
require "roadie/provider_list"
|
20
|
+
require "roadie/filesystem_provider"
|
21
|
+
require "roadie/null_provider"
|
22
|
+
require "roadie/net_http_provider"
|
23
|
+
require "roadie/cached_provider"
|
24
|
+
require "roadie/path_rewriter_provider"
|
23
25
|
|
24
|
-
require
|
25
|
-
require
|
26
|
-
require
|
27
|
-
require
|
28
|
-
require
|
29
|
-
require
|
30
|
-
require
|
26
|
+
require "roadie/asset_scanner"
|
27
|
+
require "roadie/markup_improver"
|
28
|
+
require "roadie/url_generator"
|
29
|
+
require "roadie/url_rewriter"
|
30
|
+
require "roadie/null_url_rewriter"
|
31
|
+
require "roadie/inliner"
|
32
|
+
require "roadie/document"
|
data/roadie.gemspec
CHANGED
@@ -1,33 +1,33 @@
|
|
1
1
|
# roadie.gemspec
|
2
|
-
#
|
2
|
+
# frozen_string_literal: true
|
3
3
|
|
4
4
|
$:.push File.expand_path("../lib", __FILE__)
|
5
|
-
require
|
5
|
+
require "roadie/version"
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
|
-
s.name
|
9
|
-
s.version
|
10
|
-
s.platform
|
11
|
-
s.authors
|
12
|
-
s.email
|
13
|
-
s.homepage
|
14
|
-
s.summary
|
15
|
-
s.description =
|
16
|
-
s.license
|
17
|
-
|
18
|
-
s.required_ruby_version = ">=
|
19
|
-
|
20
|
-
s.add_dependency
|
21
|
-
s.add_dependency
|
22
|
-
|
23
|
-
s.add_development_dependency
|
24
|
-
s.add_development_dependency
|
25
|
-
s.add_development_dependency
|
8
|
+
s.name = "roadie"
|
9
|
+
s.version = Roadie::VERSION
|
10
|
+
s.platform = Gem::Platform::RUBY
|
11
|
+
s.authors = ["Magnus Bergmark"]
|
12
|
+
s.email = ["magnus.bergmark@gmail.com"]
|
13
|
+
s.homepage = "http://github.com/Mange/roadie"
|
14
|
+
s.summary = "Making HTML emails comfortable for the Ruby rockstars"
|
15
|
+
s.description = "Roadie tries to make sending HTML emails a little less painful by inlining stylesheets and rewriting relative URLs for you."
|
16
|
+
s.license = "MIT"
|
17
|
+
|
18
|
+
s.required_ruby_version = ">= 2.6"
|
19
|
+
|
20
|
+
s.add_dependency "nokogiri", "~> 1.8"
|
21
|
+
s.add_dependency "css_parser", "~> 1.4"
|
22
|
+
|
23
|
+
s.add_development_dependency "rake"
|
24
|
+
s.add_development_dependency "rspec", "~> 3.0"
|
25
|
+
s.add_development_dependency "rspec-collection_matchers", "~> 1.0"
|
26
|
+
s.add_development_dependency "webmock", "~> 3.0"
|
26
27
|
|
27
28
|
s.extra_rdoc_files = %w[README.md Changelog.md]
|
28
29
|
s.require_paths = %w[lib]
|
29
30
|
|
30
|
-
s.files
|
31
|
-
s.test_files
|
31
|
+
s.files = `git ls-files`.split("\n")
|
32
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
32
33
|
end
|
33
|
-
|
data/spec/integration_spec.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
2
4
|
|
3
5
|
describe "Roadie functionality" do
|
4
6
|
describe "on full documents" do
|
@@ -11,14 +13,7 @@ describe "Roadie functionality" do
|
|
11
13
|
document = Roadie::Document.new(html)
|
12
14
|
result = document.transform
|
13
15
|
|
14
|
-
|
15
|
-
# JRuby has a bug that makes DTD manipulation impossible
|
16
|
-
# See Nokogiri bugs #984 and #985
|
17
|
-
# https://github.com/sparklemotion/nokogiri/issues/984
|
18
|
-
# https://github.com/sparklemotion/nokogiri/issues/985
|
19
|
-
expect(result).to include("<!DOCTYPE html>")
|
20
|
-
end
|
21
|
-
|
16
|
+
expect(result).to include("<!DOCTYPE html>")
|
22
17
|
expect(result).to include("<html>")
|
23
18
|
expect(result).to include("<head>")
|
24
19
|
expect(result).to include("<body>")
|
@@ -45,8 +40,8 @@ describe "Roadie functionality" do
|
|
45
40
|
CSS
|
46
41
|
|
47
42
|
result = parse_html document.transform
|
48
|
-
expect(result).to have_styling(
|
49
|
-
expect(result).to have_styling(
|
43
|
+
expect(result).to have_styling("text-align" => "center").at_selector("h1")
|
44
|
+
expect(result).to have_styling("color" => "red").at_selector("p > em")
|
50
45
|
end
|
51
46
|
|
52
47
|
it "stores styles that cannot be inlined in the <head>" do
|
@@ -110,7 +105,7 @@ describe "Roadie functionality" do
|
|
110
105
|
HTML
|
111
106
|
|
112
107
|
result = parse_html document.transform
|
113
|
-
expect(result).to have_styling(
|
108
|
+
expect(result).to have_styling("font-size" => "200%").at_selector("p > em")
|
114
109
|
end
|
115
110
|
|
116
111
|
it "crashes when stylesheets cannot be found, unless using NullProvider" do
|
@@ -125,7 +120,9 @@ describe "Roadie functionality" do
|
|
125
120
|
</html>
|
126
121
|
HTML
|
127
122
|
|
128
|
-
expect {
|
123
|
+
expect {
|
124
|
+
document.transform
|
125
|
+
}.to raise_error(Roadie::CssNotFound, /does_not_exist\.css/)
|
129
126
|
|
130
127
|
document.asset_providers << Roadie::NullProvider.new
|
131
128
|
expect { document.transform }.to_not raise_error
|
@@ -149,8 +146,8 @@ describe "Roadie functionality" do
|
|
149
146
|
document.external_asset_providers = []
|
150
147
|
|
151
148
|
result = parse_html document.transform
|
152
|
-
expect(result).to have_selector(
|
153
|
-
expect(result).to have_styling([]).at_selector(
|
149
|
+
expect(result).to have_selector("head > link")
|
150
|
+
expect(result).to have_styling([]).at_selector("p > em")
|
154
151
|
end
|
155
152
|
|
156
153
|
it "inlines external css if configured" do
|
@@ -173,8 +170,8 @@ describe "Roadie functionality" do
|
|
173
170
|
)
|
174
171
|
|
175
172
|
result = parse_html document.transform
|
176
|
-
expect(result).to have_styling(
|
177
|
-
expect(result).to_not have_selector(
|
173
|
+
expect(result).to have_styling("font-size" => "200%").at_selector("p > em")
|
174
|
+
expect(result).to_not have_selector("head > link")
|
178
175
|
end
|
179
176
|
|
180
177
|
it "does not inline the same properties several times" do
|
@@ -195,8 +192,8 @@ describe "Roadie functionality" do
|
|
195
192
|
|
196
193
|
result = parse_html document.transform
|
197
194
|
expect(result).to have_styling([
|
198
|
-
[
|
199
|
-
]).at_selector(
|
195
|
+
["color", "red"]
|
196
|
+
]).at_selector("p")
|
200
197
|
end
|
201
198
|
|
202
199
|
it "makes URLs absolute" do
|
@@ -230,7 +227,7 @@ describe "Roadie functionality" do
|
|
230
227
|
).at_selector("body")
|
231
228
|
|
232
229
|
expect(result).to have_styling(
|
233
|
-
"background" =>
|
230
|
+
"background" => "url(https://myapp.com/rails/app/assets/link-abcdef1234567890.png)"
|
234
231
|
).at_selector("a")
|
235
232
|
end
|
236
233
|
|
@@ -322,10 +319,10 @@ describe "Roadie functionality" do
|
|
322
319
|
)
|
323
320
|
|
324
321
|
result = parse_html document.transform
|
325
|
-
expect(result).to have_styling(
|
322
|
+
expect(result).to have_styling("color" => "green").at_selector(".colorful")
|
326
323
|
end
|
327
324
|
|
328
|
-
it
|
325
|
+
it "puts non-inlineable media queries in the head" do
|
329
326
|
document = Roadie::Document.new <<-HTML
|
330
327
|
<html>
|
331
328
|
<head>
|
@@ -351,18 +348,18 @@ describe "Roadie functionality" do
|
|
351
348
|
|
352
349
|
result = parse_html document.transform
|
353
350
|
|
354
|
-
styles = result.at_css(
|
351
|
+
styles = result.at_css("html > head > style").text
|
355
352
|
expected_result = <<-CSS
|
356
353
|
@media screen and (max-width 800px) { .colorful{color:blue} }
|
357
354
|
@media screen, print and (max-width 800px) { .colorful{color:blue} }
|
358
355
|
CSS
|
359
|
-
expected_result = expected_result.gsub(
|
360
|
-
actual_result = styles.gsub(
|
356
|
+
expected_result = expected_result.gsub(/\s+/, " ").strip
|
357
|
+
actual_result = styles.gsub(/\s+/, " ").strip
|
361
358
|
|
362
359
|
expect(actual_result).to eq(expected_result)
|
363
360
|
end
|
364
361
|
|
365
|
-
it
|
362
|
+
it "groups non-inlineable media queries in the head by default" do
|
366
363
|
document = Roadie::Document.new <<-HTML
|
367
364
|
<html>
|
368
365
|
<head>
|
@@ -388,20 +385,20 @@ describe "Roadie functionality" do
|
|
388
385
|
|
389
386
|
result = parse_html document.transform
|
390
387
|
|
391
|
-
styles = result.at_css(
|
388
|
+
styles = result.at_css("html > head > style").text
|
392
389
|
expected_result = <<-CSS
|
393
390
|
@media screen and (max-width 600px) {
|
394
391
|
.colorful{color:red;width:600px}
|
395
392
|
.colorful-2{color:red;width:600px}
|
396
393
|
}
|
397
394
|
CSS
|
398
|
-
expected_result = expected_result.gsub(
|
399
|
-
actual_result = styles.gsub(
|
395
|
+
expected_result = expected_result.gsub(/\s+/, " ").strip
|
396
|
+
actual_result = styles.gsub(/\s+/, " ").strip
|
400
397
|
|
401
398
|
expect(actual_result).to eq(expected_result)
|
402
399
|
end
|
403
400
|
|
404
|
-
describe
|
401
|
+
describe "if merge_media_queries is set to false" do
|
405
402
|
it "doesn't group non-inlineable media queries in the head" do
|
406
403
|
document = Roadie::Document.new <<-HTML
|
407
404
|
<html>
|
@@ -430,7 +427,7 @@ describe "Roadie functionality" do
|
|
430
427
|
|
431
428
|
result = parse_html document.transform
|
432
429
|
|
433
|
-
styles = result.at_css(
|
430
|
+
styles = result.at_css("html > head > style").text
|
434
431
|
expected_result = <<-CSS
|
435
432
|
@media screen and (max-width 600px) {
|
436
433
|
.colorful{color:red;width:600px}
|
@@ -439,8 +436,8 @@ describe "Roadie functionality" do
|
|
439
436
|
.colorful-2{color:red;width:600px}
|
440
437
|
}
|
441
438
|
CSS
|
442
|
-
expected_result = expected_result.gsub(
|
443
|
-
actual_result = styles.gsub(
|
439
|
+
expected_result = expected_result.gsub(/\s+/, " ").strip
|
440
|
+
actual_result = styles.gsub(/\s+/, " ").strip
|
444
441
|
|
445
442
|
expect(actual_result).to eq(expected_result)
|
446
443
|
end
|
@@ -472,8 +469,8 @@ describe "Roadie functionality" do
|
|
472
469
|
CSS
|
473
470
|
|
474
471
|
result = parse_html document.transform_partial
|
475
|
-
expect(result).to have_styling(
|
476
|
-
expect(result).to have_styling(
|
472
|
+
expect(result).to have_styling("text-align" => "center").at_selector("h1")
|
473
|
+
expect(result).to have_styling("color" => "red").at_selector("p > em")
|
477
474
|
end
|
478
475
|
|
479
476
|
it "stores styles that cannot be inlined in a new <style> element" do
|
@@ -521,7 +518,7 @@ describe "Roadie functionality" do
|
|
521
518
|
HTML
|
522
519
|
|
523
520
|
result = parse_html document.transform_partial
|
524
|
-
expect(result).to have_styling(
|
521
|
+
expect(result).to have_styling("font-size" => "200%").at_selector("p > em")
|
525
522
|
end
|
526
523
|
|
527
524
|
it "crashes when stylesheets cannot be found, unless using NullProvider" do
|
@@ -529,7 +526,9 @@ describe "Roadie functionality" do
|
|
529
526
|
<link rel="stylesheet" href="/spec/fixtures/does_not_exist.css">
|
530
527
|
HTML
|
531
528
|
|
532
|
-
expect {
|
529
|
+
expect {
|
530
|
+
document.transform_partial
|
531
|
+
}.to raise_error(Roadie::CssNotFound, /does_not_exist\.css/)
|
533
532
|
|
534
533
|
document.asset_providers << Roadie::NullProvider.new
|
535
534
|
expect { document.transform_partial }.to_not raise_error
|
@@ -545,8 +544,8 @@ describe "Roadie functionality" do
|
|
545
544
|
document.external_asset_providers = []
|
546
545
|
|
547
546
|
result = parse_html document.transform_partial
|
548
|
-
expect(result).to have_xpath(
|
549
|
-
expect(result).to have_styling([]).at_selector(
|
547
|
+
expect(result).to have_xpath("./link")
|
548
|
+
expect(result).to have_styling([]).at_selector("p > em")
|
550
549
|
end
|
551
550
|
|
552
551
|
it "inlines external css if configured" do
|
@@ -561,8 +560,8 @@ describe "Roadie functionality" do
|
|
561
560
|
)
|
562
561
|
|
563
562
|
result = parse_html document.transform_partial
|
564
|
-
expect(result).to have_styling(
|
565
|
-
expect(result).to_not have_xpath(
|
563
|
+
expect(result).to have_styling("font-size" => "200%").at_selector("p > em")
|
564
|
+
expect(result).to_not have_xpath("./link")
|
566
565
|
end
|
567
566
|
|
568
567
|
it "does not inline the same properties several times" do
|
@@ -579,8 +578,8 @@ describe "Roadie functionality" do
|
|
579
578
|
|
580
579
|
result = parse_html document.transform_partial
|
581
580
|
expect(result).to have_styling([
|
582
|
-
[
|
583
|
-
]).at_selector(
|
581
|
+
["color", "red"]
|
582
|
+
]).at_selector("p")
|
584
583
|
end
|
585
584
|
|
586
585
|
it "makes URLs absolute" do
|
@@ -613,7 +612,7 @@ describe "Roadie functionality" do
|
|
613
612
|
).at_selector("div")
|
614
613
|
|
615
614
|
expect(result).to have_styling(
|
616
|
-
"background" =>
|
615
|
+
"background" => "url(https://myapp.com/rails/app/assets/link-abcdef1234567890.png)"
|
617
616
|
).at_selector("a")
|
618
617
|
end
|
619
618
|
|
@@ -1,5 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
3
4
|
|
4
5
|
module Roadie
|
5
6
|
describe AssetScanner do
|
@@ -7,8 +8,13 @@ module Roadie
|
|
7
8
|
let(:external_provider) { ProviderList.empty }
|
8
9
|
let(:dom) { dom_document "<html></html>" }
|
9
10
|
|
10
|
-
def dom_fragment(html)
|
11
|
-
|
11
|
+
def dom_fragment(html)
|
12
|
+
Nokogiri::HTML.fragment html
|
13
|
+
end
|
14
|
+
|
15
|
+
def dom_document(html)
|
16
|
+
Nokogiri::HTML.parse html
|
17
|
+
end
|
12
18
|
|
13
19
|
it "is initialized with a DOM tree, a normal asset provider set, and an external asset provider set" do
|
14
20
|
scanner = AssetScanner.new dom, normal_provider, external_provider
|
@@ -110,7 +116,7 @@ module Roadie
|
|
110
116
|
expect(scanner.find_css).to eq([])
|
111
117
|
end
|
112
118
|
|
113
|
-
it
|
119
|
+
it "ignores HTML comments and CDATA sections" do
|
114
120
|
# TinyMCE posts invalid CSS. We support that just to be pragmatic.
|
115
121
|
dom = dom_fragment %(<style><![CDATA[
|
116
122
|
<!--
|
@@ -1,11 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
require "roadie/rspec"
|
5
|
+
require "shared_examples/asset_provider"
|
4
6
|
|
5
7
|
module Roadie
|
6
8
|
describe CachedProvider do
|
7
9
|
let(:upstream) { TestProvider.new("good.css" => "body { color: green; }") }
|
8
|
-
let(:cache) {
|
10
|
+
let(:cache) { {} }
|
9
11
|
subject(:provider) { CachedProvider.new(upstream, cache) }
|
10
12
|
|
11
13
|
it_behaves_like "roadie asset provider", valid_name: "good.css", invalid_name: "bad.css"
|
@@ -1,22 +1,27 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
2
4
|
|
3
5
|
module Roadie
|
4
6
|
describe CssNotFound do
|
5
7
|
it "is initialized with a name" do
|
6
|
-
error = CssNotFound.new(
|
7
|
-
expect(error.css_name).to eq(
|
8
|
+
error = CssNotFound.new(css_name: "style.css")
|
9
|
+
expect(error.css_name).to eq("style.css")
|
8
10
|
expect(error.message).to eq('Could not find stylesheet "style.css"')
|
9
11
|
end
|
10
12
|
|
11
13
|
it "can be initialized with an extra message" do
|
12
|
-
|
14
|
+
error = CssNotFound.new(css_name: "file.css", message: "directory is missing")
|
15
|
+
expect(error.message).to eq(
|
13
16
|
'Could not find stylesheet "file.css": directory is missing'
|
14
17
|
)
|
15
18
|
end
|
16
19
|
|
17
20
|
it "shows information about used provider when given" do
|
18
21
|
provider = double("Some cool provider")
|
19
|
-
|
22
|
+
error = CssNotFound.new(css_name: "style.css", provider: provider)
|
23
|
+
|
24
|
+
expect(error.message).to eq(
|
20
25
|
%(Could not find stylesheet "style.css"\nUsed provider:\n#{provider})
|
21
26
|
)
|
22
27
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "spec_helper"
|
2
4
|
|
3
5
|
module Roadie
|
@@ -7,13 +9,13 @@ module Roadie
|
|
7
9
|
["a", "1"],
|
8
10
|
["b", "2"],
|
9
11
|
["a", "3"],
|
10
|
-
["a", "1"]
|
12
|
+
["a", "1"]
|
11
13
|
]
|
12
14
|
|
13
15
|
expect(Deduplicator.apply(input)).to eq [
|
14
16
|
["b", "2"],
|
15
17
|
["a", "3"],
|
16
|
-
["a", "1"]
|
18
|
+
["a", "1"]
|
17
19
|
]
|
18
20
|
end
|
19
21
|
|
@@ -21,7 +23,7 @@ module Roadie
|
|
21
23
|
input = [
|
22
24
|
["a", "1"],
|
23
25
|
["a", "3"],
|
24
|
-
["a", "2"]
|
26
|
+
["a", "2"]
|
25
27
|
]
|
26
28
|
|
27
29
|
expect(Deduplicator.apply(input)).to eq input
|
@@ -1,5 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
3
4
|
|
4
5
|
module Roadie
|
5
6
|
describe Document do
|
@@ -69,6 +70,9 @@ module Roadie
|
|
69
70
|
|
70
71
|
document.mode = :html
|
71
72
|
expect(document.mode).to eq(:html)
|
73
|
+
|
74
|
+
document.mode = :xml
|
75
|
+
expect(document.mode).to eq(:xml)
|
72
76
|
end
|
73
77
|
|
74
78
|
it "does not allow unknown modes" do
|
@@ -90,8 +94,8 @@ module Roadie
|
|
90
94
|
describe "transforming" do
|
91
95
|
it "runs the before and after callbacks" do
|
92
96
|
document = Document.new "<body></body>"
|
93
|
-
before = ->{}
|
94
|
-
after = ->{}
|
97
|
+
before = -> {}
|
98
|
+
after = -> {}
|
95
99
|
document.before_transformation = before
|
96
100
|
document.after_transformation = after
|
97
101
|
|
@@ -102,21 +106,6 @@ module Roadie
|
|
102
106
|
document.transform
|
103
107
|
end
|
104
108
|
|
105
|
-
# TODO: Remove on next major version.
|
106
|
-
it "works on callables that don't expect more than one argument" do
|
107
|
-
document = Document.new "<body></body>"
|
108
|
-
document.before_transformation = ->(first) { }
|
109
|
-
document.after_transformation = ->(first = nil) { }
|
110
|
-
|
111
|
-
expect { document.transform }.to_not raise_error
|
112
|
-
|
113
|
-
# It still supplies the second argument, if possible.
|
114
|
-
document.after_transformation = ->(first, second = nil) {
|
115
|
-
raise "Oops" unless second
|
116
|
-
}
|
117
|
-
expect { document.transform }.to_not raise_error
|
118
|
-
end
|
119
|
-
|
120
109
|
context "in HTML mode" do
|
121
110
|
it "does not escape curly braces" do
|
122
111
|
document = Document.new "<body><a href='https://google.com/{{hello}}'>Hello</a></body>"
|
@@ -125,26 +114,41 @@ module Roadie
|
|
125
114
|
expect(document.transform).to include("{{hello}}")
|
126
115
|
end
|
127
116
|
end
|
117
|
+
|
118
|
+
context "in XML mode" do
|
119
|
+
it "doesn't replace empty tags with self-closed ones" do
|
120
|
+
document = Document.new "<img src='https://google.com/image.png'></img>"
|
121
|
+
document.mode = :xml
|
122
|
+
|
123
|
+
expect(document.transform_partial).to end_with("</img>")
|
124
|
+
end
|
125
|
+
|
126
|
+
it "does not escape curly braces" do
|
127
|
+
document = Document.new "<a href='https://google.com/{{hello}}'>Hello</a>"
|
128
|
+
document.mode = :xml
|
129
|
+
expect(document.transform_partial).to include("{{hello}}")
|
130
|
+
end
|
131
|
+
end
|
128
132
|
end
|
129
133
|
|
130
134
|
describe "partial transforming" do
|
131
135
|
it "runs the before and after callbacks" do
|
132
136
|
document = Document.new "<p></p>"
|
133
|
-
before = ->{}
|
134
|
-
after = ->{}
|
137
|
+
before = -> {}
|
138
|
+
after = -> {}
|
135
139
|
document.before_transformation = before
|
136
140
|
document.after_transformation = after
|
137
141
|
|
138
142
|
expect(before).to receive(:call).with(
|
139
143
|
instance_of(Nokogiri::HTML::DocumentFragment),
|
140
|
-
document
|
144
|
+
document
|
141
145
|
).ordered
|
142
146
|
|
143
147
|
expect(Inliner).to receive(:new).ordered.and_return double.as_null_object
|
144
148
|
|
145
149
|
expect(after).to receive(:call).with(
|
146
150
|
instance_of(Nokogiri::HTML::DocumentFragment),
|
147
|
-
document
|
151
|
+
document
|
148
152
|
).ordered
|
149
153
|
|
150
154
|
document.transform_partial
|
@@ -158,6 +162,21 @@ module Roadie
|
|
158
162
|
expect(document.transform_partial).to include("{{hello}}")
|
159
163
|
end
|
160
164
|
end
|
165
|
+
|
166
|
+
context "in XML mode" do
|
167
|
+
it "doesn't replace empty tags with self-closed ones" do
|
168
|
+
document = Document.new "<img src='https://google.com/image.png'></img>"
|
169
|
+
document.mode = :xml
|
170
|
+
|
171
|
+
expect(document.transform_partial).to end_with("</img>")
|
172
|
+
end
|
173
|
+
|
174
|
+
it "does not escape curly braces" do
|
175
|
+
document = Document.new "<a href='https://google.com/{{hello}}'>Hello</a>"
|
176
|
+
document.mode = :xml
|
177
|
+
expect(document.transform_partial).to include("{{hello}}")
|
178
|
+
end
|
179
|
+
end
|
161
180
|
end
|
162
181
|
end
|
163
182
|
|
@@ -178,11 +197,11 @@ module Roadie
|
|
178
197
|
|
179
198
|
result = Nokogiri::HTML.parse document.transform
|
180
199
|
|
181
|
-
expect(result).to have_selector(
|
182
|
-
expect(result.at_css(
|
200
|
+
expect(result).to have_selector("html > head > title")
|
201
|
+
expect(result.at_css("title").text).to eq("Greetings")
|
183
202
|
|
184
|
-
expect(result).to have_selector(
|
185
|
-
paragraph = result.at_css(
|
203
|
+
expect(result).to have_selector("html > body > p")
|
204
|
+
paragraph = result.at_css("p")
|
186
205
|
expect(paragraph.text).to eq("Hello, world!")
|
187
206
|
expect(paragraph.to_xml).to eq('<p style="color:green">Hello, world!</p>')
|
188
207
|
end
|
@@ -201,7 +220,7 @@ module Roadie
|
|
201
220
|
HTML
|
202
221
|
|
203
222
|
document.asset_providers = TestProvider.new({
|
204
|
-
"/sample.css" => "p { color: red; text-align: right; }"
|
223
|
+
"/sample.css" => "p { color: red; text-align: right; }"
|
205
224
|
})
|
206
225
|
|
207
226
|
document.add_css "p { color: green; text-size: 2em; }"
|