roadie 3.2.2 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -0
- data/Changelog.md +15 -1
- data/README.md +88 -8
- data/lib/roadie/asset_scanner.rb +0 -7
- data/lib/roadie/document.rb +83 -7
- data/lib/roadie/inliner.rb +28 -11
- data/lib/roadie/net_http_provider.rb +16 -1
- data/lib/roadie/url_rewriter.rb +5 -1
- data/lib/roadie/version.rb +1 -1
- data/spec/integration_spec.rb +464 -234
- data/spec/lib/roadie/asset_scanner_spec.rb +0 -19
- data/spec/lib/roadie/document_spec.rb +82 -0
- data/spec/lib/roadie/inliner_spec.rb +31 -1
- data/spec/lib/roadie/net_http_provider_spec.rb +35 -0
- data/spec/lib/roadie/url_rewriter_spec.rb +16 -0
- data/spec/support/have_selector_matcher.rb +2 -2
- data/spec/support/have_xpath_matcher.rb +6 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2a5d2f3eb66ab40ecf551f53e5b7df59321c2805
|
4
|
+
data.tar.gz: 82c0b5241461df56c8810dca075245a75a0acf99
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e8c1a2ed3e74d586b95e341472b4c80e18e58ae01a094955b7dc102cd2cfe7c76ec1172159e1a1138a09adea465ac17ca1b0fcbde1f42680c46252cffee977ec
|
7
|
+
data.tar.gz: 777552240c002247354dad9c1bcc6ac6fb78ab62774d7e4fb3fe2e1a7aa49f855a67f3586b0178d0b99455c5d0e9547d72d3a30f460e3f8ecec6cabd9f437125
|
data/.travis.yml
CHANGED
@@ -5,8 +5,12 @@ rvm:
|
|
5
5
|
- 2.2
|
6
6
|
- 2.3
|
7
7
|
- 2.4
|
8
|
+
- 2.5
|
8
9
|
- jruby
|
9
10
|
- rbx
|
11
|
+
before_install:
|
12
|
+
- gem update --system # Need for Ruby 2.5.0. https://github.com/travis-ci/travis-ci/issues/8978
|
13
|
+
- gem install bundler
|
10
14
|
matrix:
|
11
15
|
allow_failures:
|
12
16
|
# Rubinius and JRuby have a lot of trouble and no large following, so I'm going to
|
data/Changelog.md
CHANGED
@@ -1,11 +1,25 @@
|
|
1
1
|
### dev
|
2
2
|
|
3
|
-
[full changelog](https://github.com/Mange/roadie/compare/v3.
|
3
|
+
[full changelog](https://github.com/Mange/roadie/compare/v3.3.0...master)
|
4
4
|
|
5
5
|
* Nothing yet.
|
6
6
|
|
7
7
|
### 3.2.2
|
8
8
|
|
9
|
+
[full changelog](https://github.com/Mange/roadie/compare/v3.2.2...v3.3.0)
|
10
|
+
|
11
|
+
* Enhancements
|
12
|
+
* Allow transforming to XHTML instead of HTML - [Zhivko Draganov](https://github.com/zdraganov) (#144).
|
13
|
+
* Support partial HTML documents (fragments) - #147
|
14
|
+
* With the help of [andfx](https://github.com/andfx) - #115
|
15
|
+
* With the help of [Frida Sjoholm](https://github.com/andf://github.com/FridaSjoholm) - #146
|
16
|
+
* Skip URL rewriting on elements with `data-roadie-ignore` - #154.
|
17
|
+
* With the help of [Hamed Asghari](https://github.com/hasghari) - #138.
|
18
|
+
* Bug fixes:
|
19
|
+
* Apply correct string encoding / charset in `NetHttpProvider` - [Jeremy Nagel](https://github.com/jeznag) (#152).
|
20
|
+
|
21
|
+
### 3.2.2
|
22
|
+
|
9
23
|
[full changelog](https://github.com/Mange/roadie/compare/v3.2.1...v3.2.2)
|
10
24
|
|
11
25
|
* Enhancements
|
data/README.md
CHANGED
@@ -5,7 +5,6 @@ Roadie
|
|
5
5
|
[![Code Climate](https://codeclimate.com/github/Mange/roadie.png)](https://codeclimate.com/github/Mange/roadie)
|
6
6
|
[![Code coverage status](https://codecov.io/github/Mange/roadie/coverage.svg?branch=master)](https://codecov.io/github/Mange/roadie?branch=master)
|
7
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
8
|
|
10
9
|
**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
10
|
|
@@ -23,7 +22,11 @@ This gem makes this easier by automatically inlining stylesheets into the docume
|
|
23
22
|
|
24
23
|
"Dynamic" selectors (`:hover`, `:visited`, `:focus`, etc.), or selectors not understood by Nokogiri will be inlined into a single `<style>` element for those email clients that support it. This changes specificity a great deal for these rules, so it might not work 100% out of the box. (See more about this below)
|
25
24
|
|
26
|
-
Roadie also rewrites all relative URLs in the email to an absolute counterpart,
|
25
|
+
Roadie also rewrites all relative URLs in the email to an absolute counterpart,
|
26
|
+
making images you insert and those referenced in your stylesheets work. No more
|
27
|
+
headaches about how to write the stylesheets while still having them work with
|
28
|
+
emails from your acceptance environments. You can disable this on specific
|
29
|
+
elements using a `data-roadie-ignore` marker.
|
27
30
|
|
28
31
|
Features
|
29
32
|
--------
|
@@ -35,9 +38,12 @@ Features
|
|
35
38
|
* Keeps `:hover` and friends around in a separate `<style>` element.
|
36
39
|
* Makes image urls absolute.
|
37
40
|
* Hostname and port configurable on a per-environment basis.
|
41
|
+
* Can be disabled on individual elements.
|
38
42
|
* Makes link `href`s and `img` `src`s absolute.
|
39
43
|
* Automatically adds proper HTML skeleton when missing; you don't have to create a layout for emails.
|
44
|
+
* Also supports HTML fragments / partial documents, where layout is not added.
|
40
45
|
* Allows you to inject stylesheets in a number of ways, at runtime.
|
46
|
+
* Removes `data-roadie-ignore` markers before finishing the HTML.
|
41
47
|
|
42
48
|
Install & Usage
|
43
49
|
---------------
|
@@ -51,10 +57,17 @@ gem 'roadie', '~> 3.2'
|
|
51
57
|
You can then create a new instance of a Roadie document:
|
52
58
|
|
53
59
|
```ruby
|
60
|
+
# Transform full documents with the #transform method.
|
54
61
|
document = Roadie::Document.new "<html><body></body></html>"
|
55
62
|
document.add_css "body { color: green; }"
|
56
63
|
document.transform
|
57
64
|
# => "<html><body style=\"color:green;\"></body></html>"
|
65
|
+
|
66
|
+
# Transform partial documents with #transform_partial.
|
67
|
+
document = Roadie::Document.new "<div>Hello world!</div>"
|
68
|
+
document.add_css "div { color: green; }"
|
69
|
+
document.transform_partial
|
70
|
+
# => "<div style=\"color:green;\">Hello world!</div>"
|
58
71
|
```
|
59
72
|
|
60
73
|
Your document instance can be configured with several options:
|
@@ -83,6 +96,14 @@ The following URLs will be rewritten for you:
|
|
83
96
|
* `img[src]` (HTML)
|
84
97
|
* `url()` (CSS)
|
85
98
|
|
99
|
+
You can disable individual elements by adding an `data-roadie-ignore` marker on
|
100
|
+
them. CSS will still be inlined on those elements, but URLs will not be
|
101
|
+
rewritten.
|
102
|
+
|
103
|
+
```html
|
104
|
+
<a href="|UNSUBSCRIBE_URL|" data-roadie-ignore>Unsubscribe</a>
|
105
|
+
```
|
106
|
+
|
86
107
|
### Referenced stylesheets ###
|
87
108
|
|
88
109
|
By default, `style` and `link` elements in the email document's `head` are processed along with the stylesheets and removed from the `head`.
|
@@ -177,7 +198,9 @@ The `NetHttpProvider` will download the URLs that is is given using Ruby's stand
|
|
177
198
|
You can give it a whitelist of hosts that downloads are allowed from:
|
178
199
|
|
179
200
|
```ruby
|
180
|
-
document.external_asset_providers << Roadie::NetHttpProvider.new(
|
201
|
+
document.external_asset_providers << Roadie::NetHttpProvider.new(
|
202
|
+
whitelist: ["myapp.com", "assets.myapp.com", "cdn.cdnnetwork.co.jp"],
|
203
|
+
)
|
181
204
|
document.external_asset_providers << Roadie::NetHttpProvider.new # Allows every host
|
182
205
|
```
|
183
206
|
|
@@ -331,11 +354,18 @@ end
|
|
331
354
|
|
332
355
|
### Keeping CSS that is impossible to inline
|
333
356
|
|
334
|
-
Some CSS is impossible to inline properly. `:hover` and `::after` comes to
|
357
|
+
Some CSS is impossible to inline properly. `:hover` and `::after` comes to
|
358
|
+
mind. Roadie tries its best to keep these around by injecting them inside a new
|
359
|
+
`<style>` element in the `<head>` (or at the beginning of the partial if
|
360
|
+
transforming a partial document).
|
335
361
|
|
336
|
-
The problem here is that Roadie cannot possible adjust the specificity for you,
|
362
|
+
The problem here is that Roadie cannot possible adjust the specificity for you,
|
363
|
+
so they will not apply the same way as they did before the styles were inlined.
|
337
364
|
|
338
|
-
Another caveat is that a lot of email clients does not support this (which is
|
365
|
+
Another caveat is that a lot of email clients does not support this (which is
|
366
|
+
the entire point of inlining in the first place), so don't put anything
|
367
|
+
important in here. Always handle the case of these selectors not being part of
|
368
|
+
the email.
|
339
369
|
|
340
370
|
#### Specificity problems ####
|
341
371
|
|
@@ -374,10 +404,26 @@ class TrackNewsletterLinks
|
|
374
404
|
end
|
375
405
|
end
|
376
406
|
|
377
|
-
document.before_transformation =
|
407
|
+
document.before_transformation = ->(dom, document) {
|
408
|
+
logger.debug "Inlining document with title #{dom.at_css('head > title').try(:text)}"
|
409
|
+
}
|
378
410
|
document.after_transformation = TrackNewsletterLinks.new
|
379
411
|
```
|
380
412
|
|
413
|
+
### XHTML vs HTML ###
|
414
|
+
|
415
|
+
You can configure the underlying HTML/XML engine to output XHTML or HTML (which
|
416
|
+
is the default). One usecase for this is that `{` tokens usually gets escaped
|
417
|
+
to `{`, which would be a problem if you then pass the resulting HTML on to
|
418
|
+
some other templating engine that uses those tokens (like Handlebars or Mustache).
|
419
|
+
|
420
|
+
```ruby
|
421
|
+
document.mode = :xhtml
|
422
|
+
```
|
423
|
+
|
424
|
+
This will also affect the emitted `<!DOCTYPE>` if transforming a full document.
|
425
|
+
Partial documents does not have a `<!DOCTYPE>`.
|
426
|
+
|
381
427
|
Build Status
|
382
428
|
------------
|
383
429
|
|
@@ -418,6 +464,40 @@ Instructions on how to do this on most platforms, see [Nokogiri's official insta
|
|
418
464
|
|
419
465
|
The CSS Parser used in Roadie does not handle keyframes. I don't think any email clients do either, but if you want to keep on trying you can add them manually to a `<style>` element (or a separate referenced stylesheet) and [tell Roadie not to touch them](#referenced-stylesheets).
|
420
466
|
|
467
|
+
### How do I get rid of the `<body>` elements that are added?
|
468
|
+
|
469
|
+
It sounds like you want to transform a partial document. Maybe you are building
|
470
|
+
partials or template fragments to later place in other documents. Use
|
471
|
+
`Document#transform_partial` instead of `Document#transform` in order to treat
|
472
|
+
the HTML as a partial document.
|
473
|
+
|
474
|
+
### Can I skip URL rewriting on a specific element?
|
475
|
+
|
476
|
+
If you add the `data-roadie-ignore` attribute on an element, URL rewriting will
|
477
|
+
not be performed on that element. This could be really useful for you if you
|
478
|
+
intend to send the email through some other rendering pipeline that replaces
|
479
|
+
some placeholders/variables.
|
480
|
+
|
481
|
+
```html
|
482
|
+
<a href="/about-us">About us</a>
|
483
|
+
<a href="|UNSUBSCRIBE_URL|" data-roadie-ignore>Unsubscribe</a>
|
484
|
+
```
|
485
|
+
|
486
|
+
Note that this will not skip CSS inlining on the element; it will still get the
|
487
|
+
correct styles applied.
|
488
|
+
|
489
|
+
### What should I do about "Invalid URL" errors?
|
490
|
+
|
491
|
+
If the URL is invalid on purpose, see _Can I skip URL rewriting on a specific
|
492
|
+
element?_ above. Otherwise, you can try to parse it yourself using Ruby's `URI`
|
493
|
+
class and see if you can figure it out.
|
494
|
+
|
495
|
+
```ruby
|
496
|
+
require "uri"
|
497
|
+
URI.parse("https://example.com/best image.jpg") # raises
|
498
|
+
URI.parse("https://example.com/best%20image.jpg") # Works!
|
499
|
+
```
|
500
|
+
|
421
501
|
Documentation
|
422
502
|
-------------
|
423
503
|
|
@@ -462,7 +542,7 @@ License
|
|
462
542
|
|
463
543
|
(The MIT License)
|
464
544
|
|
465
|
-
Copyright (c) 2009-
|
545
|
+
Copyright (c) 2009-2018 Magnus Bergmark, Jim Neath / Purify, and contributors.
|
466
546
|
|
467
547
|
* [Magnus Bergmark](https://github.com/Mange) <magnus.bergmark@gmail.com>
|
468
548
|
|
data/lib/roadie/asset_scanner.rb
CHANGED
@@ -46,7 +46,6 @@ module Roadie
|
|
46
46
|
element.remove if stylesheet
|
47
47
|
stylesheet
|
48
48
|
}.compact
|
49
|
-
remove_ignore_markers
|
50
49
|
stylesheets
|
51
50
|
end
|
52
51
|
|
@@ -102,11 +101,5 @@ module Roadie
|
|
102
101
|
|
103
102
|
true
|
104
103
|
end
|
105
|
-
|
106
|
-
def remove_ignore_markers
|
107
|
-
@dom.css("[data-roadie-ignore]").each do |node|
|
108
|
-
node.remove_attribute "data-roadie-ignore"
|
109
|
-
end
|
110
|
-
end
|
111
104
|
end
|
112
105
|
end
|
data/lib/roadie/document.rb
CHANGED
@@ -13,6 +13,8 @@ module Roadie
|
|
13
13
|
# The internal stylesheet is used last and gets the highest priority. The
|
14
14
|
# rest is used in the same order as browsers are supposed to use them.
|
15
15
|
#
|
16
|
+
# The execution methods are {#transform} and {#transform_partial}.
|
17
|
+
#
|
16
18
|
# @attr [#call] before_transformation Callback to call just before {#transform}ation begins. Will be called with the parsed DOM tree and the {Document} instance.
|
17
19
|
# @attr [#call] after_transformation Callback to call just before {#transform}ation is completed. Will be called with the current DOM tree and the {Document} instance.
|
18
20
|
class Document
|
@@ -27,6 +29,9 @@ module Roadie
|
|
27
29
|
# Should CSS that cannot be inlined be kept in a new `<style>` element in `<head>`?
|
28
30
|
attr_accessor :keep_uninlinable_css
|
29
31
|
|
32
|
+
# The mode to generate markup in. Valid values are `:html` (default) and `:xhtml`.
|
33
|
+
attr_reader :mode
|
34
|
+
|
30
35
|
# @param [String] html the input HTML
|
31
36
|
def initialize(html)
|
32
37
|
@keep_uninlinable_css = true
|
@@ -34,6 +39,7 @@ module Roadie
|
|
34
39
|
@asset_providers = ProviderList.wrap(FilesystemProvider.new)
|
35
40
|
@external_asset_providers = ProviderList.empty
|
36
41
|
@css = ""
|
42
|
+
@mode = :html
|
37
43
|
end
|
38
44
|
|
39
45
|
# Append additional CSS to the document's internal stylesheet.
|
@@ -42,18 +48,21 @@ module Roadie
|
|
42
48
|
@css << "\n\n" << new_css
|
43
49
|
end
|
44
50
|
|
45
|
-
# Transform the input HTML and returns the processed
|
51
|
+
# Transform the input HTML as a full document and returns the processed
|
52
|
+
# HTML.
|
46
53
|
#
|
47
54
|
# Before the transformation begins, the {#before_transformation} callback
|
48
55
|
# will be called with the parsed HTML tree and the {Document} instance, and
|
49
56
|
# after all work is complete the {#after_transformation} callback will be
|
50
57
|
# invoked in the same way.
|
51
58
|
#
|
52
|
-
# Most of the work is delegated to other classes. A list of them can be
|
59
|
+
# Most of the work is delegated to other classes. A list of them can be
|
60
|
+
# seen below.
|
53
61
|
#
|
54
62
|
# @see MarkupImprover MarkupImprover (improves the markup of the DOM)
|
55
63
|
# @see Inliner Inliner (inlines the stylesheets)
|
56
64
|
# @see UrlRewriter UrlRewriter (rewrites URLs and makes them absolute)
|
65
|
+
# @see #transform_partial Transforms partial documents (fragments)
|
57
66
|
#
|
58
67
|
# @return [String] the transformed HTML
|
59
68
|
def transform
|
@@ -62,7 +71,41 @@ module Roadie
|
|
62
71
|
callback before_transformation, dom
|
63
72
|
|
64
73
|
improve dom
|
65
|
-
inline dom
|
74
|
+
inline dom, keep_uninlinable_in: :head
|
75
|
+
rewrite_urls dom
|
76
|
+
|
77
|
+
callback after_transformation, dom
|
78
|
+
|
79
|
+
remove_ignore_markers dom
|
80
|
+
serialize_document dom
|
81
|
+
end
|
82
|
+
|
83
|
+
# Transform the input HTML as a HTML fragment/partial and returns the
|
84
|
+
# processed HTML.
|
85
|
+
#
|
86
|
+
# Before the transformation begins, the {#before_transformation} callback
|
87
|
+
# will be called with the parsed HTML tree and the {Document} instance, and
|
88
|
+
# after all work is complete the {#after_transformation} callback will be
|
89
|
+
# invoked in the same way.
|
90
|
+
#
|
91
|
+
# The main difference between this and {#transform} is that this does not
|
92
|
+
# treat the HTML as a full document and does not try to fix it by adding
|
93
|
+
# doctypes, {<head>} elements, etc.
|
94
|
+
#
|
95
|
+
# Most of the work is delegated to other classes. A list of them can be
|
96
|
+
# seen below.
|
97
|
+
#
|
98
|
+
# @see Inliner Inliner (inlines the stylesheets)
|
99
|
+
# @see UrlRewriter UrlRewriter (rewrites URLs and makes them absolute)
|
100
|
+
# @see #transform Transforms full documents
|
101
|
+
#
|
102
|
+
# @return [String] the transformed HTML
|
103
|
+
def transform_partial
|
104
|
+
dom = Nokogiri::HTML.fragment html
|
105
|
+
|
106
|
+
callback before_transformation, dom
|
107
|
+
|
108
|
+
inline dom, keep_uninlinable_in: :root
|
66
109
|
rewrite_urls dom
|
67
110
|
|
68
111
|
callback after_transformation, dom
|
@@ -80,7 +123,23 @@ module Roadie
|
|
80
123
|
@external_asset_providers = ProviderList.wrap(list)
|
81
124
|
end
|
82
125
|
|
126
|
+
# Change the mode. The mode affects how the resulting markup is generated.
|
127
|
+
#
|
128
|
+
# Valid modes:
|
129
|
+
# `:html` (default)
|
130
|
+
# `:xhtml`
|
131
|
+
def mode=(mode)
|
132
|
+
if VALID_MODES.include?(mode)
|
133
|
+
@mode = mode
|
134
|
+
else
|
135
|
+
raise ArgumentError, "Invalid mode #{mode.inspect}. Valid modes are: #{VALID_MODES.inspect}"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
83
139
|
private
|
140
|
+
VALID_MODES = %i[html xhtml].freeze
|
141
|
+
private_constant :VALID_MODES
|
142
|
+
|
84
143
|
def stylesheet
|
85
144
|
Stylesheet.new "(Document styles)", @css
|
86
145
|
end
|
@@ -89,9 +148,13 @@ module Roadie
|
|
89
148
|
MarkupImprover.new(dom, html).improve
|
90
149
|
end
|
91
150
|
|
92
|
-
def inline(dom)
|
151
|
+
def inline(dom, options = {})
|
152
|
+
keep_uninlinable_in = options.fetch(:keep_uninlinable_in)
|
93
153
|
dom_stylesheets = AssetScanner.new(dom, asset_providers, external_asset_providers).extract_css
|
94
|
-
Inliner.new(dom_stylesheets + [stylesheet], dom).inline(
|
154
|
+
Inliner.new(dom_stylesheets + [stylesheet], dom).inline(
|
155
|
+
keep_uninlinable_css: keep_uninlinable_css,
|
156
|
+
keep_uninlinable_in: keep_uninlinable_in,
|
157
|
+
)
|
95
158
|
end
|
96
159
|
|
97
160
|
def rewrite_urls(dom)
|
@@ -101,10 +164,17 @@ module Roadie
|
|
101
164
|
def serialize_document(dom)
|
102
165
|
# #dup is called since it fixed a few segfaults in certain versions of Nokogiri
|
103
166
|
save_options = Nokogiri::XML::Node::SaveOptions
|
167
|
+
format = {
|
168
|
+
html: save_options::AS_HTML,
|
169
|
+
xhtml: save_options::AS_XHTML,
|
170
|
+
}.fetch(mode)
|
171
|
+
|
104
172
|
dom.dup.to_html(
|
105
173
|
save_with: (
|
106
|
-
save_options::NO_DECLARATION |
|
107
|
-
|
174
|
+
save_options::NO_DECLARATION |
|
175
|
+
save_options::NO_EMPTY_TAGS |
|
176
|
+
format
|
177
|
+
),
|
108
178
|
)
|
109
179
|
end
|
110
180
|
|
@@ -127,5 +197,11 @@ module Roadie
|
|
127
197
|
end
|
128
198
|
end
|
129
199
|
end
|
200
|
+
|
201
|
+
def remove_ignore_markers(dom)
|
202
|
+
dom.css("[data-roadie-ignore]").each do |node|
|
203
|
+
node.remove_attribute "data-roadie-ignore"
|
204
|
+
end
|
205
|
+
end
|
130
206
|
end
|
131
207
|
end
|
data/lib/roadie/inliner.rb
CHANGED
@@ -24,13 +24,20 @@ module Roadie
|
|
24
24
|
|
25
25
|
# Start the inlining, mutating the DOM tree.
|
26
26
|
#
|
27
|
-
# @
|
27
|
+
# @option options [true, false] :keep_uninlinable_css
|
28
|
+
# @option options [:root, :head] :keep_uninlinable_in
|
28
29
|
# @return [nil]
|
29
|
-
def inline(
|
30
|
+
def inline(options = {})
|
31
|
+
keep_uninlinable_css = options.fetch(:keep_uninlinable_css, true)
|
32
|
+
keep_uninlinable_in = options.fetch(:keep_uninlinable_in, :head)
|
33
|
+
|
30
34
|
style_map, extra_blocks = consume_stylesheets
|
31
35
|
|
32
36
|
apply_style_map(style_map)
|
33
|
-
|
37
|
+
|
38
|
+
if keep_uninlinable_css
|
39
|
+
add_uninlinable_styles(keep_uninlinable_in, extra_blocks)
|
40
|
+
end
|
34
41
|
|
35
42
|
nil
|
36
43
|
end
|
@@ -89,21 +96,31 @@ module Roadie
|
|
89
96
|
nil
|
90
97
|
end
|
91
98
|
|
92
|
-
def
|
93
|
-
|
94
|
-
|
95
|
-
|
99
|
+
def add_uninlinable_styles(parent, blocks)
|
100
|
+
return if blocks.empty?
|
101
|
+
|
102
|
+
parent_node =
|
103
|
+
case parent
|
104
|
+
when :head
|
105
|
+
find_head
|
106
|
+
when :root
|
107
|
+
dom
|
108
|
+
else
|
109
|
+
raise ArgumentError, "Parent must be either :head or :root. Was #{parent.inspect}"
|
110
|
+
end
|
111
|
+
|
112
|
+
create_style_element(blocks, parent_node)
|
96
113
|
end
|
97
114
|
|
98
115
|
def find_head
|
99
116
|
dom.at_xpath('html/head')
|
100
117
|
end
|
101
118
|
|
102
|
-
def create_style_element(style_blocks,
|
103
|
-
return unless
|
104
|
-
element = Nokogiri::XML::Node.new("style",
|
119
|
+
def create_style_element(style_blocks, parent)
|
120
|
+
return unless parent
|
121
|
+
element = Nokogiri::XML::Node.new("style", parent.document)
|
105
122
|
element.content = style_blocks.join("\n")
|
106
|
-
|
123
|
+
parent.add_child(element)
|
107
124
|
end
|
108
125
|
|
109
126
|
# @api private
|