roadie 3.4.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/main.yml +43 -0
  3. data/.rubocop.yml +5 -0
  4. data/.solargraph.yml +16 -0
  5. data/Changelog.md +37 -3
  6. data/Gemfile +7 -2
  7. data/README.md +12 -14
  8. data/Rakefile +4 -3
  9. data/lib/roadie/asset_provider.rb +5 -1
  10. data/lib/roadie/asset_scanner.rb +8 -6
  11. data/lib/roadie/cached_provider.rb +3 -0
  12. data/lib/roadie/deduplicator.rb +3 -0
  13. data/lib/roadie/document.rb +10 -11
  14. data/lib/roadie/errors.rb +22 -16
  15. data/lib/roadie/filesystem_provider.rb +15 -3
  16. data/lib/roadie/inliner.rb +51 -19
  17. data/lib/roadie/markup_improver.rb +27 -27
  18. data/lib/roadie/net_http_provider.rb +27 -12
  19. data/lib/roadie/null_provider.rb +20 -5
  20. data/lib/roadie/null_url_rewriter.rb +11 -3
  21. data/lib/roadie/path_rewriter_provider.rb +6 -1
  22. data/lib/roadie/provider_list.rb +17 -11
  23. data/lib/roadie/rspec/asset_provider.rb +6 -1
  24. data/lib/roadie/rspec/cache_store.rb +2 -0
  25. data/lib/roadie/rspec.rb +4 -2
  26. data/lib/roadie/selector.rb +17 -5
  27. data/lib/roadie/style_attribute_builder.rb +4 -1
  28. data/lib/roadie/style_block.rb +5 -3
  29. data/lib/roadie/style_property.rb +5 -2
  30. data/lib/roadie/stylesheet.rb +4 -13
  31. data/lib/roadie/url_generator.rb +26 -8
  32. data/lib/roadie/url_rewriter.rb +12 -9
  33. data/lib/roadie/utils.rb +3 -1
  34. data/lib/roadie/version.rb +3 -1
  35. data/lib/roadie.rb +25 -23
  36. data/roadie.gemspec +23 -23
  37. data/spec/hash_as_cache_store_spec.rb +3 -1
  38. data/spec/integration_spec.rb +43 -44
  39. data/spec/lib/roadie/asset_scanner_spec.rb +11 -5
  40. data/spec/lib/roadie/cached_provider_spec.rb +6 -4
  41. data/spec/lib/roadie/css_not_found_spec.rb +10 -5
  42. data/spec/lib/roadie/deduplicator_spec.rb +5 -3
  43. data/spec/lib/roadie/document_spec.rb +47 -28
  44. data/spec/lib/roadie/filesystem_provider_spec.rb +10 -11
  45. data/spec/lib/roadie/inliner_spec.rb +42 -45
  46. data/spec/lib/roadie/markup_improver_spec.rb +20 -26
  47. data/spec/lib/roadie/net_http_provider_spec.rb +16 -14
  48. data/spec/lib/roadie/null_provider_spec.rb +4 -3
  49. data/spec/lib/roadie/null_url_rewriter_spec.rb +4 -3
  50. data/spec/lib/roadie/path_rewriter_provider_spec.rb +6 -4
  51. data/spec/lib/roadie/provider_list_spec.rb +27 -22
  52. data/spec/lib/roadie/selector_spec.rb +6 -5
  53. data/spec/lib/roadie/style_attribute_builder_spec.rb +7 -5
  54. data/spec/lib/roadie/style_block_spec.rb +3 -2
  55. data/spec/lib/roadie/style_property_spec.rb +10 -8
  56. data/spec/lib/roadie/stylesheet_spec.rb +4 -21
  57. data/spec/lib/roadie/test_provider_spec.rb +6 -4
  58. data/spec/lib/roadie/url_generator_spec.rb +3 -2
  59. data/spec/lib/roadie/url_rewriter_spec.rb +10 -7
  60. data/spec/lib/roadie/utils_spec.rb +2 -0
  61. data/spec/shared_examples/asset_provider.rb +2 -0
  62. data/spec/shared_examples/url_rewriter.rb +5 -3
  63. data/spec/spec_helper.rb +10 -8
  64. data/spec/support/have_attribute_matcher.rb +3 -2
  65. data/spec/support/have_node_matcher.rb +5 -3
  66. data/spec/support/have_selector_matcher.rb +4 -3
  67. data/spec/support/have_styling_matcher.rb +12 -11
  68. data/spec/support/have_xpath_matcher.rb +4 -3
  69. data/spec/support/test_provider.rb +2 -0
  70. metadata +26 -11
  71. data/.travis.yml +0 -23
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Roadie
2
- VERSION = '3.4.0'
4
+ VERSION = "5.0.0"
3
5
  end
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 'roadie/version'
5
- require 'roadie/errors'
6
+ require "roadie/version"
7
+ require "roadie/errors"
6
8
 
7
- require 'roadie/utils'
8
- require 'roadie/deduplicator'
9
+ require "roadie/utils"
10
+ require "roadie/deduplicator"
9
11
 
10
- require 'roadie/stylesheet'
11
- require 'roadie/selector'
12
- require 'roadie/style_property'
13
- require 'roadie/style_attribute_builder'
14
- require 'roadie/style_block'
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 'roadie/asset_provider'
17
- require 'roadie/provider_list'
18
- require 'roadie/filesystem_provider'
19
- require 'roadie/null_provider'
20
- require 'roadie/net_http_provider'
21
- require 'roadie/cached_provider'
22
- require 'roadie/path_rewriter_provider'
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 'roadie/asset_scanner'
25
- require 'roadie/markup_improver'
26
- require 'roadie/url_generator'
27
- require 'roadie/url_rewriter'
28
- require 'roadie/null_url_rewriter'
29
- require 'roadie/inliner'
30
- require 'roadie/document'
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
- # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
3
3
 
4
4
  $:.push File.expand_path("../lib", __FILE__)
5
- require 'roadie/version'
5
+ require "roadie/version"
6
6
 
7
7
  Gem::Specification.new do |s|
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 = %q{Making HTML emails comfortable for the Ruby rockstars}
15
- s.description = %q{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 = ">= 1.9"
19
-
20
- s.add_dependency 'nokogiri', '~> 1.5'
21
- s.add_dependency 'css_parser', '~> 1.4'
22
-
23
- s.add_development_dependency 'rspec', '~> 3.0'
24
- s.add_development_dependency 'rspec-collection_matchers', '~> 1.0'
25
- s.add_development_dependency 'webmock', '~> 3.0'
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 = `git ls-files`.split("\n")
31
- s.test_files = `git ls-files -- spec/*`.split("\n")
31
+ s.files = `git ls-files`.split("\n")
32
+ s.test_files = `git ls-files -- spec/*`.split("\n")
32
33
  end
33
-
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
  require "roadie/rspec"
3
5
 
4
6
  describe "Using Hash as a cache store" do
5
- subject(:hash) { Hash.new }
7
+ subject(:hash) { {} }
6
8
  it_behaves_like "roadie cache store"
7
9
  end
@@ -1,4 +1,6 @@
1
- require 'spec_helper'
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
- unless defined?(JRuby)
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('text-align' => 'center').at_selector('h1')
49
- expect(result).to have_styling('color' => 'red').at_selector('p > em')
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('font-size' => '200%').at_selector('p > em')
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 { document.transform }.to raise_error(Roadie::CssNotFound, /does_not_exist\.css/)
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('head > link')
153
- expect(result).to have_styling([]).at_selector('p > em')
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('font-size' => '200%').at_selector('p > em')
177
- expect(result).to_not have_selector('head > link')
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
- ['color', 'red']
199
- ]).at_selector('p')
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" => 'url(https://myapp.com/rails/app/assets/link-abcdef1234567890.png)'
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('color' => 'green').at_selector('.colorful')
322
+ expect(result).to have_styling("color" => "green").at_selector(".colorful")
326
323
  end
327
324
 
328
- it 'puts non-inlineable media queries in the head' do
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('html > head > style').text
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(/[\s]+/, ' ').strip
360
- actual_result = styles.gsub(/[\s]+/, ' ').strip
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 'groups non-inlineable media queries in the head by default' do
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('html > head > style').text
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(/[\s]+/, ' ').strip
399
- actual_result = styles.gsub(/[\s]+/, ' ').strip
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 'if merge_media_queries is set to false' do
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('html > head > style').text
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(/[\s]+/, ' ').strip
443
- actual_result = styles.gsub(/[\s]+/, ' ').strip
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('text-align' => 'center').at_selector('h1')
476
- expect(result).to have_styling('color' => 'red').at_selector('p > em')
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('font-size' => '200%').at_selector('p > em')
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 { document.transform_partial }.to raise_error(Roadie::CssNotFound, /does_not_exist\.css/)
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('./link')
549
- expect(result).to have_styling([]).at_selector('p > em')
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('font-size' => '200%').at_selector('p > em')
565
- expect(result).to_not have_xpath('./link')
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
- ['color', 'red']
583
- ]).at_selector('p')
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" => 'url(https://myapp.com/rails/app/assets/link-abcdef1234567890.png)'
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
- # encoding: UTF-8
2
- require 'spec_helper'
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); Nokogiri::HTML.fragment html; end
11
- def dom_document(html); Nokogiri::HTML.parse html; end
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 'ignores HTML comments and CDATA sections' do
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
- require 'spec_helper'
2
- require 'roadie/rspec'
3
- require 'shared_examples/asset_provider'
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) { Hash.new }
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
- require 'spec_helper'
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('style.css')
7
- expect(error.css_name).to eq('style.css')
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
- expect(CssNotFound.new('file.css', "directory is missing").message).to eq(
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
- expect(CssNotFound.new('style.css', nil, provider).message).to eq(
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
- # encoding: UTF-8
2
- require 'spec_helper'
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('html > head > title')
182
- expect(result.at_css('title').text).to eq("Greetings")
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('html > body > p')
185
- paragraph = result.at_css('p')
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; }"