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 +4 -4
- data/lib/html_proofer/url_validator/internal.rb +54 -12
- data/lib/html_proofer/version.rb +1 -1
- data/lib/html_proofer.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4043366fa1c0d7aaa58fc0b577d25d2d0fba7e72afca2b43ae688e90c55dddef
|
4
|
+
data.tar.gz: a93621d2169757d3665e5950e8c99d23a1b64cc9014fbc806a986fcdcb906e26
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
-
|
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
|
-
|
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?(
|
60
|
-
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[
|
97
|
+
@runner.checked_paths[absolute_path] = File.exist?(absolute_path)
|
64
98
|
end
|
65
99
|
|
66
|
-
# verify the target
|
67
|
-
|
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")
|
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,
|
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
|
data/lib/html_proofer/version.rb
CHANGED
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.
|
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-
|
11
|
+
date: 2022-09-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|