premailer-rails 1.9.5 → 1.10.3

Sign up to get free protection for your applications and to get access to all the features.
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