html-proofer 3.14.1 → 3.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/htmlproofer +12 -6
- data/lib/html-proofer.rb +2 -2
- data/lib/html-proofer/cache.rb +1 -2
- data/lib/html-proofer/check.rb +3 -2
- data/lib/html-proofer/check/html.rb +23 -14
- data/lib/html-proofer/check/links.rb +1 -1
- data/lib/html-proofer/check/opengraph.rb +4 -4
- data/lib/html-proofer/configuration.rb +4 -1
- data/lib/html-proofer/element.rb +21 -14
- data/lib/html-proofer/log.rb +15 -11
- data/lib/html-proofer/middleware.rb +4 -3
- data/lib/html-proofer/runner.rb +23 -3
- data/lib/html-proofer/url_validator.rb +6 -1
- data/lib/html-proofer/utils.rb +2 -11
- data/lib/html-proofer/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39ffac5e6c23ab7b75d99dd69779be2109ed8b02dc4a5cb0a33740119cb66766
|
4
|
+
data.tar.gz: cdaf142dfde936fa1d88d410499c04fdbbb3b9814bc00ba6800ff3edb8acee50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34a4253b2eb9674060583c0f9006f9c36204bfd8bbb3e347293874e8db3248153e1efcdb13cbb9a5fc7967aabe478773a6a33c3c2372b4e819ecc0c41af43f36
|
7
|
+
data.tar.gz: 34530aeb5fb2836568aa5f7ebea7f154ef8e58c82ac0803aeba5632f704e7aed6c8111a095546c56b1331fa3dc1b563b08eac7cff0205aee4056815ebd8a6478
|
data/bin/htmlproofer
CHANGED
@@ -20,13 +20,13 @@ Mercenary.program(:htmlproofer) do |p|
|
|
20
20
|
p.option 'as_links', '--as-links', 'Assumes that `PATH` is a comma-separated array of links to check.'
|
21
21
|
p.option 'alt_ignore', '--alt-ignore image1,[image2,...]', Array, 'A comma-separated list of Strings or RegExps containing `img`s whose missing `alt` tags are safe to ignore'
|
22
22
|
p.option 'assume_extension', '--assume-extension', 'Automatically add extension (e.g. `.html`) to file paths, to allow extensionless URLs (as supported by Jekyll 3 and GitHub Pages) (default: `false`).'
|
23
|
-
p.option 'checks_to_ignore', '--checks-to-ignore check1,[check2,...]', Array, '
|
23
|
+
p.option 'checks_to_ignore', '--checks-to-ignore check1,[check2,...]', Array, 'A comma-separated list of Strings indicating which checks you do not want to run (default: `[]`)'
|
24
24
|
p.option 'check_external_hash', '--check-external-hash', 'Checks whether external hashes exist (even if the webpage exists). This slows the checker down (default: `false`).'
|
25
25
|
p.option 'check_favicon', '--check-favicon', 'Enables the favicon checker (default: `false`).'
|
26
|
-
p.option 'check_html', '--check-html', 'Enables HTML validation errors from
|
26
|
+
p.option 'check_html', '--check-html', 'Enables HTML validation errors from Nokogumbo (default: `false`).'
|
27
27
|
p.option 'check_img_http', '--check-img-http', 'Fails an image if it\'s marked as `http` (default: `false`).'
|
28
28
|
p.option 'check_opengraph', '--check-opengraph', 'Enables the Open Graph checker (default: `false`).'
|
29
|
-
p.option 'check_sri', '--check-sri', 'Check that `<link>` and `<script>` external resources
|
29
|
+
p.option 'check_sri', '--check-sri', 'Check that `<link>` and `<script>` external resources use SRI (default: `false`).'
|
30
30
|
p.option 'directory_index_file', '--directory-index-file <filename>', String, 'Sets the file to look for when a link refers to a directory. (default: `index.html`)'
|
31
31
|
p.option 'disable_external', '--disable-external', 'If `true`, does not run the external link checker, which can take a lot of time (default: `false`)'
|
32
32
|
p.option 'empty_alt_ignore', '--empty-alt-ignore', 'If `true`, ignores images with empty alt tags'
|
@@ -37,9 +37,12 @@ Mercenary.program(:htmlproofer) do |p|
|
|
37
37
|
p.option 'file_ignore', '--file-ignore file1,[file2,...]', Array, 'A comma-separated list of Strings or RegExps containing file paths that are safe to ignore'
|
38
38
|
p.option 'http_status_ignore', '--http-status-ignore 123,[xxx, ...]', Array, 'A comma-separated list of numbers representing status codes to ignore.'
|
39
39
|
p.option 'internal_domains', '--internal-domains domain1,[domain2,...]', Array, 'A comma-separated list of Strings containing domains that will be treated as internal urls.'
|
40
|
-
p.option 'report_invalid_tags', '--report-invalid-tags', '
|
41
|
-
p.option 'report_missing_names', '--report-missing-names', '
|
42
|
-
p.option 'report_script_embeds', '--report-script-embeds', '
|
40
|
+
p.option 'report_invalid_tags', '--report-invalid-tags', 'When `check_html` is enabled, HTML markup that is unknown to Nokogumbo are reported as errors (default: `false`)'
|
41
|
+
p.option 'report_missing_names', '--report-missing-names', 'When `check_html` is enabled, HTML markup that are missing entity names are reported as errors (default: `false`)'
|
42
|
+
p.option 'report_script_embeds', '--report-script-embeds', 'When `check_html` is enabled, `script` tags containing markup are reported as errors (default: `false`)'
|
43
|
+
p.option 'report_missing_doctype', '--report-missing-doctype', 'When `check_html` is enabled, HTML markup with missing or out-of-order `DOCTYPE` are reported as errors (default: `false`)'
|
44
|
+
p.option 'report_eof_tags', '--report-eof-tags', 'When `check_html` is enabled, HTML markup with tags that are malformed are reported as errors (default: `false`)'
|
45
|
+
p.option 'report_mismatched_tags', '--report-mismatched-tags', 'When `check_html` is enabled, HTML markup with mismatched tags are reported as errors (default: `false`)'
|
43
46
|
p.option 'log_level', '--log-level <level>', String, 'Sets the logging level, as determined by Yell. One of `:debug`, `:info`, `:warn`, `:error`, or `:fatal`. (default: `:info`)'
|
44
47
|
p.option 'only_4xx', '--only-4xx', 'Only reports errors for links that fall within the 4xx status code range'
|
45
48
|
p.option 'storage_dir', '--storage-dir PATH', String, 'Directory where to store the cache log (default: "tmp/.htmlproofer")'
|
@@ -80,6 +83,9 @@ Mercenary.program(:htmlproofer) do |p|
|
|
80
83
|
options[:validation][:report_script_embeds] = opts['report_script_embeds'] unless opts['report_script_embeds'].nil?
|
81
84
|
options[:validation][:report_missing_names] = opts['report_missing_names'] unless opts['report_missing_names'].nil?
|
82
85
|
options[:validation][:report_invalid_tags] = opts['report_invalid_tags'] unless opts['report_invalid_tags'].nil?
|
86
|
+
options[:validation][:report_missing_doctype] = opts['report_missing_doctype'] unless opts['report_missing_doctype'].nil?
|
87
|
+
options[:validation][:report_eof_tags] = opts['report_eof_tags'] unless opts['report_eof_tags'].nil?
|
88
|
+
options[:validation][:report_mismatched_tags] = opts['report_mismatched_tags'] unless opts['report_mismatched_tags'].nil?
|
83
89
|
|
84
90
|
options[:typhoeus] = HTMLProofer::Configuration.parse_json_option('typhoeus_config', opts['typhoeus_config']) unless opts['typhoeus_config'].nil?
|
85
91
|
|
data/lib/html-proofer.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
def require_all(path)
|
4
4
|
dir = File.join(File.dirname(__FILE__), path)
|
5
|
-
Dir[File.join(dir, '*.rb')].each do |f|
|
5
|
+
Dir[File.join(dir, '*.rb')].sort.each do |f|
|
6
6
|
require f
|
7
7
|
end
|
8
8
|
end
|
@@ -17,7 +17,7 @@ require 'fileutils'
|
|
17
17
|
begin
|
18
18
|
require 'awesome_print'
|
19
19
|
require 'pry-byebug'
|
20
|
-
rescue LoadError; end # rubocop:disable Lint/
|
20
|
+
rescue LoadError; end # rubocop:disable Lint/SuppressedException
|
21
21
|
module HTMLProofer
|
22
22
|
def self.check_file(file, options = {})
|
23
23
|
raise ArgumentError unless file.is_a?(String)
|
data/lib/html-proofer/cache.rb
CHANGED
@@ -120,9 +120,8 @@ module HTMLProofer
|
|
120
120
|
@cache_log.each_pair do |url, cache|
|
121
121
|
if within_timeframe?(cache['time'])
|
122
122
|
next if cache['message'].empty? # these were successes to skip
|
123
|
-
else
|
124
|
-
urls_to_check[url] = cache['filenames'] # recheck expired links
|
125
123
|
end
|
124
|
+
urls_to_check[url] = cache['filenames'] # recheck expired links
|
126
125
|
end
|
127
126
|
urls_to_check
|
128
127
|
end
|
data/lib/html-proofer/check.rb
CHANGED
@@ -5,10 +5,11 @@ module HTMLProofer
|
|
5
5
|
class Check
|
6
6
|
attr_reader :node, :html, :element, :src, :path, :options, :issues, :external_urls
|
7
7
|
|
8
|
-
def initialize(src, path, html, options)
|
8
|
+
def initialize(src, path, html, logger, options)
|
9
9
|
@src = src
|
10
10
|
@path = path
|
11
11
|
@html = remove_ignored(html)
|
12
|
+
@logger = logger
|
12
13
|
@options = options
|
13
14
|
@issues = []
|
14
15
|
@external_urls = {}
|
@@ -16,7 +17,7 @@ module HTMLProofer
|
|
16
17
|
|
17
18
|
def create_element(node)
|
18
19
|
@node = node
|
19
|
-
Element.new(node, self)
|
20
|
+
Element.new(node, self, @logger)
|
20
21
|
end
|
21
22
|
|
22
23
|
def run
|
@@ -1,28 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class HtmlCheck < ::HTMLProofer::Check
|
4
|
+
# tags embedded in scripts are used in templating languages: http://git.io/vOovv
|
4
5
|
SCRIPT_EMBEDS_MSG = /Element script embeds close tag/.freeze
|
5
6
|
INVALID_TAG_MSG = /Tag ([\w\-:]+) invalid/.freeze
|
6
7
|
INVALID_PREFIX = /Namespace prefix/.freeze
|
7
8
|
PARSE_ENTITY_REF = /htmlParseEntityRef: no name/.freeze
|
9
|
+
DOCTYPE_MSG = /Expected a doctype token/.freeze
|
10
|
+
EOF_IN_TAG = /End of input in tag/.freeze
|
11
|
+
MISMATCHED_TAGS = /That tag isn't allowed here/.freeze
|
8
12
|
|
9
13
|
def run
|
10
14
|
@html.errors.each do |error|
|
11
|
-
message
|
12
|
-
|
13
|
-
|
14
|
-
if message =~ INVALID_TAG_MSG || message =~ INVALID_PREFIX
|
15
|
-
next unless options[:validation][:report_invalid_tags]
|
16
|
-
end
|
17
|
-
|
18
|
-
if message =~ PARSE_ENTITY_REF
|
19
|
-
next unless options[:validation][:report_missing_names]
|
20
|
-
end
|
21
|
-
|
22
|
-
# tags embedded in scripts are used in templating languages: http://git.io/vOovv
|
23
|
-
next if !options[:validation][:report_script_embeds] && message =~ SCRIPT_EMBEDS_MSG
|
15
|
+
add_issue(error.message, line: error.line) if report?(error.message)
|
16
|
+
end
|
17
|
+
end
|
24
18
|
|
25
|
-
|
19
|
+
def report?(message)
|
20
|
+
case message
|
21
|
+
when SCRIPT_EMBEDS_MSG
|
22
|
+
options[:validation][:report_script_embeds]
|
23
|
+
when INVALID_TAG_MSG, INVALID_PREFIX
|
24
|
+
options[:validation][:report_invalid_tags]
|
25
|
+
when PARSE_ENTITY_REF
|
26
|
+
options[:validation][:report_missing_names]
|
27
|
+
when DOCTYPE_MSG
|
28
|
+
options[:validation][:report_missing_doctype]
|
29
|
+
when EOF_IN_TAG
|
30
|
+
options[:validation][:report_eof_tags]
|
31
|
+
when MISMATCHED_TAGS
|
32
|
+
options[:validation][:report_mismatched_tags]
|
33
|
+
else
|
34
|
+
true
|
26
35
|
end
|
27
36
|
end
|
28
37
|
end
|
@@ -34,7 +34,7 @@ class LinkCheck < ::HTMLProofer::Check
|
|
34
34
|
if missing_href?
|
35
35
|
next if @link.allow_missing_href?
|
36
36
|
# HTML5 allows dropping the href: http://git.io/vBX0z
|
37
|
-
next if @html.internal_subset.name == 'html' && @html.internal_subset.external_id.nil?
|
37
|
+
next if @html.internal_subset.nil? || (@html.internal_subset.name == 'html' && @html.internal_subset.external_id.nil?)
|
38
38
|
|
39
39
|
add_issue('anchor has no href attribute', line: line, content: content)
|
40
40
|
next
|
@@ -3,12 +3,12 @@
|
|
3
3
|
class OpenGraphElement < ::HTMLProofer::Element
|
4
4
|
attr_reader :src
|
5
5
|
|
6
|
-
def initialize(obj, check)
|
7
|
-
super(obj, check)
|
6
|
+
def initialize(obj, check, logger)
|
7
|
+
super(obj, check, logger)
|
8
8
|
# Fake up src from the content attribute
|
9
9
|
instance_variable_set('@src', @content)
|
10
10
|
|
11
|
-
@src.insert 0, 'http:' if
|
11
|
+
@src.insert 0, 'http:' if %r{^//}.match?(@src)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
@@ -23,7 +23,7 @@ class OpenGraphCheck < ::HTMLProofer::Check
|
|
23
23
|
|
24
24
|
def run
|
25
25
|
@html.css('meta[property="og:url"], meta[property="og:image"]').each do |m|
|
26
|
-
@opengraph = OpenGraphElement.new(m, self)
|
26
|
+
@opengraph = OpenGraphElement.new(m, self, @logger)
|
27
27
|
|
28
28
|
next if @opengraph.ignore?
|
29
29
|
|
@@ -51,7 +51,10 @@ module HTMLProofer
|
|
51
51
|
VALIDATION_DEFAULTS = {
|
52
52
|
report_script_embeds: false,
|
53
53
|
report_missing_names: false,
|
54
|
-
report_invalid_tags: false
|
54
|
+
report_invalid_tags: false,
|
55
|
+
report_missing_doctype: false,
|
56
|
+
report_eof_tags: false,
|
57
|
+
report_mismatched_tags: false
|
55
58
|
}.freeze
|
56
59
|
|
57
60
|
CACHE_DEFAULTS = {}.freeze
|
data/lib/html-proofer/element.rb
CHANGED
@@ -10,12 +10,18 @@ module HTMLProofer
|
|
10
10
|
|
11
11
|
attr_reader :id, :name, :alt, :href, :link, :src, :line, :data_proofer_ignore
|
12
12
|
|
13
|
-
def initialize(obj, check)
|
13
|
+
def initialize(obj, check, logger)
|
14
|
+
@logger = logger
|
14
15
|
# Construct readable ivars for every element
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
begin
|
17
|
+
obj.attributes.each_pair do |attribute, value|
|
18
|
+
name = attribute.tr('-:.;@', '_').to_s.to_sym
|
19
|
+
(class << self; self; end).send(:attr_reader, name)
|
20
|
+
instance_variable_set("@#{name}", value.value)
|
21
|
+
end
|
22
|
+
rescue NameError => e
|
23
|
+
@logger.log :error, "Attribute set `#{obj}` contains an error!"
|
24
|
+
raise e
|
19
25
|
end
|
20
26
|
|
21
27
|
@aria_hidden = defined?(@aria_hidden) && @aria_hidden == 'true' ? true : false
|
@@ -36,19 +42,19 @@ module HTMLProofer
|
|
36
42
|
|
37
43
|
# fix up missing protocols
|
38
44
|
if defined?(@href)
|
39
|
-
@href.insert(0, 'http:') if
|
45
|
+
@href.insert(0, 'http:') if %r{^//}.match?(@href)
|
40
46
|
else
|
41
47
|
@href = nil
|
42
48
|
end
|
43
49
|
|
44
50
|
if defined?(@src)
|
45
|
-
@src.insert(0, 'http:') if
|
51
|
+
@src.insert(0, 'http:') if %r{^//}.match?(@src)
|
46
52
|
else
|
47
53
|
@src = nil
|
48
54
|
end
|
49
55
|
|
50
56
|
if defined?(@srcset)
|
51
|
-
@srcset.insert(0, 'http:') if
|
57
|
+
@srcset.insert(0, 'http:') if %r{^//}.match?(@srcset)
|
52
58
|
else
|
53
59
|
@srcset = nil
|
54
60
|
end
|
@@ -99,11 +105,11 @@ module HTMLProofer
|
|
99
105
|
return true if @data_proofer_ignore
|
100
106
|
return true if @parent_ignorable
|
101
107
|
|
102
|
-
return true if
|
108
|
+
return true if /^javascript:/.match?(url)
|
103
109
|
|
104
110
|
# ignore base64 encoded images
|
105
111
|
if %w[ImageCheck FaviconCheck].include? @type
|
106
|
-
return true if
|
112
|
+
return true if /^data:image/.match?(url)
|
107
113
|
end
|
108
114
|
|
109
115
|
# ignore user defined URLs
|
@@ -172,7 +178,7 @@ module HTMLProofer
|
|
172
178
|
|
173
179
|
path_dot_ext = path + @check.options[:extension] if @check.options[:assume_extension]
|
174
180
|
|
175
|
-
if
|
181
|
+
if %r{^/}.match?(path) # path relative to root
|
176
182
|
if File.directory?(@check.src)
|
177
183
|
base = @check.src
|
178
184
|
else
|
@@ -211,10 +217,11 @@ module HTMLProofer
|
|
211
217
|
|
212
218
|
def ignores_pattern_check(links)
|
213
219
|
links.each do |ignore|
|
214
|
-
|
220
|
+
case ignore
|
221
|
+
when String
|
215
222
|
return true if ignore == url
|
216
|
-
|
217
|
-
return true if ignore
|
223
|
+
when Regexp
|
224
|
+
return true if ignore&.match?(url)
|
218
225
|
end
|
219
226
|
end
|
220
227
|
|
data/lib/html-proofer/log.rb
CHANGED
@@ -7,16 +7,27 @@ module HTMLProofer
|
|
7
7
|
class Log
|
8
8
|
include Yell::Loggable
|
9
9
|
|
10
|
+
STDOUT_LEVELS = %i[debug info warn].freeze
|
11
|
+
STDERR_LEVELS = %i[error fatal].freeze
|
12
|
+
|
10
13
|
def initialize(log_level)
|
11
14
|
@logger = Yell.new(format: false, \
|
12
15
|
name: 'HTMLProofer', \
|
13
16
|
level: "gte.#{log_level}") do |l|
|
14
|
-
l.adapter :stdout, level:
|
15
|
-
l.adapter :stderr, level:
|
17
|
+
l.adapter :stdout, level: 'lte.warn'
|
18
|
+
l.adapter :stderr, level: 'gte.error'
|
16
19
|
end
|
17
20
|
end
|
18
21
|
|
19
22
|
def log(level, message)
|
23
|
+
log_with_color(level, message)
|
24
|
+
end
|
25
|
+
|
26
|
+
def log_with_color(level, message)
|
27
|
+
@logger.send level, colorize(level, message)
|
28
|
+
end
|
29
|
+
|
30
|
+
def colorize(level, message)
|
20
31
|
color = case level
|
21
32
|
when :debug
|
22
33
|
:cyan
|
@@ -28,15 +39,8 @@ module HTMLProofer
|
|
28
39
|
:red
|
29
40
|
end
|
30
41
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
def log_with_color(level, color, message)
|
35
|
-
@logger.send level, colorize(color, message)
|
36
|
-
end
|
37
|
-
|
38
|
-
def colorize(color, message)
|
39
|
-
if $stdout.isatty && $stderr.isatty
|
42
|
+
if (STDOUT_LEVELS.include?(level) && $stdout.isatty) || \
|
43
|
+
(STDERR_LEVELS.include?(level) && $stderr.isatty)
|
40
44
|
Rainbow(message).send(color)
|
41
45
|
else
|
42
46
|
message
|
@@ -21,7 +21,8 @@ module HTMLProofer
|
|
21
21
|
allow_hash_href: true,
|
22
22
|
check_external_hash: true,
|
23
23
|
check_html: true,
|
24
|
-
url_ignore: [/.*/] # Don't try to check local files exist
|
24
|
+
url_ignore: [/.*/], # Don't try to check if local files exist
|
25
|
+
validation: { report_eof_tags: true }
|
25
26
|
}
|
26
27
|
end
|
27
28
|
|
@@ -52,7 +53,7 @@ module HTMLProofer
|
|
52
53
|
def call(env)
|
53
54
|
result = @app.call(env)
|
54
55
|
return result if env['REQUEST_METHOD'] != 'GET'
|
55
|
-
return result if env['QUERY_STRING']
|
56
|
+
return result if /proofer-ignore/.match?(env['QUERY_STRING'])
|
56
57
|
return result if result.first != 200
|
57
58
|
|
58
59
|
body = []
|
@@ -69,7 +70,7 @@ module HTMLProofer
|
|
69
70
|
'response',
|
70
71
|
Middleware.options
|
71
72
|
).check_parsed(
|
72
|
-
Nokogiri::
|
73
|
+
Nokogiri::HTML5(html, max_errors: -1), 'response'
|
73
74
|
)
|
74
75
|
|
75
76
|
raise InvalidHtmlError, parsed[:failures] unless parsed[:failures].empty?
|
data/lib/html-proofer/runner.rb
CHANGED
@@ -31,6 +31,7 @@ module HTMLProofer
|
|
31
31
|
end
|
32
32
|
|
33
33
|
@failures = []
|
34
|
+
@before_request = []
|
34
35
|
end
|
35
36
|
|
36
37
|
def run
|
@@ -45,7 +46,7 @@ module HTMLProofer
|
|
45
46
|
end
|
46
47
|
|
47
48
|
if @failures.empty?
|
48
|
-
@logger.
|
49
|
+
@logger.log :info, 'HTML-Proofer finished successfully.'
|
49
50
|
else
|
50
51
|
print_failed_tests
|
51
52
|
end
|
@@ -100,7 +101,7 @@ module HTMLProofer
|
|
100
101
|
@src.each do |src|
|
101
102
|
checks.each do |klass|
|
102
103
|
@logger.log :debug, "Checking #{klass.to_s.downcase} on #{path} ..."
|
103
|
-
check = Object.const_get(klass).new(src, path, html, @options)
|
104
|
+
check = Object.const_get(klass).new(src, path, html, @logger, @options)
|
104
105
|
check.run
|
105
106
|
external_urls = check.external_urls
|
106
107
|
external_urls = Hash[check.external_urls.map { |url, file| [swap(url, @options[:url_swap]), file] }] if @options[:url_swap]
|
@@ -117,6 +118,7 @@ module HTMLProofer
|
|
117
118
|
|
118
119
|
def validate_urls
|
119
120
|
url_validator = HTMLProofer::UrlValidator.new(@logger, @external_urls, @options)
|
121
|
+
url_validator.before_request = @before_request
|
120
122
|
@failures.concat(url_validator.run)
|
121
123
|
@external_urls = url_validator.external_urls
|
122
124
|
end
|
@@ -147,6 +149,8 @@ module HTMLProofer
|
|
147
149
|
def checks
|
148
150
|
return @checks if defined?(@checks) && !@checks.nil?
|
149
151
|
|
152
|
+
return (@checks = ['LinkCheck']) if @type == :links
|
153
|
+
|
150
154
|
@checks = HTMLProofer::Check.subchecks.map(&:name)
|
151
155
|
@checks.delete('FaviconCheck') unless @options[:check_favicon]
|
152
156
|
@checks.delete('HtmlCheck') unless @options[:check_html]
|
@@ -169,7 +173,23 @@ module HTMLProofer
|
|
169
173
|
sorted_failures.sort_and_report
|
170
174
|
count = @failures.length
|
171
175
|
failure_text = pluralize(count, 'failure', 'failures')
|
172
|
-
raise @logger.colorize :
|
176
|
+
raise @logger.colorize :fatal, "HTML-Proofer found #{failure_text}!"
|
177
|
+
end
|
178
|
+
|
179
|
+
# Set before_request callback.
|
180
|
+
#
|
181
|
+
# @example Set before_request.
|
182
|
+
# request.before_request { |request| p "yay" }
|
183
|
+
#
|
184
|
+
# @param [ Block ] block The block to execute.
|
185
|
+
#
|
186
|
+
# @yield [ Typhoeus::Request ]
|
187
|
+
#
|
188
|
+
# @return [ Array<Block> ] All before_request blocks.
|
189
|
+
def before_request(&block)
|
190
|
+
@before_request ||= []
|
191
|
+
@before_request << block if block_given?
|
192
|
+
@before_request
|
173
193
|
end
|
174
194
|
end
|
175
195
|
end
|
@@ -10,6 +10,7 @@ module HTMLProofer
|
|
10
10
|
include HTMLProofer::Utils
|
11
11
|
|
12
12
|
attr_reader :external_urls
|
13
|
+
attr_writer :before_request
|
13
14
|
|
14
15
|
def initialize(logger, external_urls, options)
|
15
16
|
@logger = logger
|
@@ -18,6 +19,7 @@ module HTMLProofer
|
|
18
19
|
@options = options
|
19
20
|
@hydra = Typhoeus::Hydra.new(@options[:hydra])
|
20
21
|
@cache = Cache.new(@logger, @options[:cache])
|
22
|
+
@before_request = []
|
21
23
|
end
|
22
24
|
|
23
25
|
def run
|
@@ -137,6 +139,9 @@ module HTMLProofer
|
|
137
139
|
def queue_request(method, href, filenames)
|
138
140
|
opts = @options[:typhoeus].merge(method: method)
|
139
141
|
request = Typhoeus::Request.new(href, opts)
|
142
|
+
@before_request.each do |callback|
|
143
|
+
callback.call(request)
|
144
|
+
end
|
140
145
|
request.on_complete { |response| response_handler(response, filenames) }
|
141
146
|
@hydra.queue request
|
142
147
|
end
|
@@ -146,7 +151,7 @@ module HTMLProofer
|
|
146
151
|
href = response.request.base_url.to_s
|
147
152
|
method = response.request.options[:method]
|
148
153
|
response_code = response.code
|
149
|
-
response.body.
|
154
|
+
response.body.delete!("\x00")
|
150
155
|
|
151
156
|
debug_msg = if filenames.nil?
|
152
157
|
"Received a #{response_code} for #{href}"
|
data/lib/html-proofer/utils.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'nokogumbo'
|
4
4
|
|
5
5
|
module HTMLProofer
|
6
6
|
module Utils
|
@@ -15,7 +15,7 @@ module HTMLProofer
|
|
15
15
|
path
|
16
16
|
end
|
17
17
|
|
18
|
-
Nokogiri::
|
18
|
+
Nokogiri::HTML5(content, max_errors: -1)
|
19
19
|
end
|
20
20
|
|
21
21
|
def swap(href, replacement)
|
@@ -24,14 +24,5 @@ module HTMLProofer
|
|
24
24
|
end
|
25
25
|
href
|
26
26
|
end
|
27
|
-
|
28
|
-
# address a problem with Nokogiri's parsing URL entities
|
29
|
-
# problem from http://git.io/vBYU1
|
30
|
-
# solution from http://git.io/vBYUi
|
31
|
-
def clean_content(string)
|
32
|
-
string.gsub(%r{(?:https?:)?//([^>]+)}i) do |url|
|
33
|
-
url.gsub(/&(?!amp;)/, '&')
|
34
|
-
end
|
35
|
-
end
|
36
27
|
end
|
37
28
|
end
|
data/lib/html-proofer/version.rb
CHANGED
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: 3.
|
4
|
+
version: 3.16.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:
|
11
|
+
date: 2020-09-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -39,19 +39,19 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0.3'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: nokogumbo
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '2.0'
|
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: '
|
54
|
+
version: '2.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: parallel
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -308,7 +308,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
308
308
|
- !ruby/object:Gem::Version
|
309
309
|
version: '0'
|
310
310
|
requirements: []
|
311
|
-
rubygems_version: 3.
|
311
|
+
rubygems_version: 3.1.2
|
312
312
|
signing_key:
|
313
313
|
specification_version: 4
|
314
314
|
summary: A set of tests to validate your HTML output. These tests check if your image
|