html-proofer 4.0.0.rc3 → 4.0.0
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 +180 -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 -9
- metadata +8 -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,21 +1,23 @@
|
|
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
|
-
|
17
|
+
if ENV.fetch("DEBUG", false)
|
18
|
+
require "awesome_print"
|
19
|
+
require "debug"
|
20
|
+
end
|
19
21
|
|
20
22
|
module HTMLProofer
|
21
23
|
def self.check_file(file, options = {})
|
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
|
4
|
+
version: 4.0.0
|
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-11 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
|
@@ -299,6 +299,7 @@ homepage: https://github.com/gjtorikian/html-proofer
|
|
299
299
|
licenses:
|
300
300
|
- MIT
|
301
301
|
metadata:
|
302
|
+
funding_uri: https://github.com/sponsors/gjtorikian/
|
302
303
|
rubygems_mfa_required: 'true'
|
303
304
|
post_install_message:
|
304
305
|
rdoc_options: []
|
@@ -314,11 +315,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
314
315
|
version: '4.0'
|
315
316
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
316
317
|
requirements:
|
317
|
-
- - "
|
318
|
+
- - ">="
|
318
319
|
- !ruby/object:Gem::Version
|
319
|
-
version:
|
320
|
+
version: '0'
|
320
321
|
requirements: []
|
321
|
-
rubygems_version: 3.3.
|
322
|
+
rubygems_version: 3.3.7
|
322
323
|
signing_key:
|
323
324
|
specification_version: 4
|
324
325
|
summary: A set of tests to validate your HTML output. These tests check if your image
|