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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c14b05b4d57365b47366c6c56d7080ed7610bb0e
4
- data.tar.gz: 3bb5ba65597cc2fe6d40fc053785683ad0e08d69
3
+ metadata.gz: 5a2073ed1c61cca54326ea63233c597afc05673a
4
+ data.tar.gz: 8a067a0516b3ff404ead0d70b147408a0ca88dea
5
5
  SHA512:
6
- metadata.gz: af255aab35b0a2ebbbe9fc554d45bbf190878531ba2faef489cc88dcc4d1b40031713da7a21f8cdbbc1cdc49fdd8e96ca32ac2a3f439f40af4602fc3874c4bbc
7
- data.tar.gz: 7aed5714d084a540a096da8df6606894d68616dbcfe1de3fb9bdcaee3eeb61624c2f1377064a850c10c6e454926ef8fda3815fc8aaca635f1398b5bd4e8c2046
6
+ metadata.gz: 613d3feeeceb8be28f49e32c656b945d98ce23b6b22ef597e063a519a3e798e250e8ae80fe0a2bcd700acd6ee6b13efbdf92bf9813266c61aa0ef147d9fc4e45
7
+ data.tar.gz: 869483a1f22ae2e38587eb73f763fa11f430271c74a30f0ebdbb08164893113dd962027b43524abec789467481209e764d98cfb4798305b1c9662975a5ed8fa2
@@ -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: "JRUBY_OPTS=--debug"
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
@@ -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
- [![Build Status](https://travis-ci.org/fphilipe/premailer-rails.png)](https://travis-ci.org/fphilipe/premailer-rails)
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
- This gem is a no config solution for the wonderful [Premailer gem](https://github.com/alexdunae/premailer) to be used with Rails.
9
- It uses interceptors which were introduced in Rails 3 and tweaks all mails which are `deliver`ed and adds a plain text part to them and inlines all CSS rules into the HTML part.
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
- By default it inlines all inline `<style>` declarations and all the CSS files that are linked to in the HTML:
12
+ ## Introduction
12
13
 
13
- ```html
14
- <link rel="stylesheet" ... />
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
- Don't worry about the host in the CSS URL since this will be ignored.
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 retrieval of the file depends on your assets configuration:
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
- * Rails 3.1 asset pipeline: It will load the compiled version of the CSS asset
22
- which is normally located in `app/assets/stylesheets/`. If the asset can't be
23
- found (e.g. it is only available on a CDN and not locally), it will be
24
- HTTP requested.
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
- * Classic static assets: It will try to load the CSS file located in
27
- `public/stylesheets/`
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 in your Rails project:
40
+ Simply add the gem to your `Gemfile`:
32
41
 
33
- gem 'premailer-rails'
42
+ ```ruby
43
+ gem 'premailer-rails'
44
+ ```
34
45
 
35
- premailer-rails requires either nokogiri or hpricot. It doesn't list them as a dependency so you can choose which one to use.
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
- gem 'nokogiri'
38
- # or
39
- gem 'hpricot'
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 in an
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 [Premailer documentation](http://rubydoc.info/gems/premailer/1.7.3/Premailer:initialize)
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: 'UTF-8',
63
- inputencoding: 'UTF-8',
76
+ input_encoding: 'UTF-8',
64
77
  generate_text_part: true
65
78
  }
66
79
  ```
67
80
 
68
- The input encoding option [changed](https://github.com/alexdunae/premailer/commit/5f5cbb4ac181299a7e73d3eca11f3cf546585364) at some point.
69
- To make sure this option works regardless of the premailer version, the old and new setting is specified.
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
- If you don't want to automatically generate a text part from the html part, set the config `:generate_text_part` to false.
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
- Note that the options `:with_html_string` and `:css_string` are used internally and thus will be overridden.
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
- [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/fphilipe/premailer-rails/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
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.5.1
1
+ 1.6.0
@@ -11,8 +11,7 @@ require 'premailer/rails/nokogiri_fix'
11
11
  class Premailer
12
12
  module Rails
13
13
  @config = {
14
- input_encoding: 'UTF-8',
15
- inputencoding: 'UTF-8',
14
+ input_encoding: 'UTF-8',
16
15
  generate_text_part: true
17
16
  }
18
17
  class << self
@@ -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
- path = extract_path(url)
31
-
32
- @cache[path] = STRATEGIES.each do |strategy|
33
- css = strategy.load(path)
34
- break css if css
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
- class Premailer
5
- module Rails
6
- module CSSLoaders
7
- # Loads the CSS from cache when not in development env.
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,15 @@
1
+ class Premailer
2
+ module Rails
3
+ module CSSLoaders
4
+ module FileSystemLoader
5
+ extend self
6
+
7
+ def load(url)
8
+ path = URI(url).path
9
+ file_path = "public#{path}"
10
+ File.read(file_path) if File.exist?(file_path)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ 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