roadie 2.4.3 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.travis.yml +10 -14
  4. data/.yardopts +1 -1
  5. data/Changelog.md +38 -5
  6. data/Gemfile +3 -4
  7. data/Guardfile +12 -1
  8. data/README.md +168 -164
  9. data/Rakefile +2 -19
  10. data/lib/roadie.rb +15 -68
  11. data/lib/roadie/asset_provider.rb +7 -58
  12. data/lib/roadie/asset_scanner.rb +92 -0
  13. data/lib/roadie/document.rb +103 -0
  14. data/lib/roadie/errors.rb +57 -0
  15. data/lib/roadie/filesystem_provider.rb +30 -60
  16. data/lib/roadie/inliner.rb +72 -217
  17. data/lib/roadie/markup_improver.rb +88 -0
  18. data/lib/roadie/null_provider.rb +13 -0
  19. data/lib/roadie/null_url_rewriter.rb +12 -0
  20. data/lib/roadie/provider_list.rb +71 -0
  21. data/lib/roadie/rspec.rb +1 -0
  22. data/lib/roadie/rspec/asset_provider.rb +49 -0
  23. data/lib/roadie/selector.rb +43 -18
  24. data/lib/roadie/style_attribute_builder.rb +25 -0
  25. data/lib/roadie/style_block.rb +32 -0
  26. data/lib/roadie/style_property.rb +93 -0
  27. data/lib/roadie/stylesheet.rb +65 -0
  28. data/lib/roadie/upgrade_guide.rb +36 -0
  29. data/lib/roadie/url_generator.rb +126 -0
  30. data/lib/roadie/url_rewriter.rb +84 -0
  31. data/lib/roadie/version.rb +1 -1
  32. data/roadie.gemspec +8 -11
  33. data/spec/fixtures/big_em.css +1 -0
  34. data/spec/fixtures/stylesheets/green.css +1 -0
  35. data/spec/integration_spec.rb +125 -95
  36. data/spec/lib/roadie/asset_scanner_spec.rb +153 -0
  37. data/spec/lib/roadie/css_not_found_spec.rb +17 -0
  38. data/spec/lib/roadie/document_spec.rb +123 -0
  39. data/spec/lib/roadie/filesystem_provider_spec.rb +44 -68
  40. data/spec/lib/roadie/inliner_spec.rb +105 -537
  41. data/spec/lib/roadie/markup_improver_spec.rb +78 -0
  42. data/spec/lib/roadie/null_provider_spec.rb +21 -0
  43. data/spec/lib/roadie/null_url_rewriter_spec.rb +19 -0
  44. data/spec/lib/roadie/provider_list_spec.rb +89 -0
  45. data/spec/lib/roadie/selector_spec.rb +15 -10
  46. data/spec/lib/roadie/style_attribute_builder_spec.rb +29 -0
  47. data/spec/lib/roadie/style_block_spec.rb +35 -0
  48. data/spec/lib/roadie/style_property_spec.rb +82 -0
  49. data/spec/lib/roadie/stylesheet_spec.rb +41 -0
  50. data/spec/lib/roadie/test_provider_spec.rb +29 -0
  51. data/spec/lib/roadie/url_generator_spec.rb +121 -0
  52. data/spec/lib/roadie/url_rewriter_spec.rb +79 -0
  53. data/spec/shared_examples/asset_provider.rb +11 -0
  54. data/spec/shared_examples/url_rewriter.rb +23 -0
  55. data/spec/spec_helper.rb +6 -60
  56. data/spec/support/have_attribute_matcher.rb +2 -2
  57. data/spec/support/have_node_matcher.rb +4 -4
  58. data/spec/support/have_selector_matcher.rb +3 -3
  59. data/spec/support/have_styling_matcher.rb +51 -15
  60. data/spec/support/test_provider.rb +13 -0
  61. metadata +86 -175
  62. data/Appraisals +0 -15
  63. data/gemfiles/rails_3.0.gemfile +0 -7
  64. data/gemfiles/rails_3.0.gemfile.lock +0 -123
  65. data/gemfiles/rails_3.1.gemfile +0 -7
  66. data/gemfiles/rails_3.1.gemfile.lock +0 -126
  67. data/gemfiles/rails_3.2.gemfile +0 -7
  68. data/gemfiles/rails_3.2.gemfile.lock +0 -124
  69. data/gemfiles/rails_4.0.gemfile +0 -7
  70. data/gemfiles/rails_4.0.gemfile.lock +0 -119
  71. data/lib/roadie/action_mailer_extensions.rb +0 -95
  72. data/lib/roadie/asset_pipeline_provider.rb +0 -28
  73. data/lib/roadie/css_file_not_found.rb +0 -22
  74. data/lib/roadie/railtie.rb +0 -39
  75. data/lib/roadie/style_declaration.rb +0 -42
  76. data/spec/fixtures/app/assets/stylesheets/integration.css +0 -10
  77. data/spec/fixtures/public/stylesheets/integration.css +0 -10
  78. data/spec/fixtures/views/integration_mailer/marketing.html.erb +0 -2
  79. data/spec/fixtures/views/integration_mailer/notification.html.erb +0 -8
  80. data/spec/fixtures/views/integration_mailer/notification.text.erb +0 -6
  81. data/spec/lib/roadie/action_mailer_extensions_spec.rb +0 -227
  82. data/spec/lib/roadie/asset_pipeline_provider_spec.rb +0 -65
  83. data/spec/lib/roadie/css_file_not_found_spec.rb +0 -29
  84. data/spec/lib/roadie/style_declaration_spec.rb +0 -49
  85. data/spec/lib/roadie_spec.rb +0 -101
  86. data/spec/shared_examples/asset_provider_examples.rb +0 -11
  87. data/spec/support/anonymous_mailer.rb +0 -21
  88. data/spec/support/change_url_options.rb +0 -5
  89. data/spec/support/parse_styling.rb +0 -25
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fb9d9810978beb19ef7c13d2ef8953827b418bb1
4
+ data.tar.gz: db5db2dc87d93790b131fd0b3c515e9c24114525
5
+ SHA512:
6
+ metadata.gz: 7cf63f4924682f07f21960926b8b804e9d82e7db8b8c90b2e658557983e9e098534841b823d162736a3d3cc973c23f568987db3e3911fbadcdc0234998c09587
7
+ data.tar.gz: c65545723737f33444e7c2797a8b01b288d0945a556100217fe7b0f86748bcfbc00908e1cd2204ea21fe26b543f0ebbf40e510831ba681fa6f66cc43ec67e981
data/.gitignore CHANGED
@@ -10,3 +10,6 @@ pkg
10
10
  Gemfile.lock
11
11
  doc
12
12
  tmp
13
+
14
+ spec/railsapps/*/log
15
+ spec/railsapps/*/tmp
data/.travis.yml CHANGED
@@ -1,22 +1,18 @@
1
- bundler_args: --without guard
2
- before_install:
3
- - gem install bundler --pre
4
-
1
+ language: ruby
5
2
  rvm:
6
- - 1.8.7
7
3
  - 1.9.3
8
4
  - 2.0.0
5
+ - 2.1.2
9
6
  - jruby
7
+ - rbx
8
+
9
+ bundler_args: --without guard
10
+ script: "rake"
10
11
 
11
- gemfile:
12
- - gemfiles/rails_3.0.gemfile
13
- - gemfiles/rails_3.1.gemfile
14
- - gemfiles/rails_3.2.gemfile
15
- - gemfiles/rails_4.0.gemfile
12
+ env:
13
+ # Setup Coveralls
14
+ secure: "D1Uvi+a7W89k91zXVVwuuvv8O8qbDdyJ4g9i+3bGaSYySHxD8YuuG1QiQ4G/S2KLp/r3VPRpa8Wb1mSwb81tEBzXpzoZC7zSvgntPxRPhMg4zpodZ0O0AkK8/t1yZSkIe0V5sejFOQ1a5LJa3OorKBBjrqM5kPDOygTXtO3bQ6E="
16
15
 
17
16
  matrix:
18
- exclude:
19
- - rvm: 1.8.7
20
- gemfile: gemfiles/rails_4.0.gemfile
21
17
  allow_failures:
22
- - rvm: jruby
18
+ - rvm: rbx
data/.yardopts CHANGED
@@ -1 +1 @@
1
- --no-private
1
+ --no-private --files Changelog.md
data/Changelog.md CHANGED
@@ -1,15 +1,48 @@
1
1
  ### dev
2
2
 
3
- [full changelog](https://github.com/Mange/roadie/compare/v2.4.3...master)
3
+ [full changelog](https://github.com/Mange/roadie/compare/v3.0.0...master)
4
4
 
5
- * Nothing yet
5
+ * Nothing yet.
6
6
 
7
- ### 2.4.3
7
+ ### 3.0.0
8
8
 
9
- [full changelog](https://github.com/Mange/roadie/compare/v2.4.2...v2.4.3)
9
+ [full changelog](https://github.com/Mange/roadie/compare/v3.0.0.pre1...v3.0.0)
10
10
 
11
- * Bug fixes:
11
+ * Enhancements:
12
+ * `Roadie::ProviderList` responds to `#empty?` and `#last`
13
+ * `Roadie::FilesystemProvider` ignores query string in filename.
14
+
15
+ Older versions of Rails generated `<link>` tags with query strings in their URLs, like such:
16
+ `/stylesheets/email.css?1380694096`
12
17
  * Blacklist `:enabled`, `:disabled` and `:checked` pseudo functions - [Tyler Hunt (tylerhunt)](https://github.com/tylerhunt).
18
+ * Add MRI 2.1.2 to Travis build matrix - [Grey Baker (greysteil)](https://github.com/greysteil).
19
+ * Try to detect an upgrade from Roadie 2 and mention how to make it work with the new version.
20
+ * Styles emitted in the `style` attribute should now be ordered as they were in the source CSS.
21
+
22
+ ### 3.0.0.pre1
23
+
24
+ [full changelog](https://github.com/Mange/roadie/compare/v2.4.2...v3.0.0.pre1)
25
+
26
+ Complete rewrite of most of the code and a new direction for the gem.
27
+
28
+ * Breaking changes:
29
+ * Removed Rails support into a separate Gem (`roadie-rails`).
30
+ * Removed Sprockets dependency and AssetPipelineProvider.
31
+ * Changed the entire public API.
32
+ * Changed the API of custom providers.
33
+ * Dropped support for Ruby 1.8.7.
34
+ * Change `data-immutable` to `data-roadie-ignore`.
35
+ * New features:
36
+ * Rewriting the URLs of `img[src]`.
37
+ * A way to inject stylesheets without having to adjust template.
38
+ * A before callback to compliment the after callback.
39
+ * Enhancements:
40
+ * Better support for stylesheets using CSS fallbacks.
41
+ This means that styles like this is now inlined: `width: 5em; width: 3rem;`, while Roadie would previously remove the first of the two.
42
+ This sadly means that the HTML file will be much larger than before if you're using a non-optimized stylesheet (for example including your application stylesheet to the email). This was a bad idea even before this change, and this might get you to change.
43
+ * Using HTML5 doctype instead of XHTML
44
+ * Full support for JRuby
45
+ * Experimental support for Rubinius
13
46
 
14
47
  ### 2.4.2
15
48
 
data/Gemfile CHANGED
@@ -1,11 +1,10 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
3
 
4
+ # Added here so it does not show up on the Gemspec; I only want it for CI builds
5
+ gem 'coveralls', group: :test, require: nil
6
+
4
7
  group :guard do
5
8
  gem 'guard'
6
9
  gem 'guard-rspec'
7
-
8
- # Guard for Mac
9
- gem 'rb-fsevent', '>= 0.9.0.pre5'
10
- gem 'growl'
11
10
  end
data/Guardfile CHANGED
@@ -1,6 +1,17 @@
1
- guard 'rspec' do
1
+ rspec_options = {
2
+ cmd: 'rspec -f documentation',
3
+ failed_mode: :keep,
4
+ all_after_pass: true,
5
+ all_on_start: true,
6
+ run_all: {cmd: 'rspec -f progress'}
7
+ }
8
+
9
+ guard 'rspec', rspec_options do
2
10
  watch(%r{^spec/.+_spec\.rb$})
3
11
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
12
+ watch('lib/roadie.rb') { "spec" }
13
+
14
+ watch(%r{lib/roadie/rspec/.*\.rb}) { "spec" }
4
15
 
5
16
  watch(%r{spec/support/.*\.rb}) { "spec" }
6
17
  watch('spec/spec_helper.rb') { "spec" }
data/README.md CHANGED
@@ -1,11 +1,18 @@
1
1
  Roadie
2
2
  ======
3
3
 
4
- > Making HTML emails comfortable for the Rails rockstars
4
+ [![Build history and status](https://secure.travis-ci.org/Mange/roadie.png)](http://travis-ci.org/#!/Mange/roadie)
5
+ [![Code Climate](https://codeclimate.com/github/Mange/roadie.png)](https://codeclimate.com/github/Mange/roadie)
6
+ [![Coverage Status](https://coveralls.io/repos/Mange/roadie/badge.png?branch=master)](https://coveralls.io/r/Mange/roadie?branch=master)
7
+ [![Gem Version](https://badge.fury.io/rb/roadie.png)](http://badge.fury.io/rb/roadie)
8
+ [![Dependency Status](https://gemnasium.com/Mange/roadie.png)](https://gemnasium.com/Mange/roadie)
9
+
10
+ **Note: This README details the 3.x version of Roadie. You might be using 2.x, which is much older and only for Rails.**
11
+
12
+ > Making HTML emails comfortable for the Ruby rockstars
5
13
 
6
- Roadie tries to make sending HTML emails a little less painful in Rails 3+ by inlining stylesheets and rewrite relative URLs for you.
14
+ Roadie tries to make sending HTML emails a little less painful by inlining stylesheets and rewriting relative URLs for you inside your emails.
7
15
 
8
- If you want to have this in Rails 2, please see [MailStyle](https://www.github.com/purify/mail_style).
9
16
 
10
17
  How does it work?
11
18
  -----------------
@@ -18,226 +25,229 @@ Roadie also rewrites all relative URLs in the email to a absolute counterpart, m
18
25
 
19
26
  ¹: Of course, rules like `:hover` will not work by definition. Only static styles can be added.
20
27
 
21
- Build Status
22
- ------------
23
-
24
- [![Build history and status](https://secure.travis-ci.org/Mange/roadie.png)](http://travis-ci.org/#!/Mange/roadie)
25
-
26
- Tested with [Travis CI](http://travis-ci.org) using [almost all combinations of](http://travis-ci.org/#!/Mange/roadie):
27
-
28
- * Ruby:
29
- * MRI 1.8.7
30
- * MRI 1.9.3
31
- * MRI 2.0.0
32
- * Rails
33
- * 3.0
34
- * 3.1
35
- * 3.2
36
- * 4.0
37
-
38
- Let me know if you want any other combination supported officially.
39
-
40
- ### Versioning ###
41
-
42
- This project follows [Semantic Versioning](http://semver.org/) and has been since version 1.0.0.
43
-
44
28
  Features
45
29
  --------
46
30
 
47
- * Supports Rails' Asset Pipeline and simple filesystem access out of the box
48
- * You can add support for CSS from any place inside your apps
49
31
  * Writes CSS styles inline
50
32
  * Respects `!important` styles
51
33
  * Does not overwrite styles already present in the `style` attribute of tags
52
34
  * Supports the same CSS selectors as [Nokogiri](http://nokogiri.org/) (use CSS3 selectors in your emails!)
53
35
  * Makes image urls absolute
54
36
  * Hostname and port configurable on a per-environment basis
55
- * Makes link `href`s absolute
37
+ * Makes link `href`s and `img` `src`s absolute
56
38
  * Automatically adds proper html skeleton when missing (you don't have to create a layout for emails)²
39
+ * Allows you to inject stylesheets in a number of ways, at runtime
57
40
 
58
- ²: This might be removed in a future version, though. You really ought to create a good layout and not let Roadie guess how you want to have it structured
41
+ ²: This might be removed in a future version, though. You really ought to create a good layout and not let Roadie guess how you want to have it structured.
59
42
 
60
- Install
61
- -------
43
+ Install & Usage
44
+ ---------------
62
45
 
63
- Add the gem to Rails' Gemfile
46
+ [Add this gem to your Gemfile as recommended by Rubygems](http://rubygems.org/gems/roadie) and run `bundle install`.
64
47
 
65
48
  ```ruby
66
- gem 'roadie'
49
+ gem 'roadie', '~> x.y.0'
67
50
  ```
68
51
 
69
- Configuring
70
- -----------
71
-
72
- Roadie listens to the following options (set in `Application.rb` or in your environment's configuration files:
52
+ You may then create a new instance of a Roadie document:
73
53
 
74
- * `config.roadie.enabled` - Set this to `false` to disable Roadie from working on your emails. Useful if you want to disable Roadie in some environments.
75
- * `config.action_mailer.default_url_options` - Used for making URLs absolute.
76
- * `config.assets.enabled` - If the asset pipeline is turned off, Roadie will default to searching for assets in `public/stylesheets`.
77
- * `config.roadie.provider` - Set the provider manually, ignoring all other options. Use for advanced cases, or when you have non-default paths or other options.
78
- * `config.roadie.after_inlining` - Set a custom inliner for the HTML document. The custom inliner in invoked after the default inliner.
54
+ ```ruby
55
+ document = Roadie::Document.new "<html><body></body></html>"
56
+ document.add_css "body { color: green; }"
57
+ document.transform
58
+ # => "<html><body style=\"color:green;\"></body></html>"
59
+ ```
79
60
 
80
- Usage
81
- -----
61
+ Your document instance can be configured several options:
82
62
 
83
- Just add a `<link rel="stylesheet" />` or `<style type="text/css"></style>` element inside your email layout and it will be inlined automatically.
63
+ * `url_options` - Dictates how absolute URLs should be built.
64
+ * `asset_providers` - A single (or list of) asset providers that are invoked when external CSS is referenced. See below.
65
+ * `before_transformation` - A callback run before inlining starts.
66
+ * `after_transformation` - A callback run after inlining is completed.
84
67
 
85
- **Note:** Do not use `stylesheet_link_tag` in your mail views. Just use a regular tag pointing to the logical asset name instead; e.g. `emails.css` instead of `emails-<SHA>.css`. This should hopefully be fixed in a later version. You are recommended to use the `:css` option to the mailer (detailed below) instead if you want to avoid problems with this.
68
+ ### Making URLs absolute ###
86
69
 
87
- You can also specify the `:css` option to mailer to have it inlined automatically without you having to make a layout:
70
+ In order to make URLs absolute you need to first configure the URL options of the document.
88
71
 
89
72
  ```ruby
90
- class Notifier < ActionMailer::Base
91
- default :css => 'email', :from => 'support@mycompany.com'
92
-
93
- def registration_mail
94
- mail(:subject => 'Welcome Aboard', :to => 'someone@example.com')
95
- end
96
-
97
- def newsletter
98
- mail(:subject => 'Newsletter', :to => 'someone@example.com', :css => ['email', 'newsletter'])
99
- end
100
- end
73
+ html = '... <a href="/about-us">Read more!</a> ...'
74
+ document = Roadie::Document.new html
75
+ document.url_options = {host: "myapp.com", protocol: "https"}
76
+ document.transform
77
+ # => "... <a href=\"https://myapp.com/about-us\">Read more!</a> ..."
101
78
  ```
102
79
 
103
- This will look for a css file called `email.css` in your assets. The `css` method can take either a string or an array of strings. The ".css" extension will be added automatically.
80
+ The following URLs will be rewritten for you:
81
+ * `a[href]` (HTML)
82
+ * `img[src]` (HTML)
83
+ * `url()` (CSS)
104
84
 
105
- ### Image URL rewriting ###
85
+ ### Referenced stylesheets ###
106
86
 
107
- If you have `default_url_options[:host]` set in your mailer, then Roadie will do it's best to make the URLs of images and in stylesheets absolute.
87
+ By default, `style` and `link` elements in the email document's `head` are processed along with the stylesheets and removed from the `head`.
108
88
 
109
- In `application.rb`:
89
+ You can set a special `data-roadie-ignore` attribute on `style` and `link` tags that you want to ignore (the attribute will be removed, however). This is the place to put things like `:hover` selectors that you want to have for email clients allowing them.
110
90
 
111
- ```ruby
112
- class Application
113
- config.action_mailer.default_url_options = {:host => 'example.com'}
114
- end
91
+ Style and link elements with `media="print"` are also ignored.
92
+
93
+ ```html
94
+ <head>
95
+ <link rel="stylesheet" type="text/css" href="/assets/emails/rock.css"> <!-- Will be inlined -->
96
+ <link rel="stylesheet" type="text/css" href="http://www.metal.org/metal.css"> <!-- Will NOT be inlined; absolute URL -->
97
+ <link rel="stylesheet" type="text/css" href="/assets/jazz.css" media="print"> <!-- Will NOT be inlined; print style -->
98
+ <link rel="stylesheet" type="text/css" href="/ambient.css" data-roadie-ignore> <!-- Will NOT be inlined; ignored -->
99
+ <style></style> <!-- Will be inlined -->
100
+ <style data-roadie-ignore></style> <!-- Will NOT be inlined; ignored -->
101
+ </head>
115
102
  ```
116
103
 
117
- If you want to to be different depending on your environment, just set it in your environment's configuration instead.
104
+ Roadie will use the given asset providers to look for the actual CSS that is referenced. If you don't change the default, it will use the `Roadie::FilesystemProvider` which looks for stylesheets on the filesystem, relative to the current working directory.
118
105
 
119
- ### Ignoring stylesheets ###
106
+ Example:
120
107
 
121
- By default, `style` and `link` elements in the email document's `head` are processed along with the stylesheets and removed from the `head`.
108
+ ```ruby
109
+ # /home/user/foo/stylesheets/primary.css
110
+ body { color: blue; }
111
+
112
+ # /home/user/foo/script.rb
113
+ html = <<-HTML
114
+ <html>
115
+ <head>
116
+ <link rel="stylesheet" type="text/css" href="/stylesheets/primary.css">
117
+ </head>
118
+ <body>
119
+ </body>
120
+ </html>
121
+ HTML
122
+
123
+ Dir.pwd # => "/home/user/foo"
124
+ document = Roadie::Document.new html
125
+ document.transform # =>
126
+ # <!DOCTYPE html>
127
+ # <html>
128
+ # <head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head>
129
+ # <body style="color:green;"></body>
130
+ # </html>
131
+ ```
122
132
 
123
- You can set a special `data-immutable="true"` attribute on `style` and `link` tags you do not want to be processed and removed from the document's `head`. This is the place to put things like `:hover` selectors that you want to have for email clients allowing them.
133
+ If a referenced stylesheet cannot be found, the `#transform` method will raise an `Roadie::CssNotFound` error. If you instead want to ignore missing stylesheets, you can use the `NullProvider`.
124
134
 
125
- Style and link elements with `media="print"` are always ignored.
135
+ ### Configuring providers ###
126
136
 
127
- ### Inlining link tags ###
137
+ You can write your own providers if you need very specific behavior for your app, or you can use the built-in providers.
128
138
 
129
- Any `link` element that is part of your email will be linked in. You can exclude them by setting `data-immutable` as you would on normal `style` elements. Linked stylesheets for print media is also ignored as you would expect.
139
+ Included providers:
140
+ * `FilesystemProvider` - Looks for files on the filesystem, relative to the given directory unless otherwise specified.
141
+ * `ProviderList` – Wraps a list of other providers and searches them in order. The `asset_providers` setting is an instance of this. It behaves a lot like an array, so you can push, pop, shift and unshift to it.
142
+ * `NullProvider` - Does not actually provide anything, it always finds empty stylesheets. Use this in tests or if you want to ignore stylesheets that cannot be found by your other providers.
130
143
 
131
- If the `link` tag uses an absolute URL to the stylesheet, it will not be inlined. Use a relative path instead:
144
+ If you want to search several locations on the filesystem, just declare that:
132
145
 
133
- ```html
134
- <head>
135
- <link rel="stylesheet" type="text/css" href="/assets/emails/rock.css"> <!-- Will be inlined -->
136
- <link rel="stylesheet" type="text/css" href="http://www.metal.org/metal.css"> <!-- Will NOT be inlined -->
137
- <link rel="stylesheet" type="text/css" href="/assets/jazz.css" media="print"> <!-- Will NOT be inlined -->
138
- <link rel="stylesheet" type="text/css" href="/ambient.css" data-immutable> <!-- Will NOT be inlined -->
139
- </head>
146
+ ```ruby
147
+ document.asset_providers = [
148
+ Roadie::FilesystemProvider.new(App.root.join("resources", "stylesheets")),
149
+ Roadie::FilesystemProvider.new(App.root.join("system", "uploads", "stylesheets")),
150
+ ]
140
151
  ```
141
152
 
142
- Writing your own provider
143
- -------------------------
153
+ If you want to ignore stylesheets that cannot be found instead of crashing, push the `NullProvider` to the end:
144
154
 
145
- A provider handles searching CSS files for you. You can easily create your own provider for your specific app by subclassing `Roadie::AssetProvider`. See the API documentation for information about how to build them.
155
+ ```ruby
156
+ document.asset_providers << Roadie::NullProvider.new
157
+ ```
146
158
 
147
- Example Subclassing the `AssetPipelineProvider`:
159
+ ### Writing your own provider ###
160
+
161
+ Writing your own provider is also easy. You just need to provide:
162
+ * `#find_stylesheet(name)`, returning either a `Roadie::Stylesheet` or nil.
163
+ * `#find_stylesheet!(name)`, returning either a `Roadie::Stylesheet` or raising `Roadie::CssNotFound`.
148
164
 
149
165
  ```ruby
150
- # application.rb
151
- config.roadie.provider = UserAssetsProvider.new
152
-
153
- # lib/user_assets_provider.rb
154
- class UserAssetsProvider < Roadie::AssetPipelineProvider
155
- def find(name)
156
- user = User.find_by_name(name)
157
- if user
158
- user.custom_css
159
- else
160
- super
166
+ class UserAssetsProvider
167
+ def initialize(user_collection)
168
+ @user_collection = user_collection
169
+ end
170
+
171
+ def find_stylesheet(name)
172
+ if name =~ %r{^/users/(\d+)\.css$}
173
+ user = @user_collection.find_user($1)
174
+ Roadie::Stylesheet.new("user #{user.id} stylesheet", user.stylesheet)
161
175
  end
162
176
  end
163
- end
164
- ```
165
177
 
166
- Writing your own inliner
167
- -------------------------
178
+ def find_stylesheet!(name)
179
+ find_stylesheet(name) or raise Roadie::CssNotFound.new(name)
180
+ end
168
181
 
169
- A custom inliner transforms an outgoing HTML email using application specific rules. The custom inliner is invoked after the default inliner.
182
+ # Instead of implementing #find_stylesheet!, you could also:
183
+ # include Roadie::AssetProvider
184
+ end
170
185
 
171
- A custom inliner can be created using a `lambda` that accepts one parameter or an object that responds to the `call` method with one parameter.
186
+ # Try to look for a user stylesheet first, then fall back to normal filesystem lookup.
187
+ document.asset_providers = [
188
+ UserAssetsProvider.new(app),
189
+ Roadie::FilesystemProvider.new('./stylesheets'),
190
+ ]
191
+ ```
172
192
 
173
- Example for using lambda as custom inliner:
193
+ You can test for compliance by using the built-in RSpec examples:
174
194
 
175
195
  ```ruby
176
- # application.rb
177
- config.roadie.after_inlining = lambda do |document|
178
- document.css("a#new_user").each do |link|
179
- link['href'] = "http://www.foo.com#{link['href']}"
196
+ require 'spec_helper'
197
+ require 'roadie/rspec'
198
+
199
+ describe MyOwnProvider do
200
+ # Will use the default `subject` (MyOwnProvider.new)
201
+ it_behaves_like "roadie asset provider", valid_name: "found.css", invalid_name: "does_not_exist.css"
202
+
203
+ # Extra setup just for these tests:
204
+ it_behaves_like "roadie asset provider", valid_name: "found.css", invalid_name: "does_not_exist.css" do
205
+ subject { MyOwnProvider.new(...) }
206
+ before { Whatever.stub ... }
180
207
  end
181
208
  end
182
209
  ```
183
210
 
184
- Example for using object as custom inliner:
211
+ ### Callbacks ###
185
212
 
186
- ```ruby
187
- # application.rb
188
- config.roadie.after_inlining = PromotionInliner.new
213
+ Callbacks allow you to do custom work on documents before they are inlined. The Nokogiri document tree is passed to the callable:
189
214
 
190
- # lib/product_link_inliner.rb
191
- class PromotionInliner
215
+ ```ruby
216
+ class TrackNewsletterLinks
192
217
  def call(document)
193
- document.css("a.product").each do |link|
194
- fix_link link
195
- end
218
+ document.css("a").each { |link| fix_link(link) }
196
219
  end
197
220
 
198
221
  def fix_link(link)
199
- if link['class'] =~ /\bsale\b/
200
- link['href'] = link['href'] + '?source=newsletter'
201
- end
222
+ divider = (link['href'] =~ /?/ ? '&' : '?')
223
+ link['href'] = link['href'] + divider + 'source=newsletter'
202
224
  end
203
225
  end
226
+
227
+ document.before_transformation = { |document| logger.debug "Inlining document with title #{document.at_css('head > title').try(:text)}" }
228
+ document.after_transformation = TrackNewsletterLinks.new
204
229
  ```
205
230
 
206
- ### Custom inliner scopes
231
+ Build Status
232
+ ------------
207
233
 
208
- - **All HTML emails**
234
+ Tested with [Travis CI](http://travis-ci.org) using:
209
235
 
210
- ```ruby
211
- # application.rb. Custom inliner for all emails.
212
- config.roadie.after_inlining = PromotionInliner.new
213
- ```
214
- - **All HTML emails sent by a mailer**
236
+ * MRI 1.9.3
237
+ * MRI 2.0.0
238
+ * MRI 2.1.2
239
+ * JRuby (latest)
240
+ * Rubinius >= 2.1 (experimental)
215
241
 
216
- ```ruby
217
- class MarketingMailer < ActionMailer::Base
218
- # Custom inliner for all mailer methods.
219
- default after_inlining: PromotionInliner.new
220
- end
221
- ```
242
+ [(Build status)](http://travis-ci.org/#!/Mange/roadie)
222
243
 
223
- - **All HTML emails sent by a specific mailer method**
244
+ Let me know if you want any other VM supported officially.
224
245
 
225
- ```ruby
226
- class UserMailer < ActionMailer::Base
227
- def registration
228
- # Custom inliner for registration emails
229
- mail(after_inlining: MarketingMailer.new)
230
- end
231
- end
232
- ```
246
+ Rubinius support is experimental since it it currently hindered by a Rubinius bug that will probably be fixed shortly.
233
247
 
234
- Bugs / TODO
235
- -----------
248
+ ### Versioning ###
236
249
 
237
- * Improve overall performance
238
- * Clean up stylesheet assignment code
239
- * Assets referenced with digest URLs should be findable
240
- * Roadie should be able to have multiple asset providers in a specific order
250
+ This project follows [Semantic Versioning](http://semver.org/) and has been since version 1.0.0.
241
251
 
242
252
  FAQ
243
253
  ---
@@ -262,18 +272,24 @@ Put any styles using them in a separate stylesheet and make sure it is ignored.
262
272
  Documentation
263
273
  -------------
264
274
 
265
- * [Online documentation for 2.3.0](http://rubydoc.info/gems/roadie/2.3.0/frames)
275
+ * [Online documentation for gem](http://rubydoc.info/gems/roadie/frames)
266
276
  * [Online documentation for master](http://rubydoc.info/github/Mange/roadie/master/frames)
277
+ * [Online documentation for Roadie 2.4](http://rubydoc.info/gems/roadie/2.4/frames)
267
278
  * [Changelog](https://github.com/Mange/roadie/blob/master/Changelog.md)
268
279
 
269
280
  Running specs
270
281
  -------------
271
282
 
272
- Run specs for your current ruby against the latest compatible version of rails with `rake spec`. You can run against all supported combinations of ruby and rails by issuing `rake spec:all`.
283
+ ```bash
284
+ bundle install
285
+ rake
286
+ ```
273
287
 
274
288
  History and contributors
275
289
  ------------------------
276
290
 
291
+ This gem was previously tied to Rails. It is now framework-agnostic and supports any type of HTML documents. If you want to use it with Rails, check out [roadie-rails](https://github.com/Mange/roadie-rails).
292
+
277
293
  Major contributors to Roadie:
278
294
 
279
295
  * [Arttu Tervo (arttu)](https://github.com/arttu) - Original Asset pipeline support
@@ -281,26 +297,14 @@ Major contributors to Roadie:
281
297
 
282
298
  You can [see all contributors](https://github.com/Mange/roadie/contributors) on GitHub.
283
299
 
284
- This gem was originally developed for Rails 2 use on [Purify](http://purifyapp.com) under the name [MailStyle](https://www.github.com/purify/mail_style). However, the author stopped maintaining it and a fork took place to make it Rails 3+ compatible.
285
-
286
- The following people have contributed to the orignal gem:
287
-
288
- * [Jim Neath](http://jimneath.org) (Original author)
289
- * [Lars Klevans](http://tastybyte.blogspot.com/)
290
- * [Jonas Grimfelt](http://github.com/grimen)
291
- * [Ben Johnson](http://www.binarylogic.com)
292
- * [Istvan Hoka](http://istvanhoka.com/)
293
- * [Voraz](http://blog.voraz.com.br)
294
-
295
300
  License
296
301
  -------
297
302
 
298
303
  (The MIT License)
299
304
 
300
- Copyright (c) 2009-2013
305
+ Copyright (c) 2009-2014
301
306
 
302
- * [Jim Neath](http://jimneath.org)
303
- * Magnus Bergmark <magnus.bergmark@gmail.com>
307
+ * [Magnus Bergmark](https://github.com/Mange) <magnus.bergmark@gmail.com>
304
308
 
305
309
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
306
310