awesomemailer 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ 0.1.2
2
+ * Added support for @media queries and vendor prefixes
3
+ in the header. Should solve most issues w/CSS3 in
4
+ emails. Obviously it won't fix Outlook. Nothing can fix
5
+ Outlook.
6
+
1
7
  0.1.0
2
8
  * Full test coverage and moved to Nokogiri from Hpricot. Also
3
9
  added autoload so the gem is there when you need it but won't
data/Gemfile CHANGED
@@ -8,6 +8,7 @@ gem 'nokogiri', '>= 1.5.6'
8
8
  group :test do
9
9
  gem 'guard-rspec', require: false
10
10
  gem 'jeweler', require: false
11
+ gem 'pry'
11
12
  gem 'rspec', require: false
12
13
  gem 'simplecov', require: false
13
14
  end
data/Gemfile.lock CHANGED
@@ -22,6 +22,7 @@ GEM
22
22
  multi_json (~> 1.0)
23
23
  addressable (2.3.2)
24
24
  builder (3.0.4)
25
+ coderay (1.0.9)
25
26
  css_parser (1.2.6)
26
27
  addressable
27
28
  rdoc
@@ -47,10 +48,15 @@ GEM
47
48
  i18n (>= 0.4.0)
48
49
  mime-types (~> 1.16)
49
50
  treetop (~> 1.4.8)
51
+ method_source (0.8.1)
50
52
  mime-types (1.19)
51
53
  multi_json (1.3.7)
52
54
  nokogiri (1.5.6)
53
55
  polyglot (0.3.3)
56
+ pry (0.9.12)
57
+ coderay (~> 1.0.5)
58
+ method_source (~> 0.8)
59
+ slop (~> 3.4)
54
60
  rack (1.4.1)
55
61
  rack-cache (1.2)
56
62
  rack (>= 0.4)
@@ -71,6 +77,7 @@ GEM
71
77
  multi_json (~> 1.0)
72
78
  simplecov-html (~> 0.7.1)
73
79
  simplecov-html (0.7.1)
80
+ slop (3.4.4)
74
81
  sprockets (2.1.3)
75
82
  hike (~> 1.2)
76
83
  rack (~> 1.0)
@@ -91,5 +98,6 @@ DEPENDENCIES
91
98
  guard-rspec
92
99
  jeweler
93
100
  nokogiri (>= 1.5.6)
101
+ pry
94
102
  rspec
95
103
  simplecov
data/README.md CHANGED
@@ -8,90 +8,96 @@ Add this to your Gemfile:
8
8
 
9
9
  gem 'awesomemailer'
10
10
 
11
- Or if you're old-fashioned, do this:
12
-
13
- gem install awesomemailer
14
-
15
- Then `require 'awesome_mailer'` and follow the example below.
11
+ Then bundle. And some chips. And a soda.
16
12
 
17
13
  ## Example
18
14
 
19
15
  Suppose you have the following mailer:
20
16
 
21
- class UserMailer < ActionMailer::Base
22
- def signup(user_id)
23
- @user = User.find(user_id)
24
- mail(:to => @user.email, :from => "no-reply@example.com")
25
- end
26
- end
17
+ ```ruby
18
+ class UserMailer < ActionMailer::Base
19
+ def signup(user_id)
20
+ @user = User.find(user_id)
21
+ mail(:to => @user.email, :from => "no-reply@example.com")
22
+ end
23
+ end
24
+ ```
27
25
 
28
26
  ... and you have a template `app/views/user_mailer/signup.html.erb`. It might look something like this:
29
27
 
30
- <html>
31
- <%= stylesheet_link_tag 'email' %>
32
- <body>
33
- <div id="header"><%= link_to raw(image_tag('logo.png')), root_url %></div>
34
- <div id="content">
35
- <p>Welcome to AwesomeMailer, <%= @user.name %>! We think you might be neat.</p>
36
- </div>
37
- <div id="footer">
38
- Copyright &copy 2012 <a href="http://www.delightfulwidgets.com">Delightful Widgets</a>
39
- </div>
40
- </body>
41
- </html>
28
+ ```html
29
+ <html>
30
+ <%= stylesheet_link_tag 'email' %>
31
+ <body>
32
+ <div id="header"><%= link_to raw(image_tag('logo.png')), root_url %></div>
33
+ <div id="content">
34
+ <p>Welcome to AwesomeMailer, <%= @user.name %>! We think you might be neat.</p>
35
+ </div>
36
+ <div id="footer">
37
+ Copyright &copy 2013 <a href="http://www.delightfulwidgets.com">Delightful Widgets</a>
38
+ </div>
39
+ </body>
40
+ </html>
41
+ ```
42
42
 
43
43
  ... and your style sheet (email.css) might be kinda like this:
44
44
 
45
- body {
46
- background: #f0f0f0;
47
- font: 12pt Arial normal;
48
- }
45
+ ```css
46
+ body {
47
+ background: #f0f0f0;
48
+ font: 12pt Arial normal;
49
+ }
49
50
 
50
- a img {
51
- border-width: 0;
52
- }
51
+ a img {
52
+ border-width: 0;
53
+ }
53
54
 
54
- #header {
55
- border-bottom: 1px solid black;
56
- margin-bottom: 1em;
57
- }
55
+ #header {
56
+ border-bottom: 1px solid black;
57
+ margin-bottom: 1em;
58
+ }
58
59
 
59
- #content {
60
- font-family: Helvetica;
61
- padding: 1em 0;
62
- }
60
+ #content {
61
+ font-family: Helvetica;
62
+ padding: 1em 0;
63
+ }
63
64
 
64
- #content p {
65
- line-height: 1.3em;
66
- }
65
+ #content p {
66
+ line-height: 1.3em;
67
+ }
67
68
 
68
- #footer {
69
- border-top: 1px dotted orange;
70
- font-size: 10pt;
71
- }
69
+ #footer {
70
+ border-top: 1px dotted orange;
71
+ font-size: 10pt;
72
+ }
73
+ ```
72
74
 
73
75
  ... you might be unhappy because most mail viewers couldn't care less that you included a stylesheet. But wait!
74
76
  There's AwesomeMailer! Just change your mailer to look like this:
75
77
 
76
- class UserMailer < AwesomeMailer::Base
78
+ ```ruby
79
+ class UserMailer < AwesomeMailer::Base
80
+ ```
77
81
 
78
82
  ... and voila! Now your templates will render like this:
79
83
 
80
- <html>
81
- <body style="background: #f0f0f0; font: 12pt Arial normal;">
82
- <div id="header" style="border-bottom: 1px solid black; margin-bottom: 1em;">
83
- <a href="http://www.delightfulwidgets.com/">
84
- <img src="http://www.delightfulwidgets.com/assets/logo.png" style="border-width: 0;" />
85
- </a>
86
- </div>
87
- <div id="content" style="font-family: Helvetica; padding: 1em 0;">
88
- <p style="line-height: 1.3em;">Welcome to AwesomeMailer, <%= @user.name %>! We think you might be neat.</p>
89
- </div>
90
- <div id="footer" style="border-top: 1px dotted orange; font-size: 10pt;">
91
- Copyright &copy 2012 <a href="http://www.delightfulwidgets.com">Delightful Widgets</a>
92
- </div>
93
- </body>
94
- </html>
84
+ ```html
85
+ <html>
86
+ <body style="background: #f0f0f0; font: 12pt Arial normal;">
87
+ <div id="header" style="border-bottom: 1px solid black; margin-bottom: 1em;">
88
+ <a href="http://www.delightfulwidgets.com/">
89
+ <img src="http://www.delightfulwidgets.com/assets/logo.png" style="border-width: 0;" />
90
+ </a>
91
+ </div>
92
+ <div id="content" style="font-family: Helvetica; padding: 1em 0;">
93
+ <p style="line-height: 1.3em;">Welcome to AwesomeMailer, <%= @user.name %>! We think you might be neat.</p>
94
+ </div>
95
+ <div id="footer" style="border-top: 1px dotted orange; font-size: 10pt;">
96
+ Copyright &copy 2012 <a href="http://www.delightfulwidgets.com">Delightful Widgets</a>
97
+ </div>
98
+ </body>
99
+ </html>
100
+ ```
95
101
 
96
102
  WOW!
97
103
 
@@ -118,8 +124,6 @@ File bugs using the issues tab in Github. **Don't** e-mail me. _Please_.
118
124
 
119
125
  ## LEGAL FUNSIES
120
126
 
121
- AwesomeMailer is copyright (c) 2011 Delightful Widgets Inc.
127
+ AwesomeMailer is copyright (c) 2013 Delightful Widgets Inc.
122
128
 
123
- It was built by Flip Sasser (flip@x451.com) using libraries from Alex Dunae
124
- ([https://github.com/alexdunae/css_parser](https://github.com/alexdunae/css_parser)) and, as far as I know, Nick Sieger
125
- ([https://github.com/hpricot/hpricot](https://github.com/hpricot/hpricot)). Those guys are AWESOME. Be their friends.
129
+ It was built by [Flip Sasser](http://www.inthebackforty.com/). CSS parsing is courtesy of ([css_parser](https://github.com/alexdunae/css_parser)) by Alex Dunae. Thanks, b.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.1.2
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "awesomemailer"
8
- s.version = "0.1.1"
8
+ s.version = "0.1.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Flip Sasser"]
12
- s.date = "2013-03-16"
12
+ s.date = "2013-04-12"
13
13
  s.description = "\n AwesomeMailer embeds your e-mail CSS inline, allowing you to write e-mail templates without worrying too much about stylesheets\n "
14
14
  s.email = "flip@x451.com"
15
15
  s.extra_rdoc_files = [
@@ -17,21 +17,42 @@ module AwesomeMailer
17
17
  end
18
18
 
19
19
  private
20
- def append_styles!(document, selector, declarations)
21
- header_stylesheet.inner_html += "#{selector} { #{declarations} }\n"
20
+ def append_styles_to_body!(document, selector, declarations)
21
+ declarations = "#{declarations.join('; ')};"
22
+ document.search(selector).each do |element|
23
+ element['style'] = [element['style'], declarations].compact.join(';')
24
+ end
25
+ end
26
+
27
+ def append_styles_to_head!(document, selector, declarations, media = nil)
28
+ selector_and_declarations = "#{selector} { #{declarations.join('; ')}; }"
29
+ if media != :all
30
+ selector_and_declarations = "@media #{media} { #{selector_and_declarations} }"
31
+ end
32
+ header_stylesheet.inner_html += "#{selector_and_declarations}\n"
22
33
  end
23
34
 
24
35
  def apply_css!(document)
25
- css_parser.each_selector do |selector, declarations, specificity|
26
- # Rewrite relative URLs to match their parent CSS's URL path
27
- rewrite_relative_urls(declarations) if css_host
28
- if selector =~ /(^@|:)/
29
- # Include difficult styles in the head
30
- append_styles!(document, selector, declarations.to_s)
31
- else
32
- # Include regular styles inline
33
- document.search(selector).each do |element|
34
- element['style'] = [element['style'], *declarations].compact.join(';')
36
+ css_parser.rules_by_media_query.each do |media_query, rules|
37
+ rules.each do |rule|
38
+ rule.each_selector do |selector, declarations, specificity|
39
+ # Rewrite relative URLs to match their parent CSS's URL path
40
+ rewrite_relative_urls(declarations) if host
41
+ declarations = declarations.split(';').map(&:strip)
42
+ if media_query != :all || selector =~ /(^@|:|moz)/
43
+ # Include difficult styles in the head
44
+ append_styles_to_head!(document, selector, declarations, media_query)
45
+ else
46
+ # Strip vendor prefix styles and append them to the header
47
+ vendor_specific_declarations = declarations.select {|declaration| declaration =~ /^-/ }
48
+ if vendor_specific_declarations.any?
49
+ declarations -= vendor_specific_declarations
50
+ append_styles_to_head!(document, selector, vendor_specific_declarations, media_query)
51
+ end
52
+
53
+ # Include regular styles inline
54
+ append_styles_to_body!(document, selector, declarations)
55
+ end
35
56
  end
36
57
  end
37
58
  end
@@ -39,13 +60,7 @@ module AwesomeMailer
39
60
 
40
61
  def asset_pipeline_path
41
62
  return false unless sprockets?
42
- /^#{Regexp.escape(Rails.configuration.assets.prefix)}\//
43
- end
44
-
45
- def css_host
46
- if host = AwesomeMailer::Base.default_url_options[:host]
47
- Addressable::URI.heuristic_parse(host, scheme: 'http')
48
- end
63
+ /^#{Regexp.escape(Rails.configuration.assets[:prefix])}\//
49
64
  end
50
65
 
51
66
  def css_parser
@@ -66,13 +81,19 @@ module AwesomeMailer
66
81
  end
67
82
  end
68
83
 
84
+ def host
85
+ if host = AwesomeMailer::Base.default_url_options[:host]
86
+ Addressable::URI.heuristic_parse(host, scheme: 'http')
87
+ end
88
+ end
89
+
69
90
  def load_stylesheet(stylesheet)
70
91
  stylesheet_path = stylesheet['href'].split('?').shift
71
- stylesheet_path.gsub!(/^#{Regexp.escape(css_host)}/, '') if css_host
92
+ stylesheet_path.gsub!(/^#{Regexp.escape(host)}/, '') if host
72
93
  case stylesheet_path
73
94
  when asset_pipeline_path
74
95
  if asset = read_asset_pipeline_asset(stylesheet_path)
75
- css_parser.add_block!(asset.to_s, :media_types => :all)
96
+ css_parser.add_block!(asset.to_s)
76
97
  end
77
98
  when /^\//
78
99
  local_path = rails? && Rails.root.join('public', stylesheet_path.gsub(/^\//, '')).to_s
@@ -96,7 +117,7 @@ module AwesomeMailer
96
117
  def rewrite_relative_urls(css_declarations)
97
118
  css_declarations.scan(/(url\s*\(?["']+(.[^'"]*)["']\))/i).each do |url_command, item|
98
119
  next if item =~ /^http(s){0,1}:\/\//
99
- item_url = css_host.dup
120
+ item_url = host.dup
100
121
  item_url.path = File.join(item_url.path, item)
101
122
  new_url_command = url_command.gsub(item, item_url.to_s)
102
123
  css_declarations[url_command] = new_url_command
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: awesomemailer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-16 00:00:00.000000000 Z
12
+ date: 2013-04-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionmailer