premailer-rails3 1.3.1 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a17a57069bfce9809df15e905f26bb4ab2721e25
4
+ data.tar.gz: 7ba91f1ffa9c5073f5146ed5249eef1560114eb8
5
+ SHA512:
6
+ metadata.gz: d922dfeb7c62cb82b9a61be651a5ccee3f98614ef747d289505351dd17f17ead55cbe84dae559fa3e53e8fe3afb8d11662c04958639435e10ab00b17a3ff40e8
7
+ data.tar.gz: 22daec1ea1a916420a146d6d79f516f983ad2e45ba2462e56fd6b51e96b83bdafb79ec5657fbd6b38f459f225135a469cd866b2c1581197208ee8544afae5635
@@ -1,8 +1,10 @@
1
1
  language: ruby
2
+ script: "bundle exec rspec"
2
3
  rvm:
4
+ - 2.0.0
3
5
  - 1.9.3
6
+ - 1.8.7
4
7
  - jruby-18mode # JRuby in 1.8 mode
5
8
  - jruby-19mode # JRuby in 1.9 mode
6
9
  - rbx-18mode
7
10
  - rbx-19mode
8
- - 1.8.7
data/Gemfile CHANGED
@@ -2,3 +2,7 @@ source "http://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in premailer-rails3.gemspec
4
4
  gemspec
5
+
6
+ platforms :jruby do
7
+ gem "jruby-openssl"
8
+ end
data/README.md CHANGED
@@ -1,9 +1,12 @@
1
- # premailer-rails3
1
+ # premailer-rails
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/fphilipe/premailer-rails3.png?branch=master)](http://travis-ci.org/fphilipe/premailer-rails3) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/fphilipe/premailer-rails3)
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)
4
7
 
5
8
  This gem is a no config solution for the wonderful
6
- [Premailer gem](https://github.com/alexdunae/premailer) to be used with Rails 3.
9
+ [Premailer gem](https://github.com/alexdunae/premailer) to be used with Rails.
7
10
  It uses interceptors which were introduced in Rails 3 and tweaks all mails which
8
11
  are `deliver`ed and adds a plain text part to them and inlines all CSS rules
9
12
  into the HTML part.
@@ -16,11 +19,8 @@ By default it inlines all the CSS files that are linked to in the HTML:
16
19
 
17
20
  Don't worry about the host in the CSS URL since this will be ignored.
18
21
 
19
- If no CSS file is linked to in the HTML and no inline `<style type="text/css">`
20
- is presnet, it will try to load a default CSS file `email.css`.
21
-
22
- Every CSS file (including the default `email.css`) is loaded from within the
23
- app. The retrieval of the file depends on your assets configuration:
22
+ Every CSS file is loaded from within the app.
23
+ The retrieval of the file depends on your assets configuration:
24
24
 
25
25
  * Rails 3.1 asset pipeline: It will load the compiled version of the CSS asset
26
26
  which is normally located in `app/assets/stylesheets/`. If the asset can't be
@@ -38,9 +38,9 @@ app. The retrieval of the file depends on your assets configuration:
38
38
 
39
39
  Simply add the gem to your Gemfile in your Rails project:
40
40
 
41
- gem 'premailer-rails3'
41
+ gem 'premailer-rails'
42
42
 
43
- premailer-rails3 requires either nokogiri or hpricot. It doesn't list them as a
43
+ premailer-rails requires either nokogiri or hpricot. It doesn't list them as a
44
44
  dependency so you can choose which one to use.
45
45
 
46
46
  gem 'nokogiri'
@@ -53,13 +53,13 @@ That's it!
53
53
 
54
54
  ## Configuration
55
55
 
56
- Premailer itself accepts a number of options. In order for premailer-rails3 to
56
+ Premailer itself accepts a number of options. In order for premailer-rails to
57
57
  pass these options on to the underlying premailer instance, specify them in an
58
58
  initializer:
59
59
 
60
60
  ```ruby
61
- PremailerRails.config.merge!(:preserve_styles => true,
62
- :remove_ids => true)
61
+ Premailer::Rails.config.merge!(:preserve_styles => true,
62
+ :remove_ids => true)
63
63
  ```
64
64
 
65
65
  For a list of options, refer to the [Premailer documentation](http://rubydoc.info/gems/premailer/1.7.3/Premailer:initialize)
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.3.2
@@ -0,0 +1,23 @@
1
+ require 'premailer'
2
+ require 'action_mailer'
3
+
4
+ require 'premailer/rails/css_loaders'
5
+ require 'premailer/rails/css_helper'
6
+ require 'premailer/rails/customized_premailer'
7
+ require 'premailer/rails/hook'
8
+ require 'premailer/rails/nokogiri_fix'
9
+
10
+ class Premailer
11
+ module Rails
12
+ @config = {
13
+ :input_encoding => 'UTF-8',
14
+ :inputencoding => 'UTF-8',
15
+ :generate_text_part => true
16
+ }
17
+ class << self
18
+ attr_accessor :config
19
+ end
20
+ end
21
+ end
22
+
23
+ ActionMailer::Base.register_interceptor(Premailer::Rails::Hook)
@@ -0,0 +1,58 @@
1
+ require 'open-uri'
2
+ require 'zlib'
3
+
4
+ class Premailer
5
+ module Rails
6
+ module CSSHelper
7
+ extend self
8
+
9
+ @cache = {}
10
+ attr :cache
11
+
12
+ STRATEGIES = [
13
+ CSSLoaders::CacheLoader,
14
+ CSSLoaders::AssetPipelineLoader,
15
+ CSSLoaders::FileSystemLoader
16
+ ]
17
+
18
+ # Returns all linked CSS files concatenated as string.
19
+ def css_for_doc(doc)
20
+ urls = css_urls_in_doc(doc)
21
+ urls.map { |url| load_css(url) }.join("\n")
22
+ end
23
+
24
+ private
25
+
26
+ def css_urls_in_doc(doc)
27
+ doc.search('link[@type="text/css"]').map do |link|
28
+ link.attributes['href'].to_s
29
+ end
30
+ end
31
+
32
+ def has_inline_css?(doc)
33
+ not doc.search('style[@type="text/css"]').empty?
34
+ end
35
+
36
+ def load_css(url)
37
+ path = extract_path(url)
38
+
39
+ @cache[path] = STRATEGIES.each do |strategy|
40
+ css = strategy.load(path)
41
+ break css if css
42
+ end
43
+ end
44
+
45
+ # Extracts the path of a url.
46
+ def extract_path(url)
47
+ if url.is_a? String
48
+ # Remove everything after ? including ?
49
+ url = url[0..(url.index('?') - 1)] if url.include? '?'
50
+ # Remove the host
51
+ url = url.sub(/^https?\:\/\/[^\/]*/, '') if url.index('http') == 0
52
+ end
53
+
54
+ url
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,66 @@
1
+ class Premailer
2
+ module Rails
3
+ module CSSLoaders
4
+ # Loads the CSS from cache when not in development env.
5
+ module CacheLoader
6
+ extend self
7
+
8
+ def load(path)
9
+ unless ::Rails.env.development?
10
+ CSSHelper.cache[path]
11
+ end
12
+ end
13
+ end
14
+
15
+ # Loads the CSS from the asset pipeline.
16
+ module AssetPipelineLoader
17
+ extend self
18
+
19
+ def load(path)
20
+ if assets_enabled?
21
+ file = file_name(path)
22
+ if asset = ::Rails.application.assets.find_asset(file)
23
+ asset.to_s
24
+ else
25
+ request_and_unzip(file)
26
+ end
27
+ end
28
+ end
29
+
30
+ def assets_enabled?
31
+ ::Rails.configuration.assets.enabled rescue false
32
+ end
33
+
34
+ def file_name(path)
35
+ path.sub("#{::Rails.configuration.assets.prefix}/", '') \
36
+ .sub(/-.*\.css$/, '.css')
37
+ end
38
+
39
+ def request_and_unzip(file)
40
+ url = [
41
+ ::Rails.configuration.action_controller.asset_host,
42
+ ::Rails.configuration.assets.prefix.sub(/^\//, ''),
43
+ ::Rails.configuration.assets.digests[file]
44
+ ].join('/')
45
+ response = Kernel.open(url)
46
+
47
+ begin
48
+ Zlib::GzipReader.new(response).read
49
+ rescue Zlib::GzipFile::Error, Zlib::Error
50
+ response.rewind
51
+ response.read
52
+ end
53
+ end
54
+ end
55
+
56
+ # Loads the CSS from the file system.
57
+ module FileSystemLoader
58
+ extend self
59
+
60
+ def load(path)
61
+ File.read("#{::Rails.root}/public#{path}")
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,20 @@
1
+ class Premailer
2
+ module Rails
3
+ class CustomizedPremailer < ::Premailer
4
+ def initialize(html)
5
+ # In order to pass the CSS as string to super it is necessary to access
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.
11
+ @options = Rails.config.merge(:with_html_string => true)
12
+ Premailer.send(:include, Adapter.find(Adapter.use))
13
+ doc = load_html(html)
14
+
15
+ options = @options.merge(:css_string => CSSHelper.css_for_doc(doc))
16
+ super(html, options)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,45 @@
1
+ class Premailer
2
+ module Rails
3
+ class Hook
4
+ def self.delivering_email(message)
5
+ # If the mail only has one part, it may be stored in message.body. In that
6
+ # case, if the mail content type is text/html, the body part will be the
7
+ # html body.
8
+ if message.html_part
9
+ html_body = message.html_part.body.to_s
10
+ needs_multipart = true
11
+ message.parts.delete(message.html_part)
12
+ elsif message.content_type =~ /text\/html/
13
+ html_body = message.body.to_s
14
+ message.body = nil
15
+ needs_multipart = Rails.config[:generate_text_part]
16
+ end
17
+
18
+ if html_body
19
+ premailer = CustomizedPremailer.new(html_body)
20
+ charset = message.charset
21
+
22
+ if needs_multipart
23
+ # IMPORTANT: Plain text part must be generated before CSS is inlined.
24
+ # Not doing so results in CSS declarations visible in the plain text
25
+ # part.
26
+ if Rails.config[:generate_text_part] \
27
+ and not message.text_part
28
+ message.text_part do
29
+ content_type "text/plain; charset=#{charset}"
30
+ body premailer.to_plain_text
31
+ end
32
+ end
33
+
34
+ message.html_part do
35
+ content_type "text/html; charset=#{charset}"
36
+ body premailer.to_inline_css
37
+ end
38
+ else
39
+ message.body = premailer.to_inline_css
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,13 @@
1
+ require 'premailer/adapter/nokogiri'
2
+
3
+ Premailer::Adapter::Nokogiri.module_eval do
4
+ # Patch load_html method to fix character encoding issues.
5
+ def load_html(html)
6
+ if RUBY_VERSION.to_f >= 1.9
7
+ html = html.force_encoding('UTF-8').encode!
8
+ ::Nokogiri::HTML(html) {|c| c.recover }
9
+ else
10
+ ::Nokogiri::HTML(html, nil, 'UTF-8') {|c| c.recover }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ class Premailer
2
+ module Rails
3
+ class CustomizedPremailer < ::Premailer
4
+ def initialize(html)
5
+ # In order to pass the CSS as string to super it is necessary to access
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.
11
+ @options = Rails.config.merge(:with_html_string => true)
12
+ Premailer.send(:include, Adapter.find(Adapter.use))
13
+ doc = load_html(html)
14
+
15
+ options = @options.merge(:css_string => CSSHelper.css_for_doc(doc))
16
+ super(html, options)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ class Premailer
2
+ module Rails
3
+ VERSION = File.read(
4
+ File.expand_path('../../../../VERSION', __FILE__)
5
+ ).strip
6
+ end
7
+ end
@@ -0,0 +1,23 @@
1
+ require 'premailer'
2
+ require 'action_mailer'
3
+
4
+ require 'premailer/rails/css_loaders'
5
+ require 'premailer/rails/css_helper'
6
+ require 'premailer/rails/customized_premailer'
7
+ require 'premailer/rails/hook'
8
+ require 'premailer/rails/nokogiri_fix'
9
+
10
+ class Premailer
11
+ module Rails
12
+ @config = {
13
+ :input_encoding => 'UTF-8',
14
+ :inputencoding => 'UTF-8',
15
+ :generate_text_part => true
16
+ }
17
+ class << self
18
+ attr_accessor :config
19
+ end
20
+ end
21
+ end
22
+
23
+ ActionMailer::Base.register_interceptor(Premailer::Rails::Hook)
@@ -1,29 +1,30 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  $:.push File.expand_path("../lib", __FILE__)
3
- require "premailer-rails3/version"
3
+ require "premailer/rails/version"
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "premailer-rails3"
7
- s.version = PremailerRails::VERSION
7
+ s.version = Premailer::Rails::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ["Philipe Fatio"]
10
10
  s.email = ["philipe.fatio@gmail.com"]
11
- s.homepage = "https://github.com/fphilipe/premailer-rails3"
12
- s.summary = %q{Easily create HTML emails in Rails 3.}
13
- s.description = %q{This gem brings you the power of the premailer gem to Rails 3
14
- without any configuration needs. Create HTML emails, include a
15
- CSS file as you do in a normal HTML document and premailer will
16
- inline the included CSS.}
11
+ s.homepage = "https://github.com/fphilipe/premailer-rails"
12
+ s.summary = %q{Easily create styled HTML emails in Rails.}
13
+ s.description = %q{This gem brings you the power of the premailer gem to Rails
14
+ without any configuration needs. Create HTML emails,
15
+ include a CSS file as you do in a normal HTML document and
16
+ premailer will inline the included CSS.}
17
17
 
18
- s.rubyforge_project = "premailer-rails3"
19
-
20
- s.files = `git ls-files`.split("\n")
18
+ files = `git ls-files`.split("\n")
19
+ files.delete('premailer-rails.gemspec')
20
+ files.push('premailer-rails3.gemspec')
21
+ s.files = files
21
22
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
23
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
24
  s.require_paths = ["lib"]
24
25
 
25
26
  s.add_dependency("premailer", ["~> 1.7"])
26
- s.add_dependency("rails", ["~> 3"])
27
+ s.add_dependency("rails", [">= 3"])
27
28
 
28
29
  s.add_development_dependency 'rspec-core'
29
30
  s.add_development_dependency 'rspec-expectations'
@@ -31,4 +32,6 @@ Gem::Specification.new do |s|
31
32
  s.add_development_dependency 'mail'
32
33
  s.add_development_dependency 'nokogiri'
33
34
  s.add_development_dependency 'hpricot'
35
+
36
+ s.post_install_message = 'This gem has been renamed to premailer-rails. This is the last version that is released under the old name. Please change this in your Gemfile.'
34
37
  end
@@ -1,15 +1,15 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe PremailerRails::CSSHelper do
3
+ describe Premailer::Rails::CSSHelper do
4
4
  # Reset the CSS cache
5
- after { PremailerRails::CSSHelper.send(:instance_variable_set, '@cache', {}) }
5
+ after { Premailer::Rails::CSSHelper.send(:instance_variable_set, '@cache', {}) }
6
6
 
7
7
  def load_css(path)
8
- PremailerRails::CSSHelper.send(:load_css, path)
8
+ Premailer::Rails::CSSHelper.send(:load_css, path)
9
9
  end
10
10
 
11
11
  def css_for_doc(doc)
12
- PremailerRails::CSSHelper.css_for_doc(doc)
12
+ Premailer::Rails::CSSHelper.css_for_doc(doc)
13
13
  end
14
14
 
15
15
  describe '#css_for_doc' do
@@ -20,11 +20,11 @@ describe PremailerRails::CSSHelper do
20
20
  let(:files) { %w[ stylesheets/base.css stylesheets/font.css ] }
21
21
 
22
22
  it 'should return the content of both files concatenated' do
23
- PremailerRails::CSSHelper \
23
+ Premailer::Rails::CSSHelper \
24
24
  .expects(:load_css) \
25
25
  .with('http://example.com/stylesheets/base.css') \
26
26
  .returns('content of base.css')
27
- PremailerRails::CSSHelper \
27
+ Premailer::Rails::CSSHelper \
28
28
  .expects(:load_css) \
29
29
  .with('http://example.com/stylesheets/font.css') \
30
30
  .returns('content of font.css')
@@ -32,34 +32,6 @@ describe PremailerRails::CSSHelper do
32
32
  css_for_doc(doc).should == "content of base.css\ncontent of font.css"
33
33
  end
34
34
  end
35
-
36
- context 'when HTML contains style tag' do
37
- let(:files) { [] }
38
- let(:html) { Fixtures::HTML.with_style_block }
39
-
40
- it 'should not load the default file' do
41
- PremailerRails::CSSHelper \
42
- .expects(:load_css) \
43
- .with(:default) \
44
- .never
45
-
46
- css_for_doc(doc).should be_nil
47
- end
48
- end
49
-
50
- context 'when HTML contains no linked CSS file nor style block tag' do
51
- let(:files) { [] }
52
- let(:html) { Fixtures::HTML.with_no_css_link }
53
-
54
- it 'should load the default file' do
55
- PremailerRails::CSSHelper \
56
- .expects(:load_css) \
57
- .with(:default) \
58
- .returns('content of default css')
59
-
60
- css_for_doc(doc).should == 'content of default css'
61
- end
62
- end
63
35
  end
64
36
 
65
37
  describe '#load_css' do
@@ -81,7 +53,8 @@ describe PremailerRails::CSSHelper do
81
53
 
82
54
  context 'when file is cached' do
83
55
  it 'should return the cached value' do
84
- cache = PremailerRails::CSSHelper.send(:instance_variable_get, '@cache')
56
+ cache =
57
+ Premailer::Rails::CSSHelper.send(:instance_variable_get, '@cache')
85
58
  cache['/stylesheets/base.css'] = 'content of base.css'
86
59
 
87
60
  load_css('http://example.com/stylesheets/base.css') \
@@ -91,7 +64,8 @@ describe PremailerRails::CSSHelper do
91
64
 
92
65
  context 'when in development mode' do
93
66
  it 'should not return cached values' do
94
- cache = PremailerRails::CSSHelper.send(:instance_variable_get, '@cache')
67
+ cache =
68
+ Premailer::Rails::CSSHelper.send(:instance_variable_get, '@cache')
95
69
  cache['/stylesheets/base.css'] = 'cached content of base.css'
96
70
  File.expects(:read) \
97
71
  .with('RAILS_ROOT/public/stylesheets/base.css') \
@@ -103,29 +77,6 @@ describe PremailerRails::CSSHelper do
103
77
  end
104
78
  end
105
79
 
106
- context 'when Hassle is used' do
107
- before { Rails.configuration.middleware.stubs(:include?) \
108
- .with(Hassle) \
109
- .returns(true) }
110
-
111
- it 'should load email.css when the default CSS is requested' do
112
- File.expects(:read) \
113
- .with('RAILS_ROOT/tmp/hassle/stylesheets/email.css') \
114
- .returns('content of default css')
115
-
116
- load_css(:default).should == 'content of default css'
117
- end
118
-
119
- it 'should return the content of the file compiled by Hassle' do
120
- File.expects(:read) \
121
- .with('RAILS_ROOT/tmp/hassle/stylesheets/base.css') \
122
- .returns('content of base.css')
123
-
124
- load_css('http://example.com/stylesheets/base.css') \
125
- .should == 'content of base.css'
126
- end
127
- end
128
-
129
80
  context 'when Rails asset pipeline is used' do
130
81
  before {
131
82
  Rails.configuration.stubs(:assets).returns(
@@ -136,14 +87,6 @@ describe PremailerRails::CSSHelper do
136
87
  )
137
88
  }
138
89
 
139
- it 'should load email.css when the default CSS is requested' do
140
- Rails.application.assets.expects(:find_asset) \
141
- .with('email.css') \
142
- .returns(mock(:to_s => 'content of default css'))
143
-
144
- load_css(:default).should == 'content of default css'
145
- end
146
-
147
90
  it 'should return the content of the file compiled by Rails' do
148
91
  Rails.application.assets.expects(:find_asset) \
149
92
  .with('base.css') \
@@ -204,14 +147,6 @@ describe PremailerRails::CSSHelper do
204
147
  end
205
148
 
206
149
  context 'when static stylesheets are used' do
207
- it 'should load email.css when the default CSS is requested' do
208
- File.expects(:read) \
209
- .with('RAILS_ROOT/public/stylesheets/email.css') \
210
- .returns('content of default css')
211
-
212
- load_css(:default).should == 'content of default css'
213
- end
214
-
215
150
  it 'should return the content of the static file' do
216
151
  File.expects(:read) \
217
152
  .with('RAILS_ROOT/public/stylesheets/base.css') \