html-proofer 4.0.0.rc2 → 4.0.1
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.
- checksums.yaml +4 -4
- data/bin/htmlproofer +3 -2
- data/lib/html-proofer.rb +1 -1
- data/lib/html_proofer/attribute/url.rb +186 -174
- data/lib/html_proofer/cache.rb +128 -85
- data/lib/html_proofer/check/favicon.rb +29 -24
- data/lib/html_proofer/check/images.rb +78 -47
- data/lib/html_proofer/check/links.rb +109 -98
- data/lib/html_proofer/check/open_graph.rb +30 -25
- data/lib/html_proofer/check/scripts.rb +36 -28
- data/lib/html_proofer/check.rb +11 -10
- data/lib/html_proofer/configuration.rb +16 -15
- data/lib/html_proofer/element.rb +19 -19
- data/lib/html_proofer/log.rb +19 -19
- data/lib/html_proofer/reporter/cli.rb +22 -18
- data/lib/html_proofer/reporter.rb +3 -3
- data/lib/html_proofer/runner.rb +45 -44
- data/lib/html_proofer/url_validator/external.rb +157 -152
- data/lib/html_proofer/url_validator/internal.rb +72 -62
- data/lib/html_proofer/utils.rb +5 -5
- data/lib/html_proofer/version.rb +1 -1
- data/lib/html_proofer.rb +11 -10
- metadata +22 -7
@@ -1,86 +1,96 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module HTMLProofer
|
4
|
-
class UrlValidator
|
5
|
-
|
4
|
+
class UrlValidator
|
5
|
+
class Internal < UrlValidator
|
6
|
+
attr_reader :internal_urls
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
def initialize(runner, internal_urls)
|
9
|
+
super(runner)
|
9
10
|
|
10
|
-
|
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
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
-
|
33
|
-
|
34
|
-
@cache.add_internal(url.to_s, metadata, false)
|
35
|
-
next
|
36
|
-
end
|
22
|
+
@failed_checks
|
23
|
+
end
|
37
24
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
-
|
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
|
-
|
49
|
-
|
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
|
-
|
52
|
-
|
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
|
-
|
56
|
-
|
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
|
-
|
59
|
-
|
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
|
-
|
64
|
-
|
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
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
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
|
-
|
73
|
-
|
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
|
data/lib/html_proofer/utils.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
File.read(path)
|
18
|
+
else
|
19
|
+
path
|
20
|
+
end
|
21
21
|
|
22
22
|
Nokogiri::HTML5(content, max_errors: -1)
|
23
23
|
end
|
data/lib/html_proofer/version.rb
CHANGED
data/lib/html_proofer.rb
CHANGED
@@ -1,23 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
lib_dir = File.join(File.dirname(__dir__),
|
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
|
-
|
7
|
+
"html_proofer" => "HTMLProofer"
|
8
8
|
)
|
9
|
-
gem_loader.ignore(File.join(lib_dir,
|
9
|
+
gem_loader.ignore(File.join(lib_dir, "html-proofer.rb"))
|
10
10
|
gem_loader.setup
|
11
11
|
|
12
|
-
require
|
12
|
+
require "html_proofer/version"
|
13
13
|
|
14
|
-
require
|
15
|
-
require
|
14
|
+
require "parallel"
|
15
|
+
require "fileutils"
|
16
16
|
|
17
|
-
|
18
|
-
require
|
19
|
-
|
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.
|
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-
|
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.
|
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.
|
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:
|
320
|
+
version: '0'
|
306
321
|
requirements: []
|
307
|
-
rubygems_version: 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
|