premailer-rails 1.9.5 → 1.10.3

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.
Files changed (40) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +4 -0
  3. data/.travis.yml +2 -9
  4. data/CHANGELOG.md +26 -0
  5. data/Gemfile +8 -4
  6. data/README.md +21 -28
  7. data/VERSION +1 -1
  8. data/lib/premailer/rails/css_helper.rb +29 -10
  9. data/lib/premailer/rails/css_loaders/asset_pipeline_loader.rb +11 -11
  10. data/lib/premailer/rails/css_loaders/file_system_loader.rb +24 -2
  11. data/lib/premailer/rails/css_loaders/network_loader.rb +1 -1
  12. data/lib/premailer/rails/css_loaders.rb +0 -1
  13. data/lib/premailer/rails/customized_premailer.rb +4 -4
  14. data/lib/premailer/rails.rb +2 -1
  15. data/premailer-rails.gemspec +1 -2
  16. data/spec/integration/css_helper_spec.rb +170 -139
  17. data/spec/integration/delivery_spec.rb +13 -0
  18. data/spec/integration/hook_spec.rb +1 -1
  19. data/spec/rails_app/app/assets/config/manifest.js +3 -0
  20. data/spec/rails_app/app/assets/stylesheets/application.css +3 -0
  21. data/spec/rails_app/app/mailers/application_mailer.rb +4 -0
  22. data/spec/rails_app/app/mailers/welcome_mailer.rb +6 -0
  23. data/spec/rails_app/app/views/layouts/mailer.html.erb +11 -0
  24. data/spec/rails_app/app/views/welcome_mailer/welcome_email.html.erb +1 -0
  25. data/spec/rails_app/config/application.rb +13 -0
  26. data/spec/rails_app/config/boot.rb +5 -0
  27. data/spec/rails_app/config/environment.rb +2 -0
  28. data/spec/rails_app/config/environments/test.rb +10 -0
  29. data/spec/rails_app/config/initializers/assets.rb +1 -0
  30. data/spec/rails_app/config/routes.rb +3 -0
  31. data/spec/rails_app/config.ru +5 -0
  32. data/spec/spec_helper.rb +3 -4
  33. data/spec/unit/css_loaders/file_system_loader_spec.rb +37 -0
  34. data/spec/unit/css_loaders/network_loader_spec.rb +1 -1
  35. data/spec/unit/customized_premailer_spec.rb +32 -40
  36. metadata +33 -32
  37. data/lib/premailer/rails/css_loaders/cache_loader.rb +0 -29
  38. data/spec/integration/hook_registration_spec.rb +0 -11
  39. data/spec/support/stubs/action_mailer.rb +0 -5
  40. data/spec/support/stubs/rails.rb +0 -51
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 1d3d9d793a427df886ea2b99af60ce466db67bd2
4
- data.tar.gz: 3849875af6ec63a8194008c94ab543a0b8fbd920
2
+ SHA256:
3
+ metadata.gz: 36e83f5f50cf99a5c7c520cc40f135b08e1957f23bd471ab3dfd987549fcca25
4
+ data.tar.gz: 002da6d81c92ab09bf2af64c6dd7a87c6a0babf6fd70bc2b59361730499bf3e5
5
5
  SHA512:
6
- metadata.gz: e99f797aaa7f53584f5b8b63b5a20358be04e70a6c3677774abaf04814ceb1574393b7532dad24e36c5accc2ab86bed46aac6efc7967534afb1a5d9880be1dfe
7
- data.tar.gz: 17df1bf7a56bba9ed2474f85012b78d810b924b28efe756827ae66494a5948065dbb4f1aeae8dfc94744d2a830e18fd7f82ade8a90ec63f60a41481623c4e64d
6
+ metadata.gz: 2a44732ed01c2cb9ae7662e8dedaffd3d1989d32f627d7182683c6a6878c12e563cbe370008a4770f3e0643715c458ea981a5dd1a303387f4ddec825da7e80ad
7
+ data.tar.gz: 23e017fb41932ee883165623cc0afe3f74d9c49a27c5070bd879dfbf174faca160cc76bc3fae350f083be4b89380760016a3c5de8fcfcb1887e4033a855035e3
data/.gitignore CHANGED
@@ -2,3 +2,7 @@
2
2
  doc/
3
3
  Gemfile.lock
4
4
  coverage/
5
+ spec/rails_app/tmp/
6
+ spec/rails_app/log/
7
+ .ruby-version
8
+ /.bundle
data/.travis.yml CHANGED
@@ -3,20 +3,13 @@ language: ruby
3
3
  cache: bundler
4
4
  script: bundle exec rspec
5
5
  rvm:
6
- - 2.3.0
7
- - ruby-head
8
- - jruby
9
- - rbx-2
6
+ - 2.6.1
10
7
  env:
11
- global:
12
- - JRUBY_OPTS="--2.0"
13
8
  matrix:
14
9
  - ACTION_MAILER_VERSION=4
15
- - ACTION_MAILER_VERSION=5.beta
10
+ - ACTION_MAILER_VERSION=5
16
11
  - ACTION_MAILER_VERSION=master
17
12
  matrix:
18
13
  fast_finish: true
19
14
  allow_failures:
20
15
  - env: ACTION_MAILER_VERSION=master
21
- - env: ACTION_MAILER_VERSION=5.beta
22
- - rvm: ruby-head
data/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # Changelog
2
2
 
3
+ ## v1.10.3
4
+
5
+ - Remove upper version constraint for actionmailer
6
+
7
+ ## v1.10.2
8
+
9
+ - Explicitly check for assets_manifest (@derekwheel, #214)
10
+
11
+ ## v1.10.1
12
+
13
+ - Catch error when sprockets can't find asset (@kirs, #209)
14
+
15
+ ## v1.10.0
16
+
17
+ - Drop support for hpricot now that premailer-rails also doesn't support it
18
+ - Use `Rails.application.assets_manifest` instead of `Rails.application.assets` in Asset Pipeline loader (@kirs, #201)
19
+ - Introduce `:strategies` config option that allows to control CSS fetching stragies
20
+
21
+ ## v1.9.7
22
+
23
+ - Use `Rails.root` in `FileSystemLoader` (@stanhu, #195)
24
+
25
+ ## v1.9.6
26
+
27
+ - Handle `relative_url_root` in when loading CSS from file system
28
+
3
29
  ## v1.9.5
4
30
 
5
31
  - Mention license in gemspec
data/Gemfile CHANGED
@@ -2,16 +2,20 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- action_mailer_version = ENV.fetch('ACTION_MAILER_VERSION', '4')
5
+ rails_version = ENV.fetch('ACTION_MAILER_VERSION', '5')
6
6
 
7
- if action_mailer_version == 'master'
7
+ if rails_version == 'master'
8
8
  git 'git://github.com/rails/rails.git' do
9
- gem 'actionmailer'
9
+ gem 'rails'
10
10
  end
11
+ gem 'sprockets-rails', github: 'rails/sprockets-rails'
12
+ gem 'arel', github: 'rails/arel'
11
13
  else
12
- gem 'actionmailer', "~> #{action_mailer_version}"
14
+ gem 'rails', "~> #{rails_version}"
13
15
  end
14
16
 
17
+ gem 'byebug'
18
+
15
19
  platforms :rbx do
16
20
  gem 'rubysl'
17
21
  gem 'racc'
data/README.md CHANGED
@@ -39,34 +39,34 @@ styled emails without having to set anything up.
39
39
  Whenever premailer-rails processes an email, it collects the URLs of all linked
40
40
  stylesheets (`<link rel="stylesheet" href="css_url">`). Then, for each of these
41
41
  URLs, it tries to get the content through a couple of strategies. As long as
42
- a strategy does not return anything, the next one is used. The strategies and
43
- their order are as follows:
42
+ a strategy does not return anything, the next one is used. The strategies
43
+ available are:
44
44
 
45
- 1. **Cache:** If there's a file in cache matching that URL, the cache content
46
- is returned. The cache right now is rather rudimentary. Whenever a CSS file
47
- is retrieved, it is stored in memory such that subsequent requests to the
48
- same file are faster. The caching is disabled inside Rails in the
49
- development environment.
50
-
51
- 2. **File System:** If there's a file inside `public/` with the same path as in
45
+ - `:filesystem`: If there's a file inside `public/` with the same path as in
52
46
  the URL, it is read from disk. E.g. if the URL is
53
47
  `http://cdn.example.com/assets/email.css` the contents of the file located
54
48
  at `public/assets/email.css` gets returned if it exists.
55
49
 
56
- 3. **Asset Pipeline:** If Rails is available and the asset pipeline is enabled,
50
+ - `:asset_pipeline`: If Rails is available and the asset pipeline is enabled,
57
51
  the file is retrieved through the asset pipeline. E.g. if the URL is
58
52
  `http://cdn.example.com/assets/email-fingerprint123.css`, the file
59
53
  `email.css` is requested from the asset pipeline. That is, the fingerprint
60
54
  and the prefix (in this case `assets` is the prefix) are stripped before
61
55
  requesting it from the asset pipeline.
62
56
 
63
- 4. **Network:** As a last resort, the URL is simply requested and the response
64
- body is used. This is usefull when the assets are not bundled in the
57
+ - `:network`: As a last resort, the URL is simply requested and the response
58
+ body is used. This is useful when the assets are not bundled in the
65
59
  application and only available on a CDN. On Heroku e.g. you can add assets
66
60
  to your `.slugignore` causing your assets to not be available to the app
67
61
  (and thus resulting in a smaller app) and deploy the assets to a CDN such
68
62
  as S3/CloudFront.
69
63
 
64
+ You can configure which strategies you want to use as well as specify their
65
+ order. Refer to the *Configuration* section for more on this.
66
+
67
+ Note that the retrieved CSS is cached when the gem is running with Rails in
68
+ production.
69
+
70
70
  ## Installation
71
71
 
72
72
  Simply add the gem to your `Gemfile`:
@@ -75,19 +75,12 @@ Simply add the gem to your `Gemfile`:
75
75
  gem 'premailer-rails'
76
76
  ```
77
77
 
78
- premailer-rails requires either [nokogiri] or [hpricot]. It doesn't list them as
79
- a dependency so you can choose which one to use. Since hpricot is no longer
80
- maintained, I suggest you to go with nokogiri. Add either one to your `Gemfile`:
81
-
82
- ```ruby
83
- gem 'nokogiri'
84
- # or
85
- gem 'hpricot'
86
- ```
87
-
88
- If both gems are loaded for some reason, premailer chooses hpricot.
89
-
90
- That's it!
78
+ premailer-rails and premailer require a gem that is used to parse the email's
79
+ HTML. For a list of supported gems and how to select which one to use, please
80
+ refer to the [*Adapter*
81
+ section](https://github.com/premailer/premailer#adapters) of premailer. Note
82
+ that there is no hard dependency from either gem so you should add one yourself.
83
+ Also note that this gem is only tested with [nokogiri].
91
84
 
92
85
  ## Configuration
93
86
 
@@ -106,7 +99,8 @@ configs are:
106
99
  ```ruby
107
100
  {
108
101
  input_encoding: 'UTF-8',
109
- generate_text_part: true
102
+ generate_text_part: true,
103
+ strategies: [:filesystem, :asset_pipeline, :network]
110
104
  }
111
105
  ```
112
106
 
@@ -184,9 +178,8 @@ premailer-rails is released under the MIT license. See the [license file].
184
178
  [premailer]: https://github.com/premailer/premailer
185
179
  [actionmailer]: https://github.com/rails/rails/tree/master/actionmailer
186
180
  [nokogiri]: https://github.com/sparklemotion/nokogiri
187
- [hpricot]: https://github.com/hpricot/hpricot
188
181
 
189
- [premailer documentation]: http://rubydoc.info/gems/premailer/1.7.3/Premailer:initialize
182
+ [premailer documentation]: https://www.rubydoc.info/gems/premailer/Premailer:initialize
190
183
 
191
184
  [fphilipe twitter]: https://twitter.com/fphilipe
192
185
  [license file]: LICENSE
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.9.5
1
+ 1.10.3
@@ -5,12 +5,8 @@ class Premailer
5
5
 
6
6
  FileNotFound = Class.new(StandardError)
7
7
 
8
- STRATEGIES = [
9
- CSSLoaders::CacheLoader,
10
- CSSLoaders::FileSystemLoader,
11
- CSSLoaders::AssetPipelineLoader,
12
- CSSLoaders::NetworkLoader
13
- ]
8
+ attr_accessor :cache
9
+ self.cache = {}
14
10
 
15
11
  # Returns all linked CSS files concatenated as string.
16
12
  def css_for_doc(doc)
@@ -18,8 +14,10 @@ class Premailer
18
14
  end
19
15
 
20
16
  def css_for_url(url)
21
- load_css(url).tap do |content|
22
- CSSLoaders::CacheLoader.store(url, content)
17
+ if cache_enabled?
18
+ load_css_with_cache(url)
19
+ else
20
+ load_css(url)
23
21
  end
24
22
  end
25
23
 
@@ -36,14 +34,35 @@ class Premailer
36
34
  end
37
35
  end
38
36
 
37
+ def load_css_with_cache(url)
38
+ self.cache[url] ||= load_css(url)
39
+ end
40
+
41
+ def cache_enabled?
42
+ defined?(::Rails.env) && ::Rails.env.production?
43
+ end
44
+
39
45
  def load_css(url)
40
- STRATEGIES.each do |strategy|
41
- css = strategy.load(url)
46
+ Premailer::Rails.config.fetch(:strategies).each do |strategy|
47
+ css = find_strategy(strategy).load(url)
42
48
  return css.force_encoding('UTF-8') if css
43
49
  end
44
50
 
45
51
  raise FileNotFound, %{File with URL "#{url}" could not be loaded by any strategy.}
46
52
  end
53
+
54
+ def find_strategy(key)
55
+ case key
56
+ when :filesystem
57
+ CSSLoaders::FileSystemLoader
58
+ when :asset_pipeline
59
+ CSSLoaders::AssetPipelineLoader
60
+ when :network
61
+ CSSLoaders::NetworkLoader
62
+ else
63
+ key
64
+ end
65
+ end
47
66
  end
48
67
  end
49
68
  end
@@ -5,18 +5,11 @@ class Premailer
5
5
  extend self
6
6
 
7
7
  def load(url)
8
- if asset_pipeline_present?
9
- file = file_name(url)
10
- asset = ::Rails.application.assets.find_asset(file)
11
- asset.to_s if asset
12
- end
13
- end
8
+ return unless asset_pipeline_present?
14
9
 
15
- def asset_pipeline_present?
16
- defined?(::Rails) &&
17
- ::Rails.respond_to?(:application) &&
18
- ::Rails.application.respond_to?(:assets) &&
19
- ::Rails.application.assets
10
+ file = file_name(url)
11
+ ::Rails.application.assets_manifest.find_sources(file).first
12
+ rescue Errno::ENOENT, TypeError => _error
20
13
  end
21
14
 
22
15
  def file_name(url)
@@ -29,6 +22,13 @@ class Premailer
29
22
  .sub(/\A#{prefix}/, '')
30
23
  .sub(/-(\h{32}|\h{64})\.css\z/, '.css')
31
24
  end
25
+
26
+ def asset_pipeline_present?
27
+ defined?(::Rails) &&
28
+ ::Rails.application &&
29
+ ::Rails.application.respond_to?(:assets_manifest) &&
30
+ ::Rails.application.assets_manifest
31
+ end
32
32
  end
33
33
  end
34
34
  end
@@ -5,9 +5,31 @@ class Premailer
5
5
  extend self
6
6
 
7
7
  def load(url)
8
+ file = file_name(url)
9
+ File.read(file) if File.file?(file)
10
+ end
11
+
12
+ def file_name(url)
8
13
  path = URI(url).path
9
- file_path = "public#{path}"
10
- File.read(file_path) if File.file?(file_path)
14
+ if relative_url_root
15
+ path = path.sub(/\A#{relative_url_root.chomp('/')}/, '')
16
+ end
17
+ asset_filename(path)
18
+ end
19
+
20
+ def asset_filename(filename)
21
+ if defined?(::Rails) && ::Rails.respond_to?(:root)
22
+ File.join(::Rails.root, 'public', filename)
23
+ else
24
+ File.join('public', filename)
25
+ end
26
+ end
27
+
28
+ def relative_url_root
29
+ defined?(::Rails) &&
30
+ ::Rails.respond_to?(:configuration) &&
31
+ ::Rails.configuration.respond_to?(:relative_url_root) &&
32
+ ::Rails.configuration.relative_url_root
11
33
  end
12
34
  end
13
35
  end
@@ -14,7 +14,7 @@ class Premailer
14
14
 
15
15
  if uri.host.present?
16
16
  return uri if uri.scheme.present?
17
- URI("http://#{uri.to_s}")
17
+ URI("http:#{uri}")
18
18
  elsif asset_host_present?
19
19
  scheme, host = asset_host(url).split(%r{:?//})
20
20
  scheme, host = host, scheme if host.nil?
@@ -1,6 +1,5 @@
1
1
  require 'uri'
2
2
 
3
- require 'premailer/rails/css_loaders/cache_loader'
4
3
  require 'premailer/rails/css_loaders/file_system_loader'
5
4
  require 'premailer/rails/css_loaders/asset_pipeline_loader'
6
5
  require 'premailer/rails/css_loaders/network_loader'
@@ -4,10 +4,10 @@ class Premailer
4
4
  def initialize(html)
5
5
  # In order to pass the CSS as string to super it is necessary to access
6
6
  # the parsed HTML beforehand. To do so, the adapter needs to be
7
- # initialized. The ::Premailer::Adaptor handles the discovery of a
8
- # suitable adaptor (Nokogiri or Hpricot). To make load_html work, an
9
- # adaptor needs to be included and @options[:with_html_string] needs to
10
- # be set. For further information, refer to ::Premailer#initialize.
7
+ # initialized. The ::Premailer::Adapter handles the discovery of
8
+ # a suitable adapter. To make load_html work, an adapter needs to be
9
+ # included and @options[:with_html_string] needs to be set. For further
10
+ # information, refer to ::Premailer#initialize.
11
11
  @options = Rails.config.merge(with_html_string: true)
12
12
  Premailer.send(:include, Adapter.find(Adapter.use))
13
13
  doc = load_html(html)
@@ -11,7 +11,8 @@ class Premailer
11
11
  module Rails
12
12
  @config = {
13
13
  input_encoding: 'UTF-8',
14
- generate_text_part: true
14
+ generate_text_part: true,
15
+ strategies: [:filesystem, :asset_pipeline, :network]
15
16
  }
16
17
  class << self
17
18
  attr_accessor :config
@@ -22,10 +22,9 @@ Gem::Specification.new do |s|
22
22
  s.require_paths = ["lib"]
23
23
 
24
24
  s.add_dependency 'premailer', '~> 1.7', '>= 1.7.9'
25
- s.add_dependency 'actionmailer', '>= 3', '< 6'
25
+ s.add_dependency 'actionmailer', '>= 3'
26
26
 
27
27
  s.add_development_dependency 'rspec', '~> 3.3'
28
28
  s.add_development_dependency 'nokogiri'
29
- s.add_development_dependency 'hpricot' unless RUBY_PLATFORM == 'java'
30
29
  s.add_development_dependency 'coveralls' if RUBY_ENGINE == 'ruby'
31
30
  end