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,11 +1,13 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
2
4
 
3
5
  module Roadie
4
6
  describe StyleProperty do
5
7
  it "is initialized with a property, value, if it is marked as important, and the specificity" do
6
- StyleProperty.new('color', 'green', true, 45).tap do |declaration|
7
- expect(declaration.property).to eq('color')
8
- expect(declaration.value).to eq('green')
8
+ StyleProperty.new("color", "green", true, 45).tap do |declaration|
9
+ expect(declaration.property).to eq("color")
10
+ expect(declaration.value).to eq("green")
9
11
  expect(declaration).to be_important
10
12
  expect(declaration.specificity).to eq(45)
11
13
  end
@@ -13,18 +15,18 @@ module Roadie
13
15
 
14
16
  describe "string representation" do
15
17
  it "is the property and the value joined with a colon" do
16
- expect(StyleProperty.new('color', 'green', false, 1).to_s).to eq('color:green')
17
- expect(StyleProperty.new('font-size', '1.1em', false, 1).to_s).to eq('font-size:1.1em')
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")
18
20
  end
19
21
 
20
22
  it "contains the !important flag when set" do
21
- expect(StyleProperty.new('color', 'green', true, 1).to_s).to eq('color:green !important')
23
+ expect(StyleProperty.new("color", "green", true, 1).to_s).to eq("color:green !important")
22
24
  end
23
25
  end
24
26
 
25
27
  describe "comparing" do
26
28
  def declaration(specificity, important = false)
27
- StyleProperty.new('color', 'green', important, specificity)
29
+ StyleProperty.new("color", "green", important, specificity)
28
30
  end
29
31
 
30
32
  it "compares on specificity" do
@@ -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 Stylesheet do
@@ -17,28 +18,10 @@ module Roadie
17
18
  expect(stylesheet.blocks.map(&:to_s)).to eq([
18
19
  "body{color:green !important;font-size:200%}",
19
20
  "a{color:red}",
20
- "i{color:red}",
21
+ "i{color:red}"
21
22
  ])
22
23
  end
23
24
 
24
- if VERSION < "4.0"
25
- it "can iterate all inlinable blocks" do
26
- inlinable = double(inlinable?: true, selector: "good", properties: "props")
27
- bad = double(inlinable?: false, selector: "bad", properties: "props")
28
-
29
- stylesheet = Stylesheet.new("example.css", "")
30
- allow(stylesheet).to receive_messages blocks: [bad, inlinable, bad]
31
-
32
- expect(stylesheet.each_inlinable_block.to_a).to eq([
33
- ["good", "props"],
34
- ])
35
- end
36
- else
37
- it "should no longer have #each_inlinable_block" do
38
- fail "Remove #each_inlinable_block"
39
- end
40
- end
41
-
42
25
  it "has a string representation of the contents" do
43
26
  stylesheet = Stylesheet.new("example.css", "body { color: green;}a{ color: red; font-size: small }")
44
27
  expect(stylesheet.to_s).to eq("body{color:green}\na{color:red;font-size:small}")
@@ -1,5 +1,7 @@
1
- require 'spec_helper'
2
- require 'roadie/rspec'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "roadie/rspec"
3
5
 
4
6
  describe TestProvider do
5
7
  subject(:provider) { TestProvider.new }
@@ -11,7 +13,7 @@ describe TestProvider do
11
13
  it "finds styles from a predefined hash" do
12
14
  provider = TestProvider.new({
13
15
  "foo.css" => "a { color: red; }",
14
- "bar.css" => "body { color: green; }",
16
+ "bar.css" => "body { color: green; }"
15
17
  })
16
18
  expect(provider.find_stylesheet("foo.css").to_s).not_to include("body")
17
19
  expect(provider.find_stylesheet("bar.css").to_s).to include("body")
@@ -21,7 +23,7 @@ describe TestProvider do
21
23
  it "can have a default for missing entries" do
22
24
  provider = TestProvider.new({
23
25
  "foo.css" => "a { color: red; }",
24
- :default => "body { color: green; }",
26
+ :default => "body { color: green; }"
25
27
  })
26
28
  expect(provider.find_stylesheet("foo.css").to_s).not_to include("body")
27
29
  expect(provider.find_stylesheet("bar.css").to_s).to include("body")
@@ -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 UrlGenerator do
@@ -1,5 +1,7 @@
1
- require 'spec_helper'
2
- require 'shared_examples/url_rewriter'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "shared_examples/url_rewriter"
3
5
 
4
6
  module Roadie
5
7
  describe UrlRewriter do
@@ -9,7 +11,9 @@ module Roadie
9
11
  it_behaves_like "url rewriter"
10
12
 
11
13
  describe "transforming DOM trees" do
12
- def dom_document(html); Nokogiri::HTML.parse html; end
14
+ def dom_document(html)
15
+ Nokogiri::HTML.parse html
16
+ end
13
17
 
14
18
  it "rewrites all a[href]" do
15
19
  expect(generator).to receive(:generate_url).with("some/path").and_return "http://foo.com/"
@@ -71,9 +75,8 @@ module Roadie
71
75
  it "rewrites all url() directives" do
72
76
  expect(generator).to receive(:generate_url).with("some/path.jpg").and_return "http://foo.com/image.jpg"
73
77
  css = "body { background: top url(some/path.jpg) #eee; }"
74
- expect {
75
- rewriter.transform_css css
76
- }.to change { css }.to "body { background: top url(http://foo.com/image.jpg) #eee; }"
78
+ transformed_css = rewriter.transform_css css
79
+ expect(transformed_css).to eq "body { background: top url(http://foo.com/image.jpg) #eee; }"
77
80
  end
78
81
 
79
82
  it "correctly identifies URLs with single quotes" do
@@ -88,7 +91,7 @@ module Roadie
88
91
 
89
92
  it "correctly identifies URLs with parenthesis inside them" do
90
93
  expect(generator).to receive(:generate_url).with("images/map_(large_(extra)).png").and_return "x"
91
- rewriter.transform_css 'url(images/map_(large_(extra)).png)'
94
+ rewriter.transform_css "url(images/map_(large_(extra)).png)"
92
95
  end
93
96
  end
94
97
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  module Roadie
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  shared_examples_for "asset provider role" do
2
4
  it "responds to #find_stylesheet" do
3
5
  expect(subject).to respond_to(:find_stylesheet)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  shared_examples_for "url rewriter" do
2
4
  it "is constructed with a generator" do
3
5
  generator = double "URL generator"
@@ -6,7 +8,7 @@ shared_examples_for "url rewriter" do
6
8
  }.to_not raise_error
7
9
  end
8
10
 
9
- it "has a #transform_dom(dom) method that returns nil" do
11
+ it "has a #transform_dom(dom) method that returns the modified string" do
10
12
  expect(subject).to respond_to(:transform_dom)
11
13
  expect(subject.method(:transform_dom).arity).to eq(1)
12
14
 
@@ -14,10 +16,10 @@ shared_examples_for "url rewriter" do
14
16
  expect(subject.transform_dom(dom)).to be_nil
15
17
  end
16
18
 
17
- it "has a #transform_css(css) method that returns nil" do
19
+ it "has a #transform_css(css) method that returns the modified string" do
18
20
  expect(subject).to respond_to(:transform_css)
19
21
  expect(subject.method(:transform_css).arity).to eq(1)
20
22
 
21
- expect(subject.transform_css("")).to be_nil
23
+ expect(subject.transform_css("")).to eq("")
22
24
  end
23
25
  end
data/spec/spec_helper.rb CHANGED
@@ -1,19 +1,21 @@
1
- require 'rspec/collection_matchers'
2
- require 'webmock/rspec'
1
+ # frozen_string_literal: true
3
2
 
4
- if ENV['CI']
5
- require 'simplecov'
3
+ require "rspec/collection_matchers"
4
+ require "webmock/rspec"
5
+
6
+ if ENV["CI"]
7
+ require "simplecov"
6
8
  SimpleCov.start
7
9
 
8
- require 'codecov'
10
+ require "codecov"
9
11
  SimpleCov.formatter = SimpleCov::Formatter::Codecov
10
12
  end
11
13
 
12
- $: << File.dirname(__FILE__) + '/../lib'
13
- require 'roadie'
14
+ $: << File.dirname(__FILE__) + "/../lib"
15
+ require "roadie"
14
16
 
15
17
  RSpec.configure do |config|
16
18
  config.run_all_when_everything_filtered = true
17
19
  end
18
20
 
19
- Dir['./spec/support/**/*.rb'].each { |file| require file }
21
+ Dir["./spec/support/**/*.rb"].sort.each { |file| require file }
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  RSpec::Matchers.define :have_attribute do |attribute|
2
- @selector = 'body > *:first'
4
+ @selector = "body > *:first"
3
5
 
4
6
  chain :at_selector do |selector|
5
7
  @selector = selector
@@ -25,4 +27,3 @@ RSpec::Matchers.define :have_attribute do |attribute|
25
27
  node && node[attribute_name]
26
28
  end
27
29
  end
28
-
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  RSpec::Matchers.define :have_node do |selector|
2
4
  chain(:with_attributes) { |attributes| @attributes = attributes }
3
5
  match do |document|
@@ -9,11 +11,11 @@ RSpec::Matchers.define :have_node do |selector|
9
11
  end
10
12
  end
11
13
 
12
- failure_message { "expected document to #{name_to_sentence}#{expected_to_sentence}"}
13
- failure_message_when_negated { "expected document to not #{name_to_sentence}#{expected_to_sentence}"}
14
+ failure_message { "expected document to #{name_to_sentence}#{expected_to_sentence}" }
15
+ failure_message_when_negated { "expected document to not #{name_to_sentence}#{expected_to_sentence}" }
14
16
 
15
17
  def match_attributes(node_attributes)
16
- attributes = Hash[node_attributes.map { |name, attribute| [name, attribute.value] }]
18
+ attributes = node_attributes.map { |name, attribute| [name, attribute.value] }.to_h
17
19
  @attributes == attributes
18
20
  end
19
21
  end
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  RSpec::Matchers.define :have_selector do |selector|
2
4
  match { |document| !document.css(selector).empty? }
3
- failure_message { "expected document to have selector #{selector.inspect}"}
4
- failure_message_when_negated { "expected document to not have selector #{selector.inspect}"}
5
+ failure_message { "expected document to have selector #{selector.inspect}" }
6
+ failure_message_when_negated { "expected document to not have selector #{selector.inspect}" }
5
7
  end
6
-
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  RSpec::Matchers.define :have_styling do |rules|
2
4
  normalized_rules = StylingExpectation.new(rules)
3
5
 
4
6
  chain(:at_selector) { |selector| @selector = selector }
5
7
  match { |document|
6
- @selector ||= 'body > *:first'
8
+ @selector ||= "body > *:first"
7
9
  normalized_rules == styles_at_selector(document)
8
10
  }
9
11
 
@@ -21,7 +23,7 @@ RSpec::Matchers.define :have_styling do |rules|
21
23
 
22
24
  def styles_at_selector(document)
23
25
  expect(document).to have_selector(@selector)
24
- StylingExpectation.new document.at_css(@selector)['style']
26
+ StylingExpectation.new document.at_css(@selector)["style"]
25
27
  end
26
28
  end
27
29
 
@@ -40,23 +42,22 @@ class StylingExpectation
40
42
  rules == other.rules
41
43
  end
42
44
 
43
- def to_s() rules.to_s end
45
+ def to_s
46
+ rules.to_s
47
+ end
44
48
 
45
49
  protected
50
+
46
51
  attr_reader :rules
47
52
 
48
53
  private
54
+
49
55
  def parse_rules(css)
50
- css.split(';').map { |property| parse_property(property) }
56
+ css.split(";").map { |property| parse_property(property) }
51
57
  end
52
58
 
53
59
  def parse_property(property)
54
- rule, value = property.split(':', 2).map(&:strip)
55
- [rule, normalize_quotes(value)]
56
- end
57
-
58
- # JRuby's Nokogiri encodes quotes
59
- def normalize_quotes(string)
60
- string.gsub '%22', '"'
60
+ rule, value = property.split(":", 2).map(&:strip)
61
+ [rule, value]
61
62
  end
62
63
  end
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  RSpec::Matchers.define :have_xpath do |xpath|
2
4
  match { |document| !document.xpath(xpath).empty? }
3
- failure_message { "expected document to have xpath #{xpath.inspect}"}
4
- failure_message_when_negated { "expected document to not have xpath #{xpath.inspect}"}
5
+ failure_message { "expected document to have xpath #{xpath.inspect}" }
6
+ failure_message_when_negated { "expected document to not have xpath #{xpath.inspect}" }
5
7
  end
6
-
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class TestProvider
2
4
  include Roadie::AssetProvider
3
5
 
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.0
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Magnus Bergmark
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-30 00:00:00.000000000 Z
11
+ date: 2022-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.5'
19
+ version: '1.8'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.5'
26
+ version: '1.8'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: css_parser
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rspec
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -91,8 +105,10 @@ extra_rdoc_files:
91
105
  - Changelog.md
92
106
  files:
93
107
  - ".autotest"
108
+ - ".github/workflows/main.yml"
94
109
  - ".gitignore"
95
- - ".travis.yml"
110
+ - ".rubocop.yml"
111
+ - ".solargraph.yml"
96
112
  - ".yardopts"
97
113
  - Changelog.md
98
114
  - Gemfile
@@ -166,7 +182,7 @@ homepage: http://github.com/Mange/roadie
166
182
  licenses:
167
183
  - MIT
168
184
  metadata: {}
169
- post_install_message:
185
+ post_install_message:
170
186
  rdoc_options: []
171
187
  require_paths:
172
188
  - lib
@@ -174,16 +190,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
174
190
  requirements:
175
191
  - - ">="
176
192
  - !ruby/object:Gem::Version
177
- version: '1.9'
193
+ version: '2.6'
178
194
  required_rubygems_version: !ruby/object:Gem::Requirement
179
195
  requirements:
180
196
  - - ">="
181
197
  - !ruby/object:Gem::Version
182
198
  version: '0'
183
199
  requirements: []
184
- rubyforge_project:
185
- rubygems_version: 2.6.14
186
- signing_key:
200
+ rubygems_version: 3.0.9
201
+ signing_key:
187
202
  specification_version: 4
188
203
  summary: Making HTML emails comfortable for the Ruby rockstars
189
204
  test_files:
data/.travis.yml DELETED
@@ -1,23 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.1
5
- - 2.2
6
- - 2.3
7
- - 2.4
8
- - 2.5
9
- - jruby
10
- - rbx
11
- before_install:
12
- - gem update --system # Need for Ruby 2.5.0. https://github.com/travis-ci/travis-ci/issues/8978
13
- - gem install bundler
14
- matrix:
15
- allow_failures:
16
- # Rubinius and JRuby have a lot of trouble and no large following, so I'm going to
17
- # allow failures on it until it gets more stable on Travis / Real Life(tm).
18
- # Let me know if you need it. Patches are welcome!
19
- - rvm: jruby
20
- - rvm: rbx
21
- fast_finish: true
22
- cache: bundler
23
- script: "rake"