premailer-rails 1.9.7 → 1.10.0
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.
- checksums.yaml +5 -5
- data/.gitignore +4 -0
- data/CHANGELOG.md +6 -0
- data/Gemfile +8 -4
- data/README.md +20 -28
- data/VERSION +1 -1
- data/lib/premailer/rails.rb +2 -1
- data/lib/premailer/rails/css_helper.rb +29 -10
- data/lib/premailer/rails/css_loaders.rb +0 -1
- data/lib/premailer/rails/css_loaders/asset_pipeline_loader.rb +8 -11
- data/lib/premailer/rails/css_loaders/network_loader.rb +1 -1
- data/lib/premailer/rails/customized_premailer.rb +4 -4
- data/premailer-rails.gemspec +0 -1
- data/spec/integration/css_helper_spec.rb +155 -141
- data/spec/integration/delivery_spec.rb +13 -0
- data/spec/integration/hook_spec.rb +1 -1
- data/spec/rails_app/app/assets/config/manifest.js +3 -0
- data/spec/rails_app/app/assets/stylesheets/application.css +3 -0
- data/spec/rails_app/app/mailers/application_mailer.rb +4 -0
- data/spec/rails_app/app/mailers/welcome_mailer.rb +6 -0
- data/spec/rails_app/app/views/layouts/mailer.html.erb +11 -0
- data/spec/rails_app/app/views/welcome_mailer/welcome_email.html.erb +1 -0
- data/spec/rails_app/config.ru +5 -0
- data/spec/rails_app/config/application.rb +13 -0
- data/spec/rails_app/config/boot.rb +5 -0
- data/spec/rails_app/config/environment.rb +2 -0
- data/spec/rails_app/config/environments/test.rb +10 -0
- data/spec/rails_app/config/initializers/assets.rb +1 -0
- data/spec/rails_app/config/routes.rb +3 -0
- data/spec/spec_helper.rb +3 -8
- data/spec/unit/css_loaders/network_loader_spec.rb +1 -1
- data/spec/unit/customized_premailer_spec.rb +32 -40
- metadata +31 -24
- data/lib/premailer/rails/css_loaders/cache_loader.rb +0 -29
- data/spec/integration/hook_registration_spec.rb +0 -11
- data/spec/support/stubs/action_mailer.rb +0 -5
- data/spec/support/stubs/rails.rb +0 -51
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 77899a5ba8ec23d6cf40d3b3d630f7872e92cbc959ba64ac528b31a658ae6f13
|
4
|
+
data.tar.gz: 4d13e28457b824306a517a7cff731fd83713654367562c9a7192e8a632d62aa2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc27f934b5772cc632cb7424013d31176afcdf47e60696479eb712c4ee85abe24a5d2524848e862e5a1489aea0778a789b1f2e96dc308df5caeb91a06f763e96
|
7
|
+
data.tar.gz: c3de5ed3a8625350eff2c07b30ed01cf418f6bb0a820e2244ad1e5c1018f495d8270e699539e21fbcac2e31c43d5e9fc36202b867b4d784c8955f8ea6338d13d
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## v1.10.0
|
4
|
+
|
5
|
+
- Drop support for hpricot now that premailer-rails also doesn't support it
|
6
|
+
- Use `Rails.application.assets_manifest` instead of `Rails.application.assets` in Asset Pipeline loader (@kirs, #201)
|
7
|
+
- Introduce `:strategies` config option that allows to control CSS fetching stragies
|
8
|
+
|
3
9
|
## v1.9.7
|
4
10
|
|
5
11
|
- Use `Rails.root` in `FileSystemLoader` (@stanhu, #195)
|
data/Gemfile
CHANGED
@@ -2,16 +2,20 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
|
-
|
5
|
+
rails_version = ENV.fetch('ACTION_MAILER_VERSION', '5')
|
6
6
|
|
7
|
-
if
|
7
|
+
if rails_version == 'master'
|
8
8
|
git 'git://github.com/rails/rails.git' do
|
9
|
-
gem '
|
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 '
|
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
|
43
|
-
|
42
|
+
a strategy does not return anything, the next one is used. The strategies
|
43
|
+
available are:
|
44
44
|
|
45
|
-
|
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
|
-
|
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
|
-
|
64
|
-
body is used. This is
|
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,20 +75,12 @@ Simply add the gem to your `Gemfile`:
|
|
75
75
|
gem 'premailer-rails'
|
76
76
|
```
|
77
77
|
|
78
|
-
premailer-rails
|
79
|
-
a
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
gem
|
84
|
-
# or
|
85
|
-
gem 'hpricot'
|
86
|
-
```
|
87
|
-
|
88
|
-
If both gems are loaded for some reason, premailer chooses hpricot.
|
89
|
-
|
90
|
-
You can also explicitly configure the apapter as documented
|
91
|
-
[here](https://github.com/premailer/premailer#adapters).
|
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].
|
92
84
|
|
93
85
|
## Configuration
|
94
86
|
|
@@ -107,7 +99,8 @@ configs are:
|
|
107
99
|
```ruby
|
108
100
|
{
|
109
101
|
input_encoding: 'UTF-8',
|
110
|
-
generate_text_part: true
|
102
|
+
generate_text_part: true,
|
103
|
+
strategies: [:filesystem, :asset_pipeline, :network]
|
111
104
|
}
|
112
105
|
```
|
113
106
|
|
@@ -185,7 +178,6 @@ premailer-rails is released under the MIT license. See the [license file].
|
|
185
178
|
[premailer]: https://github.com/premailer/premailer
|
186
179
|
[actionmailer]: https://github.com/rails/rails/tree/master/actionmailer
|
187
180
|
[nokogiri]: https://github.com/sparklemotion/nokogiri
|
188
|
-
[hpricot]: https://github.com/hpricot/hpricot
|
189
181
|
|
190
182
|
[premailer documentation]: http://rubydoc.info/gems/premailer/1.7.3/Premailer:initialize
|
191
183
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.10.0
|
data/lib/premailer/rails.rb
CHANGED
@@ -5,12 +5,8 @@ class Premailer
|
|
5
5
|
|
6
6
|
FileNotFound = Class.new(StandardError)
|
7
7
|
|
8
|
-
|
9
|
-
|
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
|
-
|
22
|
-
|
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) && ::Rails.env.production?
|
43
|
+
end
|
44
|
+
|
39
45
|
def load_css(url)
|
40
|
-
|
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
|
-
|
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
|
-
|
16
|
-
|
17
|
-
|
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 => _error
|
20
13
|
end
|
21
14
|
|
22
15
|
def file_name(url)
|
@@ -29,6 +22,10 @@ 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) && ::Rails.application && ::Rails.application.assets_manifest
|
28
|
+
end
|
32
29
|
end
|
33
30
|
end
|
34
31
|
end
|
@@ -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::
|
8
|
-
# suitable
|
9
|
-
#
|
10
|
-
#
|
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)
|
data/premailer-rails.gemspec
CHANGED
@@ -26,6 +26,5 @@ Gem::Specification.new do |s|
|
|
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
|
@@ -1,186 +1,200 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Premailer::Rails::CSSHelper do
|
4
|
-
|
5
|
-
|
4
|
+
# Reset the CSS cache:
|
5
|
+
after do
|
6
|
+
Premailer::Rails::CSSHelper.cache = {}
|
7
|
+
end
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
Premailer::Rails::CSSLoaders::CacheLoader.clear!
|
11
|
-
end
|
9
|
+
def css_for_url(path)
|
10
|
+
Premailer::Rails::CSSHelper.css_for_url(path)
|
11
|
+
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
def css_for_doc(doc)
|
14
|
+
Premailer::Rails::CSSHelper.css_for_doc(doc)
|
15
|
+
end
|
16
|
+
|
17
|
+
def expect_file(path, content='file content')
|
18
|
+
path = "#{Rails.root}/#{path}"
|
19
|
+
allow(File).to receive(:file?).with(path).and_return(true)
|
20
|
+
expect(File).to receive(:read).with(path).and_return(content)
|
21
|
+
end
|
16
22
|
|
17
|
-
|
18
|
-
|
23
|
+
describe '#css_for_doc' do
|
24
|
+
let(:html) { Fixtures::HTML.with_css_links(*files) }
|
25
|
+
let(:doc) { Nokogiri(html) }
|
26
|
+
|
27
|
+
context 'when HTML contains linked CSS files' do
|
28
|
+
let(:files) { %w[ stylesheets/base.css stylesheets/font.css ] }
|
29
|
+
|
30
|
+
it 'returns the content of both files concatenated' do
|
31
|
+
allow(Premailer::Rails::CSSHelper).to \
|
32
|
+
receive(:css_for_url)
|
33
|
+
.with('http://example.com/stylesheets/base.css')
|
34
|
+
.and_return('content of base.css')
|
35
|
+
allow(Premailer::Rails::CSSHelper).to \
|
36
|
+
receive(:css_for_url)
|
37
|
+
.with('http://example.com/stylesheets/font.css')
|
38
|
+
.and_return('content of font.css')
|
39
|
+
|
40
|
+
expect(css_for_doc(doc)).to eq("content of base.css\ncontent of font.css")
|
19
41
|
end
|
42
|
+
end
|
20
43
|
|
21
|
-
|
22
|
-
|
23
|
-
|
44
|
+
context 'when HTML contains ignored links' do
|
45
|
+
let(:files) { ['ignore.css', 'data-premailer' => 'ignore'] }
|
46
|
+
|
47
|
+
it 'ignores links' do
|
48
|
+
expect(Premailer::Rails::CSSHelper).to_not receive(:css_for_url)
|
49
|
+
css_for_doc(doc)
|
24
50
|
end
|
51
|
+
end
|
52
|
+
end
|
25
53
|
|
26
|
-
|
27
|
-
|
28
|
-
|
54
|
+
describe '#css_for_url' do
|
55
|
+
context 'when path is a url' do
|
56
|
+
it 'loads the CSS at the local path' do
|
57
|
+
expect_file('public/stylesheets/base.css')
|
29
58
|
|
30
|
-
|
31
|
-
|
59
|
+
css_for_url('http://example.com/stylesheets/base.css?test')
|
60
|
+
end
|
61
|
+
end
|
32
62
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
receive(:css_for_url)
|
40
|
-
.with('http://example.com/stylesheets/font.css')
|
41
|
-
.and_return('content of font.css')
|
63
|
+
context 'when path is a relative url' do
|
64
|
+
it 'loads the CSS at the local path' do
|
65
|
+
expect_file('public/stylesheets/base.css')
|
66
|
+
css_for_url('/stylesheets/base.css?test')
|
67
|
+
end
|
68
|
+
end
|
42
69
|
|
43
|
-
|
44
|
-
|
45
|
-
|
70
|
+
context 'when cache is enabled' do
|
71
|
+
before do
|
72
|
+
allow(Premailer::Rails::CSSHelper).to receive(:cache_enabled?).and_return(true)
|
73
|
+
end
|
46
74
|
|
47
|
-
|
48
|
-
|
75
|
+
context 'when file is cached' do
|
76
|
+
it 'returns the cached value' do
|
77
|
+
Premailer::Rails::CSSHelper.cache['http://example.com/stylesheets/base.css'] = 'content of base.css'
|
49
78
|
|
50
|
-
|
51
|
-
|
52
|
-
css_for_doc(doc)
|
53
|
-
end
|
79
|
+
expect(css_for_url('http://example.com/stylesheets/base.css')).to \
|
80
|
+
eq('content of base.css')
|
54
81
|
end
|
55
82
|
end
|
83
|
+
end
|
56
84
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
85
|
+
context 'when cache is disabled' do
|
86
|
+
before do
|
87
|
+
allow(Premailer::Rails::CSSHelper).to receive(:cache_enabled?).and_return(false)
|
88
|
+
end
|
61
89
|
|
62
|
-
|
63
|
-
|
64
|
-
|
90
|
+
it 'does not return cached values' do
|
91
|
+
Premailer::Rails::CSSHelper.cache['http://example.com/stylesheets/base.css'] = 'cached content'
|
92
|
+
content = 'new content of base.css'
|
93
|
+
expect_file('public/stylesheets/base.css', content)
|
65
94
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
css_for_url('/stylesheets/base.css?test')
|
70
|
-
end
|
71
|
-
end
|
95
|
+
expect(css_for_url('http://example.com/stylesheets/base.css')).to eq(content)
|
96
|
+
end
|
97
|
+
end
|
72
98
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
99
|
+
context 'when Rails asset pipeline is used' do
|
100
|
+
before do
|
101
|
+
allow(Rails.configuration)
|
102
|
+
.to receive(:assets).and_return(double(prefix: '/assets'))
|
103
|
+
allow(Rails.configuration)
|
104
|
+
.to receive(:relative_url_root).and_return(nil)
|
105
|
+
end
|
79
106
|
|
80
|
-
|
81
|
-
|
82
|
-
|
107
|
+
context 'and a precompiled file exists' do
|
108
|
+
it 'returns that file' do
|
109
|
+
path = '/assets/email-digest.css'
|
110
|
+
content = 'read from file'
|
111
|
+
expect_file("public#{path}", content)
|
112
|
+
expect(css_for_url(path)).to eq(content)
|
83
113
|
end
|
114
|
+
end
|
84
115
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
'http://example.com/stylesheets/base.css',
|
89
|
-
'cached content of base.css'
|
90
|
-
)
|
91
|
-
content = 'new content of base.css'
|
92
|
-
expect_file('public/stylesheets/base.css', content)
|
93
|
-
allow(Rails.env).to receive(:development?).and_return(true)
|
94
|
-
|
95
|
-
expect(css_for_url('http://example.com/stylesheets/base.css')).to eq(content)
|
96
|
-
end
|
97
|
-
end
|
116
|
+
context "when find_sources raises Errno::ENOENT" do
|
117
|
+
let(:response) { 'content of base.css' }
|
118
|
+
let(:uri) { URI('http://example.com/assets/base.css') }
|
98
119
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
.
|
103
|
-
|
104
|
-
.to receive(:relative_url_root).and_return(nil)
|
105
|
-
end
|
120
|
+
it "falls back to Net::HTTP" do
|
121
|
+
expect(Rails.application.assets_manifest).to \
|
122
|
+
receive(:find_sources)
|
123
|
+
.with('base.css')
|
124
|
+
.and_raise(Errno::ENOENT)
|
106
125
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
end
|
114
|
-
end
|
126
|
+
allow(Net::HTTP).to \
|
127
|
+
receive(:get).with(uri).and_return(response)
|
128
|
+
expect(css_for_url('http://example.com/assets/base.css')).to \
|
129
|
+
eq(response)
|
130
|
+
end
|
131
|
+
end
|
115
132
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
133
|
+
it 'returns the content of the file compiled by Rails' do
|
134
|
+
expect(Rails.application.assets_manifest).to \
|
135
|
+
receive(:find_sources)
|
136
|
+
.with('base.css')
|
137
|
+
.and_return(['content of base.css'])
|
121
138
|
|
122
|
-
|
123
|
-
|
124
|
-
|
139
|
+
expect(css_for_url('http://example.com/assets/base.css')).to \
|
140
|
+
eq('content of base.css')
|
141
|
+
end
|
125
142
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
143
|
+
it 'returns same file when path contains file fingerprint' do
|
144
|
+
expect(Rails.application.assets_manifest).to \
|
145
|
+
receive(:find_sources)
|
146
|
+
.with('base.css')
|
147
|
+
.and_return(['content of base.css'])
|
131
148
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
149
|
+
expect(css_for_url(
|
150
|
+
'http://example.com/assets/base-089e35bd5d84297b8d31ad552e433275.css'
|
151
|
+
)).to eq('content of base.css')
|
152
|
+
end
|
136
153
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
154
|
+
context 'when asset can not be found' do
|
155
|
+
let(:response) { 'content of base.css' }
|
156
|
+
let(:path) { '/assets/base-089e35bd5d84297b8d31ad552e433275.css' }
|
157
|
+
let(:url) { "http://assets.example.com#{path}" }
|
158
|
+
let(:asset_host) { 'http://assets.example.com' }
|
142
159
|
|
143
|
-
|
144
|
-
|
145
|
-
|
160
|
+
before do
|
161
|
+
allow(Rails.application.assets_manifest).to \
|
162
|
+
receive(:find_sources).and_return([])
|
146
163
|
|
147
|
-
|
148
|
-
|
149
|
-
|
164
|
+
config = double(asset_host: asset_host)
|
165
|
+
allow(Rails.configuration).to \
|
166
|
+
receive(:action_controller).and_return(config)
|
150
167
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
end
|
168
|
+
allow(Net::HTTP).to \
|
169
|
+
receive(:get).with(URI(url)).and_return(response)
|
170
|
+
end
|
155
171
|
|
156
|
-
|
157
|
-
|
158
|
-
|
172
|
+
it 'requests the file' do
|
173
|
+
expect(css_for_url(url)).to eq('content of base.css')
|
174
|
+
end
|
159
175
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
176
|
+
context 'when file url does not include the host' do
|
177
|
+
it 'requests the file using the asset host as host' do
|
178
|
+
expect(css_for_url(path)).to eq('content of base.css')
|
179
|
+
end
|
164
180
|
|
165
|
-
|
166
|
-
|
181
|
+
context 'and the asset host uses protocol relative scheme' do
|
182
|
+
let(:asset_host) { '//assets.example.com' }
|
167
183
|
|
168
|
-
|
169
|
-
|
170
|
-
end
|
171
|
-
end
|
184
|
+
it 'requests the file using http as the scheme' do
|
185
|
+
expect(css_for_url(path)).to eq('content of base.css')
|
172
186
|
end
|
173
187
|
end
|
174
188
|
end
|
189
|
+
end
|
190
|
+
end
|
175
191
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
end
|
183
|
-
end
|
192
|
+
context 'when static stylesheets are used' do
|
193
|
+
it 'returns the content of the static file' do
|
194
|
+
content = 'content of base.css'
|
195
|
+
expect_file('public/stylesheets/base.css', content)
|
196
|
+
loaded_content = css_for_url('http://example.com/stylesheets/base.css')
|
197
|
+
expect(loaded_content).to eq(content)
|
184
198
|
end
|
185
199
|
end
|
186
200
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'ActionMailer::Base delivery' do
|
4
|
+
it 'delivers email with inlined CSS' do
|
5
|
+
WelcomeMailer.welcome_email("world").deliver_now
|
6
|
+
|
7
|
+
mail = ActionMailer::Base.deliveries.last
|
8
|
+
expect(mail).to be_present
|
9
|
+
body = mail.html_part.body.to_s
|
10
|
+
expect(body).to be_present
|
11
|
+
expect(body).to include(%{<p style="font-size: 12px;">Hello world</p>})
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<p>Hello <%= @greeting %></p>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative 'boot'
|
2
|
+
|
3
|
+
require "action_mailer/railtie"
|
4
|
+
require "action_view/railtie"
|
5
|
+
require "sprockets/railtie"
|
6
|
+
require "rails/test_unit/railtie"
|
7
|
+
|
8
|
+
Bundler.require(*Rails.groups)
|
9
|
+
|
10
|
+
module Dummy
|
11
|
+
class Application < Rails::Application
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Rails.application.configure do
|
2
|
+
config.cache_classes = true
|
3
|
+
config.eager_load = false
|
4
|
+
config.consider_all_requests_local = true
|
5
|
+
config.action_controller.perform_caching = false
|
6
|
+
config.action_dispatch.show_exceptions = false
|
7
|
+
config.action_controller.allow_forgery_protection = false
|
8
|
+
config.action_mailer.delivery_method = :test
|
9
|
+
config.active_support.deprecation = :stderr
|
10
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Rails.application.config.assets.version = '1.0'
|
data/spec/spec_helper.rb
CHANGED
@@ -11,16 +11,11 @@ if RUBY_ENGINE == 'ruby'
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
#
|
15
|
-
|
16
|
-
require
|
14
|
+
# Configure Rails Environment
|
15
|
+
ENV["RAILS_ENV"] = "test"
|
16
|
+
require File.expand_path("../../spec/rails_app/config/environment.rb", __FILE__)
|
17
17
|
|
18
|
-
require 'premailer/rails'
|
19
|
-
|
20
|
-
require 'support/stubs/action_mailer'
|
21
|
-
require 'support/stubs/rails'
|
22
18
|
require 'support/fixtures/message'
|
23
19
|
require 'support/fixtures/html'
|
24
20
|
|
25
|
-
require 'hpricot' unless RUBY_PLATFORM == 'java'
|
26
21
|
require 'nokogiri'
|
@@ -18,7 +18,7 @@ describe Premailer::Rails::CSSLoaders::NetworkLoader do
|
|
18
18
|
|
19
19
|
context 'with a protocol relative URL' do
|
20
20
|
let(:url) { '//example.com/test.css' }
|
21
|
-
it { is_expected.to eq(URI("http
|
21
|
+
it { is_expected.to eq(URI("http:#{url}")) }
|
22
22
|
end
|
23
23
|
|
24
24
|
context 'with a file path' do
|
@@ -1,51 +1,43 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Premailer::Rails::CustomizedPremailer do
|
4
|
-
|
5
|
-
|
4
|
+
describe '#to_plain_text' do
|
5
|
+
it 'includes the text from the HTML part' do
|
6
|
+
premailer =
|
7
|
+
Premailer::Rails::CustomizedPremailer
|
8
|
+
.new(Fixtures::Message::HTML_PART)
|
9
|
+
expect(premailer.to_plain_text.gsub(/\s/, ' ').strip).to \
|
10
|
+
eq(Fixtures::Message::TEXT_PART.gsub(/\s/, ' ').strip)
|
11
|
+
end
|
12
|
+
end
|
6
13
|
|
7
|
-
|
8
|
-
|
14
|
+
describe '#to_inline_css' do
|
15
|
+
let(:regex) { %r{<p style=("|')color: ?red;?\1>} }
|
9
16
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
17
|
+
context 'when inline CSS block present' do
|
18
|
+
it 'returns the HTML with the CSS inlined' do
|
19
|
+
allow(Premailer::Rails::CSSHelper).to \
|
20
|
+
receive(:css_for_doc).and_return('p { color: red; }')
|
21
|
+
html = Fixtures::Message::HTML_PART
|
22
|
+
premailer = Premailer::Rails::CustomizedPremailer.new(html)
|
23
|
+
expect(premailer.to_inline_css).to match(regex)
|
18
24
|
end
|
25
|
+
end
|
19
26
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
html = Fixtures::Message::HTML_PART
|
28
|
-
premailer = Premailer::Rails::CustomizedPremailer.new(html)
|
29
|
-
expect(premailer.to_inline_css).to match(regex)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
context 'when CSS is loaded externally' do
|
34
|
-
it 'returns the HTML with the CSS inlined' do
|
35
|
-
html = Fixtures::Message::HTML_PART_WITH_CSS
|
36
|
-
premailer = Premailer::Rails::CustomizedPremailer.new(html)
|
37
|
-
expect(premailer.to_inline_css).to match(regex)
|
38
|
-
end
|
39
|
-
end
|
27
|
+
context 'when CSS is loaded externally' do
|
28
|
+
it 'returns the HTML with the CSS inlined' do
|
29
|
+
html = Fixtures::Message::HTML_PART_WITH_CSS
|
30
|
+
premailer = Premailer::Rails::CustomizedPremailer.new(html)
|
31
|
+
expect(premailer.to_inline_css).to match(regex)
|
32
|
+
end
|
33
|
+
end
|
40
34
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
48
|
-
end
|
35
|
+
context 'when HTML contains unicode' do
|
36
|
+
it 'does not mess those up' do
|
37
|
+
html = Fixtures::Message::HTML_PART_WITH_UNICODE
|
38
|
+
premailer = Premailer::Rails::CustomizedPremailer.new(html)
|
39
|
+
expect(premailer.to_inline_css).to \
|
40
|
+
include(Fixtures::Message::UNICODE_STRING)
|
49
41
|
end
|
50
42
|
end
|
51
43
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: premailer-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Philipe Fatio
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-11-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: premailer
|
@@ -78,20 +78,6 @@ dependencies:
|
|
78
78
|
- - ">="
|
79
79
|
- !ruby/object:Gem::Version
|
80
80
|
version: '0'
|
81
|
-
- !ruby/object:Gem::Dependency
|
82
|
-
name: hpricot
|
83
|
-
requirement: !ruby/object:Gem::Requirement
|
84
|
-
requirements:
|
85
|
-
- - ">="
|
86
|
-
- !ruby/object:Gem::Version
|
87
|
-
version: '0'
|
88
|
-
type: :development
|
89
|
-
prerelease: false
|
90
|
-
version_requirements: !ruby/object:Gem::Requirement
|
91
|
-
requirements:
|
92
|
-
- - ">="
|
93
|
-
- !ruby/object:Gem::Version
|
94
|
-
version: '0'
|
95
81
|
- !ruby/object:Gem::Dependency
|
96
82
|
name: coveralls
|
97
83
|
requirement: !ruby/object:Gem::Requirement
|
@@ -149,7 +135,6 @@ files:
|
|
149
135
|
- lib/premailer/rails/css_helper.rb
|
150
136
|
- lib/premailer/rails/css_loaders.rb
|
151
137
|
- lib/premailer/rails/css_loaders/asset_pipeline_loader.rb
|
152
|
-
- lib/premailer/rails/css_loaders/cache_loader.rb
|
153
138
|
- lib/premailer/rails/css_loaders/file_system_loader.rb
|
154
139
|
- lib/premailer/rails/css_loaders/network_loader.rb
|
155
140
|
- lib/premailer/rails/customized_premailer.rb
|
@@ -158,13 +143,24 @@ files:
|
|
158
143
|
- lib/premailer/rails/version.rb
|
159
144
|
- premailer-rails.gemspec
|
160
145
|
- spec/integration/css_helper_spec.rb
|
161
|
-
- spec/integration/
|
146
|
+
- spec/integration/delivery_spec.rb
|
162
147
|
- spec/integration/hook_spec.rb
|
148
|
+
- spec/rails_app/app/assets/config/manifest.js
|
149
|
+
- spec/rails_app/app/assets/stylesheets/application.css
|
150
|
+
- spec/rails_app/app/mailers/application_mailer.rb
|
151
|
+
- spec/rails_app/app/mailers/welcome_mailer.rb
|
152
|
+
- spec/rails_app/app/views/layouts/mailer.html.erb
|
153
|
+
- spec/rails_app/app/views/welcome_mailer/welcome_email.html.erb
|
154
|
+
- spec/rails_app/config.ru
|
155
|
+
- spec/rails_app/config/application.rb
|
156
|
+
- spec/rails_app/config/boot.rb
|
157
|
+
- spec/rails_app/config/environment.rb
|
158
|
+
- spec/rails_app/config/environments/test.rb
|
159
|
+
- spec/rails_app/config/initializers/assets.rb
|
160
|
+
- spec/rails_app/config/routes.rb
|
163
161
|
- spec/spec_helper.rb
|
164
162
|
- spec/support/fixtures/html.rb
|
165
163
|
- spec/support/fixtures/message.rb
|
166
|
-
- spec/support/stubs/action_mailer.rb
|
167
|
-
- spec/support/stubs/rails.rb
|
168
164
|
- spec/unit/css_loaders/asset_pipeline_loader_spec.rb
|
169
165
|
- spec/unit/css_loaders/file_system_loader_spec.rb
|
170
166
|
- spec/unit/css_loaders/network_loader_spec.rb
|
@@ -190,7 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
190
186
|
version: '0'
|
191
187
|
requirements: []
|
192
188
|
rubyforge_project:
|
193
|
-
rubygems_version: 2.
|
189
|
+
rubygems_version: 2.7.2
|
194
190
|
signing_key:
|
195
191
|
specification_version: 4
|
196
192
|
summary: Easily create styled HTML emails in Rails.
|
@@ -213,13 +209,24 @@ test_files:
|
|
213
209
|
- example/config/secrets.yml
|
214
210
|
- example/test/mailers/previews/example_mailer_preview.rb
|
215
211
|
- spec/integration/css_helper_spec.rb
|
216
|
-
- spec/integration/
|
212
|
+
- spec/integration/delivery_spec.rb
|
217
213
|
- spec/integration/hook_spec.rb
|
214
|
+
- spec/rails_app/app/assets/config/manifest.js
|
215
|
+
- spec/rails_app/app/assets/stylesheets/application.css
|
216
|
+
- spec/rails_app/app/mailers/application_mailer.rb
|
217
|
+
- spec/rails_app/app/mailers/welcome_mailer.rb
|
218
|
+
- spec/rails_app/app/views/layouts/mailer.html.erb
|
219
|
+
- spec/rails_app/app/views/welcome_mailer/welcome_email.html.erb
|
220
|
+
- spec/rails_app/config.ru
|
221
|
+
- spec/rails_app/config/application.rb
|
222
|
+
- spec/rails_app/config/boot.rb
|
223
|
+
- spec/rails_app/config/environment.rb
|
224
|
+
- spec/rails_app/config/environments/test.rb
|
225
|
+
- spec/rails_app/config/initializers/assets.rb
|
226
|
+
- spec/rails_app/config/routes.rb
|
218
227
|
- spec/spec_helper.rb
|
219
228
|
- spec/support/fixtures/html.rb
|
220
229
|
- spec/support/fixtures/message.rb
|
221
|
-
- spec/support/stubs/action_mailer.rb
|
222
|
-
- spec/support/stubs/rails.rb
|
223
230
|
- spec/unit/css_loaders/asset_pipeline_loader_spec.rb
|
224
231
|
- spec/unit/css_loaders/file_system_loader_spec.rb
|
225
232
|
- spec/unit/css_loaders/network_loader_spec.rb
|
@@ -1,29 +0,0 @@
|
|
1
|
-
class Premailer
|
2
|
-
module Rails
|
3
|
-
module CSSLoaders
|
4
|
-
module CacheLoader
|
5
|
-
extend self
|
6
|
-
|
7
|
-
@cache = {}
|
8
|
-
|
9
|
-
def load(url)
|
10
|
-
@cache[url] unless development_env?
|
11
|
-
end
|
12
|
-
|
13
|
-
def store(url, content)
|
14
|
-
@cache[url] ||= content unless development_env?
|
15
|
-
end
|
16
|
-
|
17
|
-
def clear!
|
18
|
-
@cache = {}
|
19
|
-
end
|
20
|
-
|
21
|
-
def development_env?
|
22
|
-
defined?(::Rails) &&
|
23
|
-
::Rails.respond_to?(:env) &&
|
24
|
-
::Rails.env.development?
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe 'ActionMailer::Base.register_interceptor' do
|
4
|
-
it 'registers interceptors' do
|
5
|
-
expect(ActionMailer::Base).to \
|
6
|
-
receive(:register_interceptor).with(Premailer::Rails::Hook)
|
7
|
-
expect(ActionMailer::Base).to \
|
8
|
-
receive(:register_preview_interceptor).with(Premailer::Rails::Hook)
|
9
|
-
load 'premailer/rails.rb'
|
10
|
-
end
|
11
|
-
end
|
data/spec/support/stubs/rails.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
module Rails
|
2
|
-
extend self
|
3
|
-
|
4
|
-
module Configuration
|
5
|
-
extend self
|
6
|
-
end
|
7
|
-
|
8
|
-
module Env
|
9
|
-
extend self
|
10
|
-
|
11
|
-
def development?
|
12
|
-
false
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
module Application
|
17
|
-
extend self
|
18
|
-
|
19
|
-
module Assets
|
20
|
-
extend self
|
21
|
-
end
|
22
|
-
|
23
|
-
def assets
|
24
|
-
Assets
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
class Railtie
|
29
|
-
class Configuration
|
30
|
-
def after_initialize
|
31
|
-
yield
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.config
|
36
|
-
Configuration.new
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def env
|
41
|
-
Env
|
42
|
-
end
|
43
|
-
|
44
|
-
def configuration
|
45
|
-
Configuration
|
46
|
-
end
|
47
|
-
|
48
|
-
def application
|
49
|
-
Application
|
50
|
-
end
|
51
|
-
end
|