premailer-rails 1.5.1 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +11 -1
- data/CHANGELOG.md +16 -0
- data/Gemfile +10 -0
- data/README.md +82 -40
- data/VERSION +1 -1
- data/lib/premailer/rails.rb +1 -2
- data/lib/premailer/rails/css_helper.rb +8 -20
- data/lib/premailer/rails/css_loaders.rb +4 -63
- data/lib/premailer/rails/css_loaders/asset_pipeline_loader.rb +27 -0
- data/lib/premailer/rails/css_loaders/cache_loader.rb +19 -0
- data/lib/premailer/rails/css_loaders/file_system_loader.rb +15 -0
- data/lib/premailer/rails/css_loaders/network_loader.rb +32 -0
- data/lib/premailer/rails/hook.rb +12 -3
- data/premailer-rails.gemspec +4 -6
- data/spec/integration/css_helper_spec.rb +168 -0
- data/spec/{lib → integration}/hook_registration_spec.rb +2 -3
- data/spec/{lib → integration}/hook_spec.rb +26 -10
- data/spec/spec_helper.rb +17 -5
- data/spec/{fixtures → support/fixtures}/html.rb +0 -8
- data/spec/{fixtures → support/fixtures}/message.rb +0 -0
- data/spec/{stubs → support/stubs}/action_mailer.rb +0 -0
- data/spec/{stubs → support/stubs}/rails.rb +0 -26
- data/spec/unit/css_loaders/asset_pipeline_loader_spec.rb +30 -0
- data/spec/{lib → unit}/customized_premailer_spec.rb +12 -13
- data/spec/{lib/premailer_rails_3_spec.rb → unit/premailer_rails_spec.rb} +0 -0
- metadata +44 -56
- data/spec/lib/css_helper_spec.rb +0 -164
- data/spec/stubs/dummy.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a2073ed1c61cca54326ea63233c597afc05673a
|
4
|
+
data.tar.gz: 8a067a0516b3ff404ead0d70b147408a0ca88dea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 613d3feeeceb8be28f49e32c656b945d98ce23b6b22ef597e063a519a3e798e250e8ae80fe0a2bcd700acd6ee6b13efbdf92bf9813266c61aa0ef147d9fc4e45
|
7
|
+
data.tar.gz: 869483a1f22ae2e38587eb73f763fa11f430271c74a30f0ebdbb08164893113dd962027b43524abec789467481209e764d98cfb4798305b1c9662975a5ed8fa2
|
data/.travis.yml
CHANGED
@@ -1,8 +1,18 @@
|
|
1
1
|
language: ruby
|
2
|
+
cache: bundler
|
2
3
|
script: "bundle exec rspec"
|
3
4
|
rvm:
|
4
5
|
- 2.0.0
|
5
6
|
- 1.9.3
|
7
|
+
- ruby-head
|
6
8
|
- jruby-19mode
|
7
9
|
- rbx-19mode
|
8
|
-
env:
|
10
|
+
env:
|
11
|
+
- "ACTION_MAILER_VERSION=3.1.0"
|
12
|
+
- "ACTION_MAILER_VERSION=3.2.0"
|
13
|
+
- "ACTION_MAILER_VERSION=4.0.0"
|
14
|
+
- "ACTION_MAILER_VERSION=head"
|
15
|
+
matrix:
|
16
|
+
allow_failures:
|
17
|
+
- env: "ACTION_MAILER_VERSION=head"
|
18
|
+
- rvm: ruby-head
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## v1.6.0
|
4
|
+
|
5
|
+
- Only use asset pipeline if Rails is defined and if compile is true
|
6
|
+
|
7
|
+
- Depend on actionmailer instead of rails
|
8
|
+
|
9
|
+
- Check whether `::Rails` is defined before using it
|
10
|
+
|
11
|
+
- Add ability to skip premailer
|
12
|
+
|
13
|
+
- Test against multiple action mailer versions on travis
|
14
|
+
|
15
|
+
- Ensure CSS strings are always UTF-8 encoded
|
16
|
+
|
17
|
+
- Require premailer version >= 1.7.9
|
18
|
+
|
3
19
|
## v1.5.1
|
4
20
|
|
5
21
|
- Prefer precompiled assets over asset pipeline
|
data/Gemfile
CHANGED
@@ -2,6 +2,16 @@ source "https://rubygems.org"
|
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
|
+
action_mailer_version = ENV.fetch('ACTION_MAILER_VERSION', '4.0')
|
6
|
+
|
7
|
+
if action_mailer_version == 'head'
|
8
|
+
git 'git://github.com/rails/rails.git' do
|
9
|
+
gem 'actionmailer'
|
10
|
+
end
|
11
|
+
else
|
12
|
+
gem 'actionmailer', "~> #{action_mailer_version}"
|
13
|
+
end
|
14
|
+
|
5
15
|
platforms :jruby do
|
6
16
|
gem "jruby-openssl"
|
7
17
|
end
|
data/README.md
CHANGED
@@ -1,78 +1,120 @@
|
|
1
1
|
# premailer-rails
|
2
2
|
|
3
|
-
|
4
|
-
[![Gem Version](https://badge.fury.io/rb/premailer-rails.png)](http://badge.fury.io/rb/premailer-rails)
|
5
|
-
[![Dependency Status](https://gemnasium.com/fphilipe/premailer-rails.png)](https://gemnasium.com/fphilipe/premailer-rails)
|
6
|
-
[![Code Climate](https://codeclimate.com/github/fphilipe/premailer-rails.png)](https://codeclimate.com/github/fphilipe/premailer-rails)
|
3
|
+
CSS styled emails without the hassle.
|
7
4
|
|
8
|
-
|
9
|
-
|
5
|
+
[![Build Status][build-image]][build-link]
|
6
|
+
[![Gem Version][gem-image]][gem-link]
|
7
|
+
[![Dependency Status][deps-image]][deps-link]
|
8
|
+
[![Code Climate][gpa-image]][gpa-link]
|
9
|
+
[![Coverage Status][cov-image]][cov-link]
|
10
|
+
[![Bitdeli Badge][stats-image]][stats-link]
|
10
11
|
|
11
|
-
|
12
|
+
## Introduction
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
```
|
14
|
+
This gem is a drop in solution for styling HTML emails with CSS without having
|
15
|
+
to do the hard work yourself.
|
16
16
|
|
17
|
-
|
17
|
+
Styling emails is not just a matter of linking to a stylesheet. Most clients,
|
18
|
+
especially web clients, ignore linked stylesheets or `<style>` tags in the HTML.
|
19
|
+
The workaround is to write all the CSS rules in the `style` attribute of each
|
20
|
+
tag inside your email. This is a rather tedious and hard to maintain approach.
|
18
21
|
|
19
|
-
The
|
22
|
+
Premailer to the rescue! The great [premailer] gem applies all CSS rules to each
|
23
|
+
matching HTML element by adding them to the `style` attribute. This allows you
|
24
|
+
to keep HTML and CSS in separate files, just as you're used to from web
|
25
|
+
development, thus keeping your sanity.
|
20
26
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
27
|
+
This gem is an adapter for premailer to work with [actionmailer] out of the box.
|
28
|
+
Actionmailer is the email framework used in Rails, which also works outside of
|
29
|
+
Rails. Although premailer-rails has certain Rails specific features, **it also
|
30
|
+
works in the absence of Rails** making it compatible with other frameworks such
|
31
|
+
as sinatra.
|
25
32
|
|
26
|
-
|
27
|
-
|
33
|
+
premailer-rails works with actionmailer by registering a delivery hook. This
|
34
|
+
causes all emails that are delivered to be processed by premailer-rails. This
|
35
|
+
means that, by simply including premailer-rails in your `Gemfile`, you'll get
|
36
|
+
styled emails without having to set anything up.
|
28
37
|
|
29
38
|
## Installation
|
30
39
|
|
31
|
-
Simply add the gem to your Gemfile
|
40
|
+
Simply add the gem to your `Gemfile`:
|
32
41
|
|
33
|
-
|
42
|
+
```ruby
|
43
|
+
gem 'premailer-rails'
|
44
|
+
```
|
34
45
|
|
35
|
-
premailer-rails requires either nokogiri or hpricot. It doesn't list them as
|
46
|
+
premailer-rails requires either [nokogiri] or [hpricot]. It doesn't list them as
|
47
|
+
a dependency so you can choose which one to use. Since hpricot is no longer
|
48
|
+
maintained, I suggest you to go with nokogiri. Add either one to your `Gemfile`:
|
36
49
|
|
37
|
-
|
38
|
-
|
39
|
-
|
50
|
+
```ruby
|
51
|
+
gem 'nokogiri'
|
52
|
+
# or
|
53
|
+
gem 'hpricot'
|
54
|
+
```
|
40
55
|
|
41
|
-
If both are loaded for some reason, premailer chooses hpricot.
|
56
|
+
If both gems are loaded for some reason, premailer chooses hpricot.
|
42
57
|
|
43
58
|
That's it!
|
44
59
|
|
45
60
|
## Configuration
|
46
61
|
|
47
62
|
Premailer itself accepts a number of options. In order for premailer-rails to
|
48
|
-
pass these options on to the underlying premailer instance, specify them
|
49
|
-
initializer
|
63
|
+
pass these options on to the underlying premailer instance, specify them
|
64
|
+
as follows (in Rails you could do that in an initializer such as
|
65
|
+
`config/initializers/premailer_rails.rb`):
|
50
66
|
|
51
67
|
```ruby
|
52
|
-
Premailer::Rails.config.merge!(preserve_styles: true,
|
53
|
-
remove_ids: true)
|
68
|
+
Premailer::Rails.config.merge!(preserve_styles: true, remove_ids: true)
|
54
69
|
```
|
55
70
|
|
56
|
-
For a list of options, refer to the [
|
57
|
-
|
58
|
-
The default configs are:
|
71
|
+
For a list of options, refer to the [premailer documentation]. The default
|
72
|
+
configs are:
|
59
73
|
|
60
74
|
```ruby
|
61
75
|
{
|
62
|
-
input_encoding:
|
63
|
-
inputencoding: 'UTF-8',
|
76
|
+
input_encoding: 'UTF-8',
|
64
77
|
generate_text_part: true
|
65
78
|
}
|
66
79
|
```
|
67
80
|
|
68
|
-
|
69
|
-
|
70
|
-
If you want to use another encoding make sure to specify the right one or both.
|
81
|
+
If you don't want to automatically generate a text part from the html part, set
|
82
|
+
the config `:generate_text_part` to false.
|
71
83
|
|
72
|
-
|
84
|
+
Note that the options `:with_html_string` and `:css_string` are used internally
|
85
|
+
by premailer-rails and thus will be overridden.
|
73
86
|
|
74
|
-
|
87
|
+
## Usage
|
75
88
|
|
89
|
+
premailer-rails processes all outgoing emails by default. If you wish to skip
|
90
|
+
premailer for a certain email, simply set the `:skip_premailer` header:
|
76
91
|
|
77
|
-
|
92
|
+
```ruby
|
93
|
+
class UserMailer < ActionMailer::Base
|
94
|
+
def welcome_email(user)
|
95
|
+
mail to: user.email,
|
96
|
+
subject: 'Welcome to My Awesome Site',
|
97
|
+
skip_premailer: true
|
98
|
+
end
|
99
|
+
end
|
100
|
+
```
|
78
101
|
|
102
|
+
[build-image]: https://travis-ci.org/fphilipe/premailer-rails.png
|
103
|
+
[build-link]: https://travis-ci.org/fphilipe/premailer-rails
|
104
|
+
[gem-image]: https://badge.fury.io/rb/premailer-rails.png
|
105
|
+
[gem-link]: https://rubygems.org/gems/premailer-rails
|
106
|
+
[deps-image]: https://gemnasium.com/fphilipe/premailer-rails.png
|
107
|
+
[deps-link]: https://gemnasium.com/fphilipe/premailer-rails
|
108
|
+
[gpa-image]: https://codeclimate.com/github/fphilipe/premailer-rails.png
|
109
|
+
[gpa-link]: https://codeclimate.com/github/fphilipe/premailer-rails
|
110
|
+
[cov-image]: https://coveralls.io/repos/fphilipe/premailer-rails/badge.png
|
111
|
+
[cov-link]: https://coveralls.io/r/fphilipe/premailer-rails
|
112
|
+
[stats-image]: https://d2weczhvl823v0.cloudfront.net/fphilipe/premailer-rails/trend.png
|
113
|
+
[stats-link]: https://bitdeli.com/
|
114
|
+
|
115
|
+
[premailer]: https://github.com/premailer/premailer
|
116
|
+
[actionmailer]: https://github.com/rails/rails/tree/master/actionmailer
|
117
|
+
[nokogiri]: https://github.com/sparklemotion/nokogiri
|
118
|
+
[hpricot]: https://github.com/hpricot/hpricot
|
119
|
+
|
120
|
+
[premailer documentation]: http://rubydoc.info/gems/premailer/1.7.3/Premailer:initialize
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.6.0
|
data/lib/premailer/rails.rb
CHANGED
@@ -9,13 +9,14 @@ class Premailer
|
|
9
9
|
STRATEGIES = [
|
10
10
|
CSSLoaders::CacheLoader,
|
11
11
|
CSSLoaders::FileSystemLoader,
|
12
|
-
CSSLoaders::AssetPipelineLoader
|
12
|
+
CSSLoaders::AssetPipelineLoader,
|
13
|
+
CSSLoaders::NetworkLoader
|
13
14
|
]
|
14
15
|
|
15
16
|
# Returns all linked CSS files concatenated as string.
|
16
17
|
def css_for_doc(doc)
|
17
18
|
urls = css_urls_in_doc(doc)
|
18
|
-
urls.map { |url| load_css(url) }.join("\n")
|
19
|
+
urls.map { |url| load_css(url).force_encoding('UTF-8') }.join("\n")
|
19
20
|
end
|
20
21
|
|
21
22
|
private
|
@@ -27,24 +28,11 @@ class Premailer
|
|
27
28
|
end
|
28
29
|
|
29
30
|
def load_css(url)
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# Extracts the path of a url.
|
39
|
-
def extract_path(url)
|
40
|
-
if url.is_a? String
|
41
|
-
# Remove everything after ? including ?
|
42
|
-
url = url[0..(url.index('?') - 1)] if url.include? '?'
|
43
|
-
# Remove the host
|
44
|
-
url = url.sub(/^https?\:\/\/[^\/]*/, '') if url.index('http') == 0
|
45
|
-
end
|
46
|
-
|
47
|
-
url
|
31
|
+
@cache[url] =
|
32
|
+
STRATEGIES.each do |strategy|
|
33
|
+
css = strategy.load(url)
|
34
|
+
break css if css
|
35
|
+
end
|
48
36
|
end
|
49
37
|
end
|
50
38
|
end
|
@@ -1,65 +1,6 @@
|
|
1
1
|
require 'uri'
|
2
|
-
require 'zlib'
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
module CacheLoader
|
9
|
-
extend self
|
10
|
-
|
11
|
-
def load(path)
|
12
|
-
unless ::Rails.env.development?
|
13
|
-
CSSHelper.cache[path]
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
# Loads the CSS from the asset pipeline.
|
19
|
-
module AssetPipelineLoader
|
20
|
-
extend self
|
21
|
-
|
22
|
-
def load(path)
|
23
|
-
if assets_enabled?
|
24
|
-
file = file_name(path)
|
25
|
-
if asset = ::Rails.application.assets.find_asset(file)
|
26
|
-
asset.to_s
|
27
|
-
else
|
28
|
-
Net::HTTP.get(uri_for_path(path))
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def assets_enabled?
|
34
|
-
::Rails.configuration.assets.enabled rescue false
|
35
|
-
end
|
36
|
-
|
37
|
-
def file_name(path)
|
38
|
-
path
|
39
|
-
.sub("#{::Rails.configuration.assets.prefix}/", '')
|
40
|
-
.sub(/-\h{32}\.css$/, '.css')
|
41
|
-
end
|
42
|
-
|
43
|
-
def uri_for_path(path)
|
44
|
-
URI(path).tap do |uri|
|
45
|
-
scheme, host =
|
46
|
-
::Rails.configuration.action_controller.asset_host.split(%r{:?//})
|
47
|
-
scheme = 'http' if scheme.blank?
|
48
|
-
uri.scheme ||= scheme
|
49
|
-
uri.host ||= host
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
# Loads the CSS from the file system.
|
55
|
-
module FileSystemLoader
|
56
|
-
extend self
|
57
|
-
|
58
|
-
def load(path)
|
59
|
-
file_path = "#{::Rails.root}/public#{path}"
|
60
|
-
File.read(file_path) if File.exist?(file_path)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
3
|
+
require 'premailer/rails/css_loaders/cache_loader'
|
4
|
+
require 'premailer/rails/css_loaders/file_system_loader'
|
5
|
+
require 'premailer/rails/css_loaders/asset_pipeline_loader'
|
6
|
+
require 'premailer/rails/css_loaders/network_loader'
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class Premailer
|
2
|
+
module Rails
|
3
|
+
module CSSLoaders
|
4
|
+
module AssetPipelineLoader
|
5
|
+
extend self
|
6
|
+
|
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
|
14
|
+
|
15
|
+
def asset_pipeline_present?
|
16
|
+
defined?(::Rails) and ::Rails.application.respond_to?(:assets)
|
17
|
+
end
|
18
|
+
|
19
|
+
def file_name(url)
|
20
|
+
URI(url).path
|
21
|
+
.sub("#{::Rails.configuration.assets.prefix}/", '')
|
22
|
+
.sub(/-\h{32}\.css$/, '.css')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Premailer
|
2
|
+
module Rails
|
3
|
+
module CSSLoaders
|
4
|
+
module CacheLoader
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def load(url)
|
8
|
+
unless development_env?
|
9
|
+
CSSHelper.cache[url]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def development_env?
|
14
|
+
defined?(::Rails) and ::Rails.env.development?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Premailer
|
2
|
+
module Rails
|
3
|
+
module CSSLoaders
|
4
|
+
module NetworkLoader
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def load(url)
|
8
|
+
uri = uri_for_url(url)
|
9
|
+
Net::HTTP.get(uri) if uri
|
10
|
+
end
|
11
|
+
|
12
|
+
def uri_for_url(url)
|
13
|
+
uri = URI(url)
|
14
|
+
|
15
|
+
if not valid_uri?(uri) and defined?(::Rails)
|
16
|
+
scheme, host =
|
17
|
+
::Rails.configuration.action_controller.asset_host.split(%r{:?//})
|
18
|
+
scheme = 'http' if scheme.blank?
|
19
|
+
uri.scheme ||= scheme
|
20
|
+
uri.host ||= host
|
21
|
+
end
|
22
|
+
|
23
|
+
uri if valid_uri?(uri)
|
24
|
+
end
|
25
|
+
|
26
|
+
def valid_uri?(uri)
|
27
|
+
uri.host.present? && uri.scheme.present?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|