html-proofer 4.4.0 → 4.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 98bde6dd5e32f42e5983fd1aaa7bf02d3359b40f2b4a8b5360a5826abf2cc674
4
- data.tar.gz: 9b7d57fd18e625ab7cc91c46faceac510b05ba5290f665fb5dd333b92446b00b
3
+ metadata.gz: 4043366fa1c0d7aaa58fc0b577d25d2d0fba7e72afca2b43ae688e90c55dddef
4
+ data.tar.gz: a93621d2169757d3665e5950e8c99d23a1b64cc9014fbc806a986fcdcb906e26
5
5
  SHA512:
6
- metadata.gz: a666be806bbb70028488b3ef89f1325d7b5faaec9f48e105220db2d2f7dd022c12dabac828949ffd2100bdc2b4e3bd4c1f9ce9df48bab17b9106d9453eb49f01
7
- data.tar.gz: 8a58bb5b120ab3cf3eb0e692f3f52f4385bd5923d3a7c91e95dddd17d8b0e25d20dd207872099665ac37737afb6b4ed86d04d39bc7793c6af2abcd35390d2051
6
+ metadata.gz: 1636df520fa7d4035ca482eeafd0b5e059b0fc77a0219f340e7c47b8f2105c8dd107bf03e0d78ca582f5d7abef9d5853edae498a2133b75eab6f92b7e77b636f
7
+ data.tar.gz: 5310df2250a5db3c8864b12ae01e49a0a2d043fc15f5bece45615cbad1d2b9100c899fa35902db5536b2be85908f9208ebfe65e31318cf6a6db47e945a745f17
@@ -22,22 +22,39 @@ module HTMLProofer
22
22
  end
23
23
 
24
24
  def run_internal_link_checker(links)
25
+ # collect urls and metadata for hashes to be checked in the same target file
26
+ file_paths_hashes_to_check = {}
25
27
  to_add = []
26
- links.each_pair do |link, matched_files|
28
+ links.each_with_index do |(link, matched_files), i|
29
+ matched_count_to_log = pluralize(matched_files.count, "reference", "references")
30
+ @logger.log(:debug, "(#{i + 1} / #{links.count}) Internal link #{link}: Checking #{matched_count_to_log}")
27
31
  matched_files.each do |metadata|
28
32
  url = HTMLProofer::Attribute::Url.new(@runner, link, base_url: metadata[:base_url])
29
33
 
30
34
  @runner.current_source = metadata[:source]
31
35
  @runner.current_filename = metadata[:filename]
32
36
 
33
- unless file_exists?(url)
37
+ target_file_path = url.absolute_path
38
+ unless file_exists?(target_file_path)
34
39
  @failed_checks << Failure.new(@runner.current_filename, "Links > Internal",
35
40
  "internally linking to #{url}, which does not exist", line: metadata[:line], status: nil, content: nil)
36
41
  to_add << [url, metadata, false]
37
42
  next
38
43
  end
39
44
 
40
- unless hash_exists?(url)
45
+ hash_exists = hash_exists_for_url?(url)
46
+ if hash_exists.nil?
47
+ # the hash needs to be checked in the target file, we collect the url and metadata
48
+ unless file_paths_hashes_to_check.key?(target_file_path)
49
+ file_paths_hashes_to_check[target_file_path] = {}
50
+ end
51
+ unless file_paths_hashes_to_check[target_file_path].key?(url.hash)
52
+ file_paths_hashes_to_check[target_file_path][url.hash] = []
53
+ end
54
+ file_paths_hashes_to_check[target_file_path][url.hash] << [url, metadata]
55
+ next
56
+ end
57
+ unless hash_exists
41
58
  @failed_checks << Failure.new(@runner.current_filename, "Links > Internal",
42
59
  "internally linking to #{url}; the file exists, but the hash '#{url.hash}' does not", line: metadata[:line], status: nil, content: nil)
43
60
  to_add << [url, metadata, false]
@@ -48,6 +65,24 @@ module HTMLProofer
48
65
  end
49
66
  end
50
67
 
68
+ # check hashes by target file
69
+ @logger.log(:info, "Checking internal link hashes in #{pluralize(file_paths_hashes_to_check.count, "file", "files")}")
70
+ file_paths_hashes_to_check.each_with_index do |(file_path, hashes_to_check), i|
71
+ hash_count_to_log = pluralize(hashes_to_check.count, "hash", "hashes")
72
+ @logger.log(:debug, "(#{i + 1} / #{file_paths_hashes_to_check.count}) Checking #{hash_count_to_log} in #{file_path}")
73
+ html = create_nokogiri(file_path)
74
+ hashes_to_check.each_pair do |href_hash, url_metadata|
75
+ exists = hash_exists_in_html?(href_hash, html)
76
+ url_metadata.each do |(url, metadata)|
77
+ unless exists
78
+ @failed_checks << Failure.new(metadata[:filename], "Links > Internal",
79
+ "internally linking to #{url}; the file exists, but the hash '#{href_hash}' does not", line: metadata[:line], status: nil, content: nil)
80
+ end
81
+ to_add << [url, metadata, exists]
82
+ end
83
+ end
84
+ end
85
+
51
86
  # adding directly to the cache above results in an endless loop
52
87
  to_add.each do |(url, metadata, exists)|
53
88
  @cache.add_internal(url.to_s, metadata, exists)
@@ -56,15 +91,15 @@ module HTMLProofer
56
91
  @failed_checks
57
92
  end
58
93
 
59
- private def file_exists?(url)
60
- absolute_path = url.absolute_path
61
- return @runner.checked_paths[url.absolute_path] if @runner.checked_paths.key?(absolute_path)
94
+ private def file_exists?(absolute_path)
95
+ return @runner.checked_paths[absolute_path] if @runner.checked_paths.key?(absolute_path)
62
96
 
63
- @runner.checked_paths[url.absolute_path] = File.exist?(absolute_path)
97
+ @runner.checked_paths[absolute_path] = File.exist?(absolute_path)
64
98
  end
65
99
 
66
- # verify the target hash
67
- private def hash_exists?(url)
100
+ # verify the hash w/o just based on the URL, w/o looking at the target file
101
+ # => returns nil if the has could not be verified
102
+ private def hash_exists_for_url?(url)
68
103
  href_hash = url.hash
69
104
  return true if blank?(href_hash)
70
105
  return true unless @runner.options[:check_internal_hash]
@@ -76,10 +111,18 @@ module HTMLProofer
76
111
  decoded_href_hash = Addressable::URI.unescape(href_hash)
77
112
  fragment_ids = [href_hash, decoded_href_hash]
78
113
  # https://www.w3.org/TR/html5/single-page.html#scroll-to-fragid
79
- fragment_ids.include?("top") || !find_fragments(fragment_ids, url).empty?
114
+ return true if fragment_ids.include?("top")
115
+
116
+ nil
117
+ end
118
+
119
+ private def hash_exists_in_html?(href_hash, html)
120
+ decoded_href_hash = Addressable::URI.unescape(href_hash)
121
+ fragment_ids = [href_hash, decoded_href_hash]
122
+ !find_fragments(fragment_ids, html).empty?
80
123
  end
81
124
 
82
- private def find_fragments(fragment_ids, url)
125
+ private def find_fragments(fragment_ids, html)
83
126
  xpaths = fragment_ids.uniq.flat_map do |frag_id|
84
127
  escaped_frag_id = "'#{frag_id.split("'").join("', \"'\", '")}', ''"
85
128
  [
@@ -89,7 +132,6 @@ module HTMLProofer
89
132
  end
90
133
  xpaths << XpathFunctions.new
91
134
 
92
- html = create_nokogiri(url.absolute_path)
93
135
  html.xpath(*xpaths)
94
136
  end
95
137
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTMLProofer
4
- VERSION = "4.4.0"
4
+ VERSION = "4.4.1"
5
5
  end
data/lib/html_proofer.rb CHANGED
@@ -4,7 +4,7 @@ require "zeitwerk"
4
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
9
  gem_loader.ignore(File.join(lib_dir, "html-proofer.rb"))
10
10
  gem_loader.setup
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.4.0
4
+ version: 4.4.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-08-13 00:00:00.000000000 Z
11
+ date: 2022-09-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable