html-proofer 4.0.0.rc2 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,86 +1,96 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTMLProofer
4
- class UrlValidator::Internal < UrlValidator
5
- attr_reader :internal_urls
4
+ class UrlValidator
5
+ class Internal < UrlValidator
6
+ attr_reader :internal_urls
6
7
 
7
- def initialize(runner, internal_urls)
8
- super(runner)
8
+ def initialize(runner, internal_urls)
9
+ super(runner)
9
10
 
10
- @internal_urls = internal_urls
11
- end
12
-
13
- def validate
14
- if @cache.enabled?
15
- urls_to_check = @runner.load_internal_cache
16
- run_internal_link_checker(urls_to_check)
17
- else
18
- run_internal_link_checker(@internal_urls)
11
+ @internal_urls = internal_urls
19
12
  end
20
13
 
21
- @failed_checks
22
- end
23
-
24
- def run_internal_link_checker(links)
25
- links.each_pair do |link, matched_files|
26
- matched_files.each do |metadata|
27
- url = HTMLProofer::Attribute::Url.new(@runner, link, base_url: metadata[:base_url])
28
-
29
- @runner.current_source = metadata[:source]
30
- @runner.current_path = metadata[:current_path]
14
+ def validate
15
+ if @cache.enabled?
16
+ urls_to_check = @runner.load_internal_cache
17
+ run_internal_link_checker(urls_to_check)
18
+ else
19
+ run_internal_link_checker(@internal_urls)
20
+ end
31
21
 
32
- unless file_exists?(url)
33
- @failed_checks << Failure.new(@runner.current_path, 'Links > Internal', "internally linking to #{url}, which does not exist", line: metadata[:line], status: nil, content: nil)
34
- @cache.add_internal(url.to_s, metadata, false)
35
- next
36
- end
22
+ @failed_checks
23
+ end
37
24
 
38
- unless hash_exists?(url)
39
- @failed_checks << Failure.new(@runner.current_path, 'Links > Internal', "internally linking to #{url}; the file exists, but the hash '#{url.hash}' does not", line: metadata[:line], status: nil, content: nil)
40
- @cache.add_internal(url.to_s, metadata, false)
41
- next
25
+ def run_internal_link_checker(links)
26
+ to_add = []
27
+ links.each_pair do |link, matched_files|
28
+ matched_files.each do |metadata|
29
+ url = HTMLProofer::Attribute::Url.new(@runner, link, base_url: metadata[:base_url])
30
+
31
+ @runner.current_source = metadata[:source]
32
+ @runner.current_filename = metadata[:filename]
33
+
34
+ unless file_exists?(url)
35
+ @failed_checks << Failure.new(@runner.current_filename, "Links > Internal",
36
+ "internally linking to #{url}, which does not exist", line: metadata[:line], status: nil, content: nil)
37
+ to_add << [url, metadata, false]
38
+ next
39
+ end
40
+
41
+ unless hash_exists?(url)
42
+ @failed_checks << Failure.new(@runner.current_filename, "Links > Internal",
43
+ "internally linking to #{url}; the file exists, but the hash '#{url.hash}' does not", line: metadata[:line], status: nil, content: nil)
44
+ to_add << [url, metadata, false]
45
+ next
46
+ end
47
+
48
+ to_add << [url, metadata, true]
42
49
  end
50
+ end
43
51
 
44
- @cache.add_internal(url.to_s, metadata, true)
52
+ # adding directly to the cache above results in an endless loop
53
+ to_add.each do |(url, metadata, exists)|
54
+ @cache.add_internal(url.to_s, metadata, exists)
45
55
  end
56
+
57
+ @failed_checks
46
58
  end
47
59
 
48
- @failed_checks
49
- end
60
+ private def file_exists?(url)
61
+ absolute_path = url.absolute_path
62
+ return @runner.checked_paths[url.absolute_path] if @runner.checked_paths.key?(absolute_path)
50
63
 
51
- private def file_exists?(url)
52
- absolute_path = url.absolute_path
53
- return @runner.checked_paths[url.absolute_path] if @runner.checked_paths.key?(absolute_path)
64
+ @runner.checked_paths[url.absolute_path] = File.exist?(absolute_path)
65
+ end
54
66
 
55
- @runner.checked_paths[url.absolute_path] = File.exist?(absolute_path)
56
- end
67
+ # verify the target hash
68
+ private def hash_exists?(url)
69
+ href_hash = url.hash
70
+ return true if blank?(href_hash)
57
71
 
58
- # verify the target hash
59
- private def hash_exists?(url)
60
- href_hash = url.hash
61
- return true if blank?(href_hash)
72
+ # prevents searching files we didn't ask about
73
+ return false unless url.known_extension?
62
74
 
63
- # prevents searching files we didn't ask about
64
- return false unless url.known_extension?
75
+ decoded_href_hash = Addressable::URI.unescape(href_hash)
76
+ fragment_ids = [href_hash, decoded_href_hash]
77
+ # https://www.w3.org/TR/html5/single-page.html#scroll-to-fragid
78
+ fragment_ids.include?("top") || !find_fragments(fragment_ids, url).empty?
79
+ end
65
80
 
66
- decoded_href_hash = Addressable::URI.unescape(href_hash)
67
- fragment_ids = [href_hash, decoded_href_hash]
68
- # https://www.w3.org/TR/html5/single-page.html#scroll-to-fragid
69
- fragment_ids.include?('top') || !find_fragments(fragment_ids, url).empty?
70
- end
81
+ private def find_fragments(fragment_ids, url)
82
+ xpaths = fragment_ids.uniq.flat_map do |frag_id|
83
+ escaped_frag_id = "'#{frag_id.split("'").join("', \"'\", '")}', ''"
84
+ [
85
+ "//*[case_sensitive_equals(@id, concat(#{escaped_frag_id}))]",
86
+ "//*[case_sensitive_equals(@name, concat(#{escaped_frag_id}))]",
87
+ ]
88
+ end
89
+ xpaths << XpathFunctions.new
71
90
 
72
- private def find_fragments(fragment_ids, url)
73
- xpaths = fragment_ids.uniq.flat_map do |frag_id|
74
- escaped_frag_id = "'#{frag_id.split("'").join("', \"'\", '")}', ''"
75
- [
76
- "//*[case_sensitive_equals(@id, concat(#{escaped_frag_id}))]",
77
- "//*[case_sensitive_equals(@name, concat(#{escaped_frag_id}))]"
78
- ]
91
+ html = create_nokogiri(url.absolute_path)
92
+ html.xpath(*xpaths)
79
93
  end
80
- xpaths << XpathFunctions.new
81
-
82
- html = create_nokogiri(url.absolute_path)
83
- html.xpath(*xpaths)
84
94
  end
85
95
  end
86
96
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'nokogiri'
3
+ require "nokogiri"
4
4
 
5
5
  module HTMLProofer
6
6
  module Utils
@@ -14,10 +14,10 @@ module HTMLProofer
14
14
 
15
15
  def create_nokogiri(path)
16
16
  content = if File.exist?(path) && !File.directory?(path)
17
- File.read(path)
18
- else
19
- path
20
- end
17
+ File.read(path)
18
+ else
19
+ path
20
+ end
21
21
 
22
22
  Nokogiri::HTML5(content, max_errors: -1)
23
23
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTMLProofer
4
- VERSION = '4.0.0.rc2'
4
+ VERSION = "4.0.1"
5
5
  end
data/lib/html_proofer.rb CHANGED
@@ -1,23 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'zeitwerk'
4
- lib_dir = File.join(File.dirname(__dir__), 'lib')
3
+ require "zeitwerk"
4
+ lib_dir = File.join(File.dirname(__dir__), "lib")
5
5
  gem_loader = Zeitwerk::Loader.for_gem
6
6
  gem_loader.inflector.inflect(
7
- 'html_proofer' => 'HTMLProofer'
7
+ "html_proofer" => "HTMLProofer"
8
8
  )
9
- gem_loader.ignore(File.join(lib_dir, 'html-proofer.rb'))
9
+ gem_loader.ignore(File.join(lib_dir, "html-proofer.rb"))
10
10
  gem_loader.setup
11
11
 
12
- require 'html_proofer/version'
12
+ require "html_proofer/version"
13
13
 
14
- require 'parallel'
15
- require 'fileutils'
14
+ require "parallel"
15
+ require "fileutils"
16
16
 
17
- %w[awesome_print debug].each do |gem|
18
- require gem
19
- rescue LoadError; # rubocop:disable Lint/SuppressedException
17
+ if ENV.fetch("DEBUG", false)
18
+ require "awesome_print"
19
+ require "debug"
20
20
  end
21
+
21
22
  module HTMLProofer
22
23
  def self.check_file(file, options = {})
23
24
  raise ArgumentError unless file.is_a?(String)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: html-proofer
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0.rc2
4
+ version: 4.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Garen Torikian
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-06 00:00:00.000000000 Z
11
+ date: 2022-07-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.12'
47
+ version: '1.13'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.12'
54
+ version: '1.13'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: parallel
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: debug
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
139
153
  - !ruby/object:Gem::Dependency
140
154
  name: rake
141
155
  requirement: !ruby/object:Gem::Requirement
@@ -285,6 +299,7 @@ homepage: https://github.com/gjtorikian/html-proofer
285
299
  licenses:
286
300
  - MIT
287
301
  metadata:
302
+ funding_uri: https://github.com/sponsors/gjtorikian/
288
303
  rubygems_mfa_required: 'true'
289
304
  post_install_message:
290
305
  rdoc_options: []
@@ -300,11 +315,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
300
315
  version: '4.0'
301
316
  required_rubygems_version: !ruby/object:Gem::Requirement
302
317
  requirements:
303
- - - ">"
318
+ - - ">="
304
319
  - !ruby/object:Gem::Version
305
- version: 1.3.1
320
+ version: '0'
306
321
  requirements: []
307
- rubygems_version: 3.3.3
322
+ rubygems_version: 3.3.7
308
323
  signing_key:
309
324
  specification_version: 4
310
325
  summary: A set of tests to validate your HTML output. These tests check if your image