roadie 4.0.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
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