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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +43 -0
  3. data/.solargraph.yml +16 -0
  4. data/Changelog.md +14 -2
  5. data/Gemfile +5 -2
  6. data/README.md +11 -13
  7. data/Rakefile +2 -2
  8. data/lib/roadie/asset_provider.rb +3 -1
  9. data/lib/roadie/asset_scanner.rb +6 -6
  10. data/lib/roadie/cached_provider.rb +1 -0
  11. data/lib/roadie/deduplicator.rb +1 -0
  12. data/lib/roadie/document.rb +7 -10
  13. data/lib/roadie/errors.rb +18 -14
  14. data/lib/roadie/filesystem_provider.rb +13 -3
  15. data/lib/roadie/inliner.rb +49 -19
  16. data/lib/roadie/markup_improver.rb +22 -31
  17. data/lib/roadie/net_http_provider.rb +25 -11
  18. data/lib/roadie/null_provider.rb +18 -5
  19. data/lib/roadie/null_url_rewriter.rb +6 -2
  20. data/lib/roadie/path_rewriter_provider.rb +4 -1
  21. data/lib/roadie/provider_list.rb +15 -11
  22. data/lib/roadie/rspec/asset_provider.rb +4 -1
  23. data/lib/roadie/rspec.rb +2 -2
  24. data/lib/roadie/selector.rb +15 -5
  25. data/lib/roadie/style_attribute_builder.rb +2 -1
  26. data/lib/roadie/style_block.rb +3 -3
  27. data/lib/roadie/style_property.rb +3 -2
  28. data/lib/roadie/stylesheet.rb +2 -13
  29. data/lib/roadie/url_generator.rb +24 -8
  30. data/lib/roadie/url_rewriter.rb +6 -3
  31. data/lib/roadie/utils.rb +1 -1
  32. data/lib/roadie/version.rb +1 -2
  33. data/lib/roadie.rb +23 -23
  34. data/roadie.gemspec +23 -25
  35. data/spec/hash_as_cache_store_spec.rb +1 -1
  36. data/spec/integration_spec.rb +41 -44
  37. data/spec/lib/roadie/asset_scanner_spec.rb +9 -4
  38. data/spec/lib/roadie/cached_provider_spec.rb +4 -4
  39. data/spec/lib/roadie/css_not_found_spec.rb +8 -5
  40. data/spec/lib/roadie/deduplicator_spec.rb +3 -3
  41. data/spec/lib/roadie/document_spec.rb +45 -27
  42. data/spec/lib/roadie/filesystem_provider_spec.rb +8 -10
  43. data/spec/lib/roadie/inliner_spec.rb +40 -44
  44. data/spec/lib/roadie/markup_improver_spec.rb +17 -25
  45. data/spec/lib/roadie/net_http_provider_spec.rb +8 -8
  46. data/spec/lib/roadie/null_provider_spec.rb +2 -2
  47. data/spec/lib/roadie/null_url_rewriter_spec.rb +2 -2
  48. data/spec/lib/roadie/path_rewriter_provider_spec.rb +4 -4
  49. data/spec/lib/roadie/provider_list_spec.rb +25 -21
  50. data/spec/lib/roadie/selector_spec.rb +4 -4
  51. data/spec/lib/roadie/style_attribute_builder_spec.rb +5 -5
  52. data/spec/lib/roadie/style_block_spec.rb +1 -1
  53. data/spec/lib/roadie/style_property_spec.rb +8 -8
  54. data/spec/lib/roadie/stylesheet_spec.rb +2 -20
  55. data/spec/lib/roadie/test_provider_spec.rb +4 -4
  56. data/spec/lib/roadie/url_generator_spec.rb +1 -1
  57. data/spec/lib/roadie/url_rewriter_spec.rb +6 -4
  58. data/spec/spec_helper.rb +8 -8
  59. data/spec/support/have_attribute_matcher.rb +1 -2
  60. data/spec/support/have_node_matcher.rb +3 -3
  61. data/spec/support/have_selector_matcher.rb +2 -3
  62. data/spec/support/have_styling_matcher.rb +10 -11
  63. data/spec/support/have_xpath_matcher.rb +2 -3
  64. metadata +22 -21
  65. data/.travis.yml +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 17f87e779aab695788d0361a733cd56f81b74d4d89bc9c82eb1949f9bdec1796
4
- data.tar.gz: 608a6d3a482a827123818c45acaf9709f4dd214328809e43d327fd860ce0d455
3
+ metadata.gz: 5ba6c121fdd1072479afeee70b785db020df45cbe3b45350a20f9cfd4f8d0164
4
+ data.tar.gz: bfd6faa52b576fba65b8d2281b213ceabf137f08551749dc842b9a9477566fd2
5
5
  SHA512:
6
- metadata.gz: d512b9c8568ec0514161689fa8cb678d3c975b11ec9b6d9b7b1f31c09ad166788c88e195161b7b101256d229de36dec6abcc77f420dfddd6b663ce82233cdfcd
7
- data.tar.gz: c94e1245d485c0824057868010d849b24b37faf6fd69ab59989a3f6bae0bf02284255550fa67fef79c0355c95a149d1ad34ec9e22b0ecc8b8c1eec6888ae0545
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
@@ -0,0 +1,16 @@
1
+ ---
2
+ include:
3
+ - "**/*.rb"
4
+ exclude:
5
+ - spec/**/*
6
+ - test/**/*
7
+ - vendor/**/*
8
+ - ".bundle/**/*"
9
+ require: []
10
+ domains: []
11
+ plugins:
12
+ - solargraph-standardrb
13
+ reporters:
14
+ - standardrb
15
+ require_paths: []
16
+ max_files: 5000
data/Changelog.md CHANGED
@@ -1,9 +1,21 @@
1
1
  ### dev
2
2
 
3
- [full changelog](https://github.com/Mange/roadie/compare/v4.0.0...master)
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 'https://rubygems.org'
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 'codecov', group: :test, require: false
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
- [![Build history and status](https://travis-ci.org/Mange/roadie.svg?branch=master)](http://travis-ci.org/#!/Mange/roadie)
5
4
  [![Code Climate](https://codeclimate.com/github/Mange/roadie.png)](https://codeclimate.com/github/Mange/roadie)
6
5
  [![Code coverage status](https://codecov.io/github/Mange/roadie/coverage.svg?branch=master)](https://codecov.io/github/Mange/roadie?branch=master)
7
6
  [![Gem](https://img.shields.io/gem/v/roadie.svg)](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 raise Roadie::CssNotFound.new(name, "does not match a user stylesheet", self)
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 [Travis CI](http://travis-ci.org) using:
449
+ Tested with Github CI using:
448
450
 
449
- * MRI 2.1
450
- * MRI 2.2
451
- * MRI 2.3
452
- * MRI 2.4
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
- [(Build status)](http://travis-ci.org/#!/Mange/roadie)
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-2018 Magnus Bergmark, Jim Neath / Purify, and contributors.
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
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'bundler/setup'
3
+ require "bundler/setup"
4
4
 
5
5
  Bundler::GemHelper.install_tasks
6
6
 
@@ -10,4 +10,4 @@ task :spec do
10
10
  end
11
11
 
12
12
  desc "Default: Run specs"
13
- task :default => :spec
13
+ task default: :spec
@@ -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 CssNotFound.new(name, nil, self)
10
+ find_stylesheet(name) or raise(
11
+ CssNotFound.new(css_name: name, provider: self)
12
+ )
11
13
  end
12
14
  end
13
15
  end
@@ -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
- stylesheets = @dom.css(STYLE_ELEMENT_QUERY).map { |element|
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['media'] != "print" && element["href"]
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['href'] if should_find_external?
89
+ external_asset_provider.find_stylesheet! element["href"] if should_find_external?
90
90
  else
91
- normal_asset_provider.find_stylesheet! element['href']
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?
@@ -69,6 +69,7 @@ module Roadie
69
69
  end
70
70
 
71
71
  private
72
+
72
73
  def cache_fetch(name)
73
74
  cache[name] || cache[name] = yield
74
75
  rescue CssNotFound
@@ -26,6 +26,7 @@ module Roadie
26
26
  end
27
27
 
28
28
  private
29
+
29
30
  attr_reader :input, :latest_occurance
30
31
 
31
32
  def has_duplicates?
@@ -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
- VALID_MODES = %i[html xhtml].freeze
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
- # Arity checking is to support the API without bumping a major version.
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
- cause_message = " Caused by: #{cause}"
21
+ cause_message = if cause
22
+ " Caused by: #{cause}"
23
23
  else
24
- cause_message = ""
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
- # TODO: Change signature in the next major version of Roadie.
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 = extra_message
51
- super build_message(extra_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 || message}"
56
+ "#{provider || "Unknown provider"}: #{extra_message}"
57
57
  end
58
58
 
59
59
  private
60
- # Redundant method argument is to keep API compatability without major version bump.
61
- # TODO: Remove argument on version 4.0.
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, provider_list, errors)
72
+ def initialize(css_name:, providers:, errors:)
74
73
  @errors = errors
75
- super(css_name, "All providers failed", provider_list)
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
- def build_message(extra_message)
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(basename, %{#{file_path} does not exist. (Original name was "#{name}")}, self)
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() inspect end
40
- def inspect() "#<#{self.class} #@path>" end
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[/^([^?]+)/])
@@ -1,21 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'set'
4
- require 'nokogiri'
5
- require 'uri'
6
- require 'css_parser'
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
- # a { color: red; } # StyleBlock
14
- # <a href="/"></a> # DOM
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
- # <a href="/" style="color:red"></a>
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 => error
95
- Utils.warn "Cannot inline #{selector.inspect} from \"#{stylesheet.name}\" stylesheet. If this is valid CSS, please report a bug."
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 "Got error when looking for #{selector.inspect} (from \"#{stylesheet.name}\" stylesheet): #{error}"
99
- raise unless error.message.include?('XPath')
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('html/head')
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('style', parent.document)
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
- # Example result: ["@media(max-width: 600px) { .col-12 { display: block; } }"]
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 == ['all']
172
+ if media_types == ["all"]
152
173
  css_rules
153
174
  else
154
- "@media #{media_types.join(', ')} {\n#{css_rules}\n}"
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 #{style_blocks.size} media queries, potentially
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 == ['all']
209
+ if css_rule.media == ["all"]
180
210
  css_rule
181
211
  else
182
- "@media #{css_rule.media.join(', ')} {\n#{css_rule}\n}"
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
- # * +<html>+
11
- # * +<head>+
12
- # * +<body>+
13
- # * +<meta>+ declaring charset and content-type (text/html)
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 uses_buggy_jruby?
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.remove unless dom.internal_subset.nil?
44
- dom.create_internal_subset 'html', nil, nil
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('html')
56
- html = Nokogiri::XML::Node.new 'html', dom
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('html/head'))
52
+ if (head = dom.at_xpath("html/head"))
62
53
  head
63
54
  else
64
- create_head_element dom.at_xpath('html')
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 'head', dom
70
- unless parent.children.empty?
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('html/head/meta').none? do |meta|
87
- meta['http-equiv'].to_s.downcase == 'content-type'
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('meta', dom)
93
- meta['http-equiv'] = 'Content-Type'
94
- meta['content'] = 'text/html; charset=UTF-8'
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