roadie 3.2.2 → 3.3.0
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.
- 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
|
[](https://codeclimate.com/github/Mange/roadie)
|
6
6
|
[](https://codecov.io/github/Mange/roadie?branch=master)
|
7
7
|
[](http://badge.fury.io/rb/roadie)
|
8
|
-
[](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
|