roadie 4.0.0 → 5.0.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/.github/workflows/main.yml +43 -0
- data/.solargraph.yml +16 -0
- data/Changelog.md +14 -2
- data/Gemfile +5 -2
- data/README.md +11 -13
- data/Rakefile +2 -2
- data/lib/roadie/asset_provider.rb +3 -1
- data/lib/roadie/asset_scanner.rb +6 -6
- data/lib/roadie/cached_provider.rb +1 -0
- data/lib/roadie/deduplicator.rb +1 -0
- data/lib/roadie/document.rb +7 -10
- data/lib/roadie/errors.rb +18 -14
- data/lib/roadie/filesystem_provider.rb +13 -3
- data/lib/roadie/inliner.rb +49 -19
- data/lib/roadie/markup_improver.rb +22 -31
- data/lib/roadie/net_http_provider.rb +25 -11
- data/lib/roadie/null_provider.rb +18 -5
- data/lib/roadie/null_url_rewriter.rb +6 -2
- data/lib/roadie/path_rewriter_provider.rb +4 -1
- data/lib/roadie/provider_list.rb +15 -11
- data/lib/roadie/rspec/asset_provider.rb +4 -1
- data/lib/roadie/rspec.rb +2 -2
- data/lib/roadie/selector.rb +15 -5
- data/lib/roadie/style_attribute_builder.rb +2 -1
- data/lib/roadie/style_block.rb +3 -3
- data/lib/roadie/style_property.rb +3 -2
- data/lib/roadie/stylesheet.rb +2 -13
- data/lib/roadie/url_generator.rb +24 -8
- data/lib/roadie/url_rewriter.rb +6 -3
- data/lib/roadie/utils.rb +1 -1
- data/lib/roadie/version.rb +1 -2
- data/lib/roadie.rb +23 -23
- data/roadie.gemspec +23 -25
- data/spec/hash_as_cache_store_spec.rb +1 -1
- data/spec/integration_spec.rb +41 -44
- data/spec/lib/roadie/asset_scanner_spec.rb +9 -4
- data/spec/lib/roadie/cached_provider_spec.rb +4 -4
- data/spec/lib/roadie/css_not_found_spec.rb +8 -5
- data/spec/lib/roadie/deduplicator_spec.rb +3 -3
- data/spec/lib/roadie/document_spec.rb +45 -27
- data/spec/lib/roadie/filesystem_provider_spec.rb +8 -10
- data/spec/lib/roadie/inliner_spec.rb +40 -44
- data/spec/lib/roadie/markup_improver_spec.rb +17 -25
- data/spec/lib/roadie/net_http_provider_spec.rb +8 -8
- data/spec/lib/roadie/null_provider_spec.rb +2 -2
- data/spec/lib/roadie/null_url_rewriter_spec.rb +2 -2
- data/spec/lib/roadie/path_rewriter_provider_spec.rb +4 -4
- data/spec/lib/roadie/provider_list_spec.rb +25 -21
- data/spec/lib/roadie/selector_spec.rb +4 -4
- data/spec/lib/roadie/style_attribute_builder_spec.rb +5 -5
- data/spec/lib/roadie/style_block_spec.rb +1 -1
- data/spec/lib/roadie/style_property_spec.rb +8 -8
- data/spec/lib/roadie/stylesheet_spec.rb +2 -20
- data/spec/lib/roadie/test_provider_spec.rb +4 -4
- data/spec/lib/roadie/url_generator_spec.rb +1 -1
- data/spec/lib/roadie/url_rewriter_spec.rb +6 -4
- data/spec/spec_helper.rb +8 -8
- data/spec/support/have_attribute_matcher.rb +1 -2
- data/spec/support/have_node_matcher.rb +3 -3
- data/spec/support/have_selector_matcher.rb +2 -3
- data/spec/support/have_styling_matcher.rb +10 -11
- data/spec/support/have_xpath_matcher.rb +2 -3
- metadata +22 -21
- data/.travis.yml +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ba6c121fdd1072479afeee70b785db020df45cbe3b45350a20f9cfd4f8d0164
|
4
|
+
data.tar.gz: bfd6faa52b576fba65b8d2281b213ceabf137f08551749dc842b9a9477566fd2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b897b87d20fdd739110788a21f2b16c5c4a86726b876cfe2a1c815bc671341a02172eaca5bb65729e14cc10e06b7baa076832bd55cb36db927fb4c548eb117e
|
7
|
+
data.tar.gz: 290845f661cf1d913fcf01b3c66eeb6e6ec096667a64c21b81fa912950e42a0d1a8294532e28b01f283cf9215a5da028c3559e2fa6cac54860d9c006bce7f401
|
@@ -0,0 +1,43 @@
|
|
1
|
+
name: Main
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
branches:
|
5
|
+
- main
|
6
|
+
- master
|
7
|
+
|
8
|
+
pull_request:
|
9
|
+
types: [opened, synchronize, reopened]
|
10
|
+
|
11
|
+
jobs:
|
12
|
+
base:
|
13
|
+
name: Ruby ${{ matrix.ruby }}
|
14
|
+
runs-on: ubuntu-20.04
|
15
|
+
strategy:
|
16
|
+
fail-fast: false
|
17
|
+
matrix:
|
18
|
+
ruby: ["2.6", "2.7", "3.0", "3.1"]
|
19
|
+
|
20
|
+
steps:
|
21
|
+
- name: Checkout code
|
22
|
+
uses: actions/checkout@v2
|
23
|
+
|
24
|
+
# This setup is not compatible with the way Travis CI was
|
25
|
+
# setup, so the cache will only work for the root folder.
|
26
|
+
- name: Setup Ruby
|
27
|
+
uses: ruby/setup-ruby@v1
|
28
|
+
with:
|
29
|
+
ruby-version: ${{ matrix.ruby }}
|
30
|
+
bundler-cache: true
|
31
|
+
|
32
|
+
- name: Rake
|
33
|
+
run: bundle exec rake
|
34
|
+
|
35
|
+
- uses: codecov/codecov-action@v2
|
36
|
+
|
37
|
+
lint:
|
38
|
+
runs-on: ubuntu-latest
|
39
|
+
steps:
|
40
|
+
- name: standardrb
|
41
|
+
env:
|
42
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
43
|
+
uses: amoeba/standardrb-action@v2
|
data/.solargraph.yml
ADDED
data/Changelog.md
CHANGED
@@ -1,9 +1,21 @@
|
|
1
1
|
### dev
|
2
2
|
|
3
|
-
[full changelog](https://github.com/Mange/roadie/compare/
|
3
|
+
[full changelog](https://github.com/Mange/roadie/compare/v5.0.0...master)
|
4
4
|
|
5
5
|
Nothing yet.
|
6
6
|
|
7
|
+
### 5.0.0
|
8
|
+
|
9
|
+
[full changelog](https://github.com/Mange/roadie/compare/v4.0.0...v5.0.0)
|
10
|
+
|
11
|
+
* Drop support for Ruby 2.4 and Ruby 2.5
|
12
|
+
* Drop support for JRuby and Rubinius
|
13
|
+
* Test with Ruby 2.7 - [aried3r (Anton Rieder)](https://github.com/aried3r) (#167)
|
14
|
+
* Test with Ruby 3.0 and Ruby 3.1
|
15
|
+
* Add standardrb as code formatter
|
16
|
+
* Drop support for callbacks that accepts only a single argument.
|
17
|
+
* Change signature of `Roadie::CssNotFound` and `Roadie::ProvidersFailed`.
|
18
|
+
|
7
19
|
### 4.0.0
|
8
20
|
|
9
21
|
[full changelog](https://github.com/Mange/roadie/compare/v3.5.1...v4.0.0)
|
@@ -11,6 +23,7 @@ Nothing yet.
|
|
11
23
|
* Drop support for Ruby 2.1, 2.2, and 2.3 and
|
12
24
|
add support for frozen string literals and Ruby 2.6 - [adamkiczula (Adam
|
13
25
|
Kiczula)](https://github.com/adamkiczula) (#164)
|
26
|
+
* `Roadie::Stylesheet#each_inlinable_block` is now removed.
|
14
27
|
|
15
28
|
### 3.5.1
|
16
29
|
|
@@ -386,4 +399,3 @@ Roadie fork!
|
|
386
399
|
* + some other enhancements
|
387
400
|
* Deprecations:
|
388
401
|
* Removed support for Rails 2.x
|
389
|
-
|
data/Gemfile
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
source
|
3
|
+
source "https://rubygems.org"
|
4
4
|
gemspec
|
5
5
|
|
6
6
|
# Added here so it does not show up on the Gemspec; I only want it for CI builds
|
7
|
-
gem
|
7
|
+
gem "codecov", group: :test, require: false
|
8
|
+
# Not actually required to run the tests for the gem, but a real convenience
|
9
|
+
# for local development.
|
10
|
+
gem "standard", group: [:test, :development], require: false
|
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
Roadie
|
2
2
|
======
|
3
3
|
|
4
|
-
[](http://travis-ci.org/#!/Mange/roadie)
|
5
4
|
[](https://codeclimate.com/github/Mange/roadie)
|
6
5
|
[](https://codecov.io/github/Mange/roadie?branch=master)
|
7
6
|
[](https://rubygems.org/gems/roadie)
|
@@ -333,7 +332,10 @@ class UserAssetsProvider
|
|
333
332
|
end
|
334
333
|
|
335
334
|
def find_stylesheet!(name)
|
336
|
-
find_stylesheet(name) or
|
335
|
+
find_stylesheet(name) or
|
336
|
+
raise Roadie::CssNotFound.new(
|
337
|
+
css_name: name, message: "does not match a user stylesheet", provider: self
|
338
|
+
)
|
337
339
|
end
|
338
340
|
|
339
341
|
# Instead of implementing #find_stylesheet!, you could also:
|
@@ -444,18 +446,14 @@ Partial documents does not have a `<!DOCTYPE>`.
|
|
444
446
|
Build Status
|
445
447
|
------------
|
446
448
|
|
447
|
-
Tested with
|
449
|
+
Tested with Github CI using:
|
448
450
|
|
449
|
-
* MRI 2.
|
450
|
-
* MRI 2.
|
451
|
-
* MRI
|
452
|
-
* MRI
|
453
|
-
* JRuby (latest)
|
454
|
-
* Rubinius (failures on Rubinius will not fail the build due to a long history of instability in `rbx`)
|
451
|
+
* MRI 2.6
|
452
|
+
* MRI 2.7
|
453
|
+
* MRI 3.0
|
454
|
+
* MRI 3.1
|
455
455
|
|
456
|
-
|
457
|
-
|
458
|
-
Let me know if you want any other VM supported officially.
|
456
|
+
Let me know if you want any other runtime supported officially.
|
459
457
|
|
460
458
|
### Versioning ###
|
461
459
|
|
@@ -565,7 +563,7 @@ License
|
|
565
563
|
|
566
564
|
(The MIT License)
|
567
565
|
|
568
|
-
Copyright (c) 2009-
|
566
|
+
Copyright (c) 2009-2022 Magnus Bergmark, Jim Neath / Purify, and contributors.
|
569
567
|
|
570
568
|
* [Magnus Bergmark](https://github.com/Mange) <magnus.bergmark@gmail.com>
|
571
569
|
|
data/Rakefile
CHANGED
@@ -7,7 +7,9 @@ module Roadie
|
|
7
7
|
# It helps you by declaring {#find_stylesheet!} in the terms of #find_stylesheet in your own class.
|
8
8
|
module AssetProvider
|
9
9
|
def find_stylesheet!(name)
|
10
|
-
find_stylesheet(name) or raise
|
10
|
+
find_stylesheet(name) or raise(
|
11
|
+
CssNotFound.new(css_name: name, provider: self)
|
12
|
+
)
|
11
13
|
end
|
12
14
|
end
|
13
15
|
end
|
data/lib/roadie/asset_scanner.rb
CHANGED
@@ -43,15 +43,15 @@ module Roadie
|
|
43
43
|
# @see #find_css
|
44
44
|
# @return [Enumerable<Stylesheet>] every extracted stylesheet
|
45
45
|
def extract_css
|
46
|
-
|
46
|
+
@dom.css(STYLE_ELEMENT_QUERY).map { |element|
|
47
47
|
stylesheet = read_stylesheet(element)
|
48
48
|
element.remove if stylesheet
|
49
49
|
stylesheet
|
50
50
|
}.compact
|
51
|
-
stylesheets
|
52
51
|
end
|
53
52
|
|
54
53
|
private
|
54
|
+
|
55
55
|
STYLE_ELEMENT_QUERY = (
|
56
56
|
"style:not([data-roadie-ignore]), " +
|
57
57
|
# TODO: When using Nokogiri 1.6.1 and later; we may use a double :not here
|
@@ -75,7 +75,7 @@ module Roadie
|
|
75
75
|
def read_stylesheet(element)
|
76
76
|
if element.name == "style"
|
77
77
|
read_style_element element
|
78
|
-
elsif element.name == "link" && element[
|
78
|
+
elsif element.name == "link" && element["media"] != "print" && element["href"]
|
79
79
|
read_link_element element
|
80
80
|
end
|
81
81
|
end
|
@@ -86,14 +86,14 @@ module Roadie
|
|
86
86
|
|
87
87
|
def read_link_element(element)
|
88
88
|
if Utils.path_is_absolute?(element["href"])
|
89
|
-
external_asset_provider.find_stylesheet! element[
|
89
|
+
external_asset_provider.find_stylesheet! element["href"] if should_find_external?
|
90
90
|
else
|
91
|
-
normal_asset_provider.find_stylesheet! element[
|
91
|
+
normal_asset_provider.find_stylesheet! element["href"]
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
95
95
|
def clean_css(css)
|
96
|
-
css.gsub(CLEANING_MATCHER,
|
96
|
+
css.gsub(CLEANING_MATCHER, "")
|
97
97
|
end
|
98
98
|
|
99
99
|
def should_find_external?
|
data/lib/roadie/deduplicator.rb
CHANGED
data/lib/roadie/document.rb
CHANGED
@@ -142,6 +142,7 @@ module Roadie
|
|
142
142
|
# Valid modes:
|
143
143
|
# `:html` (default)
|
144
144
|
# `:xhtml`
|
145
|
+
# `:xml`
|
145
146
|
def mode=(mode)
|
146
147
|
if VALID_MODES.include?(mode)
|
147
148
|
@mode = mode
|
@@ -151,7 +152,8 @@ module Roadie
|
|
151
152
|
end
|
152
153
|
|
153
154
|
private
|
154
|
-
|
155
|
+
|
156
|
+
VALID_MODES = %i[html xhtml xml].freeze
|
155
157
|
private_constant :VALID_MODES
|
156
158
|
|
157
159
|
def stylesheet
|
@@ -168,7 +170,7 @@ module Roadie
|
|
168
170
|
Inliner.new(dom_stylesheets + [stylesheet], dom).inline(
|
169
171
|
keep_uninlinable_css: keep_uninlinable_css,
|
170
172
|
keep_uninlinable_in: keep_uninlinable_in,
|
171
|
-
merge_media_queries: merge_media_queries
|
173
|
+
merge_media_queries: merge_media_queries
|
172
174
|
)
|
173
175
|
end
|
174
176
|
|
@@ -182,6 +184,7 @@ module Roadie
|
|
182
184
|
format = {
|
183
185
|
html: save_options::AS_HTML,
|
184
186
|
xhtml: save_options::AS_XHTML,
|
187
|
+
xml: save_options::AS_XML
|
185
188
|
}.fetch(mode)
|
186
189
|
|
187
190
|
dom.dup.to_html(
|
@@ -189,7 +192,7 @@ module Roadie
|
|
189
192
|
save_options::NO_DECLARATION |
|
190
193
|
save_options::NO_EMPTY_TAGS |
|
191
194
|
format
|
192
|
-
)
|
195
|
+
)
|
193
196
|
)
|
194
197
|
end
|
195
198
|
|
@@ -203,13 +206,7 @@ module Roadie
|
|
203
206
|
|
204
207
|
def callback(callable, dom)
|
205
208
|
if callable.respond_to?(:call)
|
206
|
-
|
207
|
-
# TODO: Remove on next major version (v4.0)
|
208
|
-
if !callable.respond_to?(:parameters) || callable.parameters.size == 1
|
209
|
-
callable.(dom)
|
210
|
-
else
|
211
|
-
callable.(dom, self)
|
212
|
-
end
|
209
|
+
callable.call(dom, self)
|
213
210
|
end
|
214
211
|
end
|
215
212
|
|
data/lib/roadie/errors.rb
CHANGED
@@ -18,10 +18,10 @@ module Roadie
|
|
18
18
|
|
19
19
|
def initialize(given_path, cause = nil)
|
20
20
|
@cause = cause
|
21
|
-
if cause
|
22
|
-
|
21
|
+
cause_message = if cause
|
22
|
+
" Caused by: #{cause}"
|
23
23
|
else
|
24
|
-
|
24
|
+
""
|
25
25
|
end
|
26
26
|
super "Cannot use path \"#{given_path}\" in URL generation.#{cause_message}"
|
27
27
|
end
|
@@ -43,23 +43,22 @@ module Roadie
|
|
43
43
|
# Extra message
|
44
44
|
attr_reader :extra_message
|
45
45
|
|
46
|
-
|
47
|
-
def initialize(css_name, extra_message = nil, provider = nil)
|
46
|
+
def initialize(css_name:, message: nil, provider: nil)
|
48
47
|
@css_name = css_name
|
49
48
|
@provider = provider
|
50
|
-
@extra_message =
|
51
|
-
super build_message
|
49
|
+
@extra_message = message
|
50
|
+
super build_message
|
52
51
|
end
|
53
52
|
|
54
53
|
protected
|
54
|
+
|
55
55
|
def error_row
|
56
|
-
"#{provider || "Unknown provider"}: #{extra_message
|
56
|
+
"#{provider || "Unknown provider"}: #{extra_message}"
|
57
57
|
end
|
58
58
|
|
59
59
|
private
|
60
|
-
|
61
|
-
|
62
|
-
def build_message(extra_message = @extra_message)
|
60
|
+
|
61
|
+
def build_message
|
63
62
|
message = +%(Could not find stylesheet "#{css_name}")
|
64
63
|
message << ": #{extra_message}" if extra_message
|
65
64
|
message << "\nUsed provider:\n#{provider}" if provider
|
@@ -70,13 +69,18 @@ module Roadie
|
|
70
69
|
class ProvidersFailed < CssNotFound
|
71
70
|
attr_reader :errors
|
72
71
|
|
73
|
-
def initialize(css_name
|
72
|
+
def initialize(css_name:, providers:, errors:)
|
74
73
|
@errors = errors
|
75
|
-
super(
|
74
|
+
super(
|
75
|
+
css_name: css_name,
|
76
|
+
message: "All providers failed",
|
77
|
+
provider: providers
|
78
|
+
)
|
76
79
|
end
|
77
80
|
|
78
81
|
private
|
79
|
-
|
82
|
+
|
83
|
+
def build_message
|
80
84
|
message = +%(Could not find stylesheet "#{css_name}": #{extra_message}\nUsed providers:\n)
|
81
85
|
each_error_row(errors) do |row|
|
82
86
|
message << "\t" << row << "\n"
|
@@ -32,14 +32,24 @@ module Roadie
|
|
32
32
|
Stylesheet.new file_path, File.read(file_path)
|
33
33
|
else
|
34
34
|
basename = File.basename file_path
|
35
|
-
raise CssNotFound.new(
|
35
|
+
raise CssNotFound.new(
|
36
|
+
css_name: basename,
|
37
|
+
message: %{#{file_path} does not exist. (Original name was "#{name}")},
|
38
|
+
provider: self
|
39
|
+
)
|
36
40
|
end
|
37
41
|
end
|
38
42
|
|
39
|
-
def to_s
|
40
|
-
|
43
|
+
def to_s
|
44
|
+
inspect
|
45
|
+
end
|
46
|
+
|
47
|
+
def inspect
|
48
|
+
"#<#{self.class} #{@path}>"
|
49
|
+
end
|
41
50
|
|
42
51
|
private
|
52
|
+
|
43
53
|
def build_file_path(name)
|
44
54
|
raise InsecurePathError, name if name.include?("..")
|
45
55
|
File.join(@path, name[/^([^?]+)/])
|
data/lib/roadie/inliner.rb
CHANGED
@@ -1,21 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
3
|
+
require "set"
|
4
|
+
require "nokogiri"
|
5
|
+
require "uri"
|
6
|
+
require "css_parser"
|
7
7
|
|
8
8
|
module Roadie
|
9
9
|
# @api private
|
10
10
|
# The Inliner inlines stylesheets to the elements of the DOM.
|
11
11
|
#
|
12
12
|
# Inlining means that {StyleBlock}s and a DOM tree are combined:
|
13
|
-
#
|
14
|
-
#
|
13
|
+
#
|
14
|
+
# ```css
|
15
|
+
# a { color: red; } # StyleBlock
|
16
|
+
# ```
|
17
|
+
# ```html
|
18
|
+
# <a href="/"></a> # DOM
|
19
|
+
# ```
|
15
20
|
#
|
16
21
|
# becomes
|
17
22
|
#
|
18
|
-
#
|
23
|
+
# ```html
|
24
|
+
# <a href="/" style="color:red"></a>
|
25
|
+
# ```
|
19
26
|
class Inliner
|
20
27
|
# @param [Array<Stylesheet>] stylesheets the stylesheets to use in the inlining
|
21
28
|
# @param [Nokogiri::HTML::Document] dom
|
@@ -47,9 +54,11 @@ module Roadie
|
|
47
54
|
end
|
48
55
|
|
49
56
|
protected
|
57
|
+
|
50
58
|
attr_reader :stylesheets, :dom
|
51
59
|
|
52
60
|
private
|
61
|
+
|
53
62
|
def consume_stylesheets
|
54
63
|
style_map = StyleMap.new
|
55
64
|
extra_blocks = []
|
@@ -91,12 +100,18 @@ module Roadie
|
|
91
100
|
# with having to rescue errors.
|
92
101
|
# Pseudo selectors that are known to be bad are skipped automatically but
|
93
102
|
# this will catch the rest.
|
94
|
-
rescue Nokogiri::XML::XPath::SyntaxError, Nokogiri::CSS::SyntaxError
|
95
|
-
Utils.warn
|
103
|
+
rescue Nokogiri::XML::XPath::SyntaxError, Nokogiri::CSS::SyntaxError
|
104
|
+
Utils.warn(
|
105
|
+
"Cannot inline #{selector.inspect} from \"#{stylesheet.name}\" " \
|
106
|
+
"stylesheet. If this is valid CSS, please report a bug."
|
107
|
+
)
|
96
108
|
nil
|
97
109
|
rescue => error
|
98
|
-
Utils.warn
|
99
|
-
|
110
|
+
Utils.warn(
|
111
|
+
"Got error when looking for #{selector.inspect} " \
|
112
|
+
"(from \"#{stylesheet.name}\" stylesheet): #{error}"
|
113
|
+
)
|
114
|
+
raise unless error.message.include?("XPath")
|
100
115
|
nil
|
101
116
|
end
|
102
117
|
|
@@ -122,12 +137,12 @@ module Roadie
|
|
122
137
|
end
|
123
138
|
|
124
139
|
def find_head
|
125
|
-
dom.at_xpath(
|
140
|
+
dom.at_xpath("html/head")
|
126
141
|
end
|
127
142
|
|
128
143
|
def create_style_element(style_blocks, parent, merge_media_queries)
|
129
144
|
return unless parent
|
130
|
-
element = Nokogiri::XML::Node.new(
|
145
|
+
element = Nokogiri::XML::Node.new("style", parent.document)
|
131
146
|
|
132
147
|
element.content =
|
133
148
|
if merge_media_queries
|
@@ -141,17 +156,23 @@ module Roadie
|
|
141
156
|
# For performance reasons, we should group styles with the same media types within
|
142
157
|
# one media query instead of creating thousands of media queries.
|
143
158
|
# https://github.com/artifex404/media-queries-benchmark
|
144
|
-
#
|
159
|
+
#
|
160
|
+
# Example result:
|
161
|
+
#
|
162
|
+
# ```ruby
|
163
|
+
# ["@media(max-width: 600px) { .col-12 { display: block; } }"]
|
164
|
+
# ```
|
165
|
+
#
|
145
166
|
# @param {Array<StyleBlock>} style_blocks Style blocks that could not be inlined
|
146
167
|
# @return {Array<String>}
|
147
168
|
def styles_in_shared_media_queries(style_blocks)
|
148
169
|
style_blocks.group_by(&:media).map do |media_types, blocks|
|
149
170
|
css_rules = blocks.map(&:to_s).join("\n")
|
150
171
|
|
151
|
-
if media_types == [
|
172
|
+
if media_types == ["all"]
|
152
173
|
css_rules
|
153
174
|
else
|
154
|
-
"@media #{media_types.join(
|
175
|
+
"@media #{media_types.join(", ")} {\n#{css_rules}\n}"
|
155
176
|
end
|
156
177
|
end
|
157
178
|
end
|
@@ -159,27 +180,36 @@ module Roadie
|
|
159
180
|
# Some users might prefer to not group rules within media queries because
|
160
181
|
# it will result in rules getting reordered.
|
161
182
|
# e.g.
|
183
|
+
#
|
184
|
+
# ```css
|
162
185
|
# @media(max-width: 600px) { .col-6 { display: block; } }
|
163
186
|
# @media(max-width: 400px) { .col-12 { display: inline-block; } }
|
164
187
|
# @media(max-width: 600px) { .col-12 { display: block; } }
|
188
|
+
# ````
|
189
|
+
#
|
165
190
|
# will become
|
191
|
+
#
|
192
|
+
# ```css
|
166
193
|
# @media(max-width: 600px) { .col-6 { display: block; } .col-12 { display: block; } }
|
167
194
|
# @media(max-width: 400px) { .col-12 { display: inline-block; } }
|
195
|
+
# ```
|
196
|
+
#
|
197
|
+
#
|
168
198
|
# which would change the styling on the page
|
169
199
|
# (before it would've yielded display: block; for .col-12 at max-width: 600px
|
170
200
|
# and now it yields inline-block;)
|
171
201
|
#
|
172
202
|
# If merge_media_queries is set to false,
|
173
|
-
# we will generate
|
203
|
+
# we will generate `style_blocks.size` media queries, potentially
|
174
204
|
# causing performance issues.
|
175
205
|
# @param {Array<StyleBlock>} style_blocks All style blocks
|
176
206
|
# @return {Array<String>}
|
177
207
|
def styles_in_individual_media_queries(style_blocks)
|
178
208
|
style_blocks.map do |css_rule|
|
179
|
-
if css_rule.media == [
|
209
|
+
if css_rule.media == ["all"]
|
180
210
|
css_rule
|
181
211
|
else
|
182
|
-
"@media #{css_rule.media.join(
|
212
|
+
"@media #{css_rule.media.join(", ")} {\n#{css_rule}\n}"
|
183
213
|
end
|
184
214
|
end
|
185
215
|
end
|
@@ -7,13 +7,10 @@ module Roadie
|
|
7
7
|
# This class will improve the following aspects of the DOM:
|
8
8
|
# * A HTML5 doctype will be added if missing, other doctypes will be left as-is.
|
9
9
|
# * Basic HTML elements will be added if missing.
|
10
|
-
# *
|
11
|
-
# *
|
12
|
-
# *
|
13
|
-
# *
|
14
|
-
#
|
15
|
-
# @note Due to a Nokogiri bug, the HTML5 doctype cannot be added under JRuby. No doctype is outputted under JRuby.
|
16
|
-
# See https://github.com/sparklemotion/nokogiri/issues/984
|
10
|
+
# * `<html>`
|
11
|
+
# * `<head>`
|
12
|
+
# * `<body>`
|
13
|
+
# * `<meta>` declaring charset and content-type (text/html)
|
17
14
|
class MarkupImprover
|
18
15
|
# The original HTML must also be passed in in order to handle the doctypes
|
19
16
|
# since a +Nokogiri::HTML::Document+ will always have a doctype, no matter if
|
@@ -33,45 +30,39 @@ module Roadie
|
|
33
30
|
end
|
34
31
|
|
35
32
|
protected
|
33
|
+
|
36
34
|
attr_reader :dom
|
37
35
|
|
38
36
|
private
|
37
|
+
|
39
38
|
def ensure_doctype_present
|
40
|
-
return if
|
41
|
-
return if @html.include?('<!DOCTYPE ')
|
39
|
+
return if @html.include?("<!DOCTYPE ")
|
42
40
|
# Nokogiri adds a "default" doctype to the DOM, which we will remove
|
43
|
-
dom.internal_subset
|
44
|
-
dom.create_internal_subset
|
45
|
-
end
|
46
|
-
|
47
|
-
# JRuby up to at least 1.6.0 has a bug where the doctype of a document cannot be changed.
|
48
|
-
# See https://github.com/sparklemotion/nokogiri/issues/984
|
49
|
-
def uses_buggy_jruby?
|
50
|
-
# No reason to check for version yet since no existing version has a fix.
|
51
|
-
defined?(JRuby)
|
41
|
+
dom.internal_subset&.remove
|
42
|
+
dom.create_internal_subset "html", nil, nil
|
52
43
|
end
|
53
44
|
|
54
45
|
def ensure_html_element_present
|
55
|
-
return if dom.at_xpath(
|
56
|
-
html = Nokogiri::XML::Node.new
|
46
|
+
return if dom.at_xpath("html")
|
47
|
+
html = Nokogiri::XML::Node.new "html", dom
|
57
48
|
dom << html
|
58
49
|
end
|
59
50
|
|
60
51
|
def ensure_head_element_present
|
61
|
-
if (head = dom.at_xpath(
|
52
|
+
if (head = dom.at_xpath("html/head"))
|
62
53
|
head
|
63
54
|
else
|
64
|
-
create_head_element dom.at_xpath(
|
55
|
+
create_head_element dom.at_xpath("html")
|
65
56
|
end
|
66
57
|
end
|
67
58
|
|
68
59
|
def create_head_element(parent)
|
69
|
-
head = Nokogiri::XML::Node.new
|
70
|
-
|
60
|
+
head = Nokogiri::XML::Node.new "head", dom
|
61
|
+
if parent.children.empty?
|
62
|
+
parent << head
|
63
|
+
else
|
71
64
|
# Crashes when no children are present
|
72
65
|
parent.children.before head
|
73
|
-
else
|
74
|
-
parent << head
|
75
66
|
end
|
76
67
|
head
|
77
68
|
end
|
@@ -83,15 +74,15 @@ module Roadie
|
|
83
74
|
end
|
84
75
|
|
85
76
|
def content_type_meta_element_missing?
|
86
|
-
dom.xpath(
|
87
|
-
meta[
|
77
|
+
dom.xpath("html/head/meta").none? do |meta|
|
78
|
+
meta["http-equiv"].to_s.downcase == "content-type"
|
88
79
|
end
|
89
80
|
end
|
90
81
|
|
91
82
|
def make_content_type_element
|
92
|
-
meta = Nokogiri::XML::Node.new(
|
93
|
-
meta[
|
94
|
-
meta[
|
83
|
+
meta = Nokogiri::XML::Node.new("meta", dom)
|
84
|
+
meta["http-equiv"] = "Content-Type"
|
85
|
+
meta["content"] = "text/html; charset=UTF-8"
|
95
86
|
meta
|
96
87
|
end
|
97
88
|
end
|