awesomemailer 0.1.1 → 0.1.2

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.
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