html-proofer 3.1.0 → 3.2.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 +1 -1
- data/lib/html-proofer/check.rb +5 -5
- data/lib/html-proofer/check/favicon.rb +1 -1
- data/lib/html-proofer/check/images.rb +7 -6
- data/lib/html-proofer/check/links.rb +24 -23
- data/lib/html-proofer/check/scripts.rb +4 -3
- data/lib/html-proofer/element.rb +15 -5
- data/lib/html-proofer/issue.rb +8 -3
- data/lib/html-proofer/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf114815adfcc6b231c9f8b119d2e5c02dee4738
|
4
|
+
data.tar.gz: 382848c036bf27e114796531c07c55c970f8b890
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be3e69485788801d9ce34e6374eee233b2fe91553fc8051bd8fc96fa1d22792aba37b2b06d44a50a31fb50f832730a883006282e08c52bd917c7da003465b3b5
|
7
|
+
data.tar.gz: 235a71993139147fa3a1909da8bfe25d23b1124fb9f5d4e676625650ed5a3b0381aa435957f5781284c386ab7365f425bc4099b784d0309b23f9761a9ae21939
|
data/bin/htmlproofer
CHANGED
@@ -59,7 +59,7 @@ Mercenary.program(:htmlproofer) do |p|
|
|
59
59
|
unless opts['url_swap'].nil?
|
60
60
|
options[:url_swap] = {}
|
61
61
|
opts['url_swap'].each do |s|
|
62
|
-
splt = s.split(/(?<!\\):/,2)
|
62
|
+
splt = s.split(/(?<!\\):/, 2)
|
63
63
|
|
64
64
|
re = splt[0].gsub(/\\:/, ':')
|
65
65
|
string = splt[1].gsub(/\\:/, ':')
|
data/lib/html-proofer/check.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module HTMLProofer
|
2
2
|
# Mostly handles issue management and collecting of external URLs.
|
3
3
|
class Check
|
4
|
-
attr_reader :node, :element, :src, :path, :options, :issues, :external_urls
|
4
|
+
attr_reader :node, :html, :element, :src, :path, :options, :issues, :external_urls
|
5
5
|
|
6
6
|
def initialize(src, path, html, options)
|
7
7
|
@src = src
|
@@ -18,14 +18,14 @@ module HTMLProofer
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def run
|
21
|
-
|
21
|
+
raise NotImplementedError, 'HTMLProofer::Check subclasses must implement #run'
|
22
22
|
end
|
23
23
|
|
24
|
-
def add_issue(desc, line: nil, status: -1)
|
25
|
-
@issues << Issue.new(@path, desc, line: line, status: status)
|
24
|
+
def add_issue(desc, line: nil, status: -1, content: nil)
|
25
|
+
@issues << Issue.new(@path, desc, line: line, status: status, content: content)
|
26
26
|
end
|
27
27
|
|
28
|
-
def add_to_external_urls(url
|
28
|
+
def add_to_external_urls(url)
|
29
29
|
return if @external_urls[url]
|
30
30
|
add_path_for_url(url)
|
31
31
|
end
|
@@ -17,32 +17,33 @@ class ImageCheck < ::HTMLProofer::Check
|
|
17
17
|
@html.css('img').each do |node|
|
18
18
|
@img = create_element(node)
|
19
19
|
line = node.line
|
20
|
+
content = node.content
|
20
21
|
|
21
22
|
next if @img.ignore?
|
22
23
|
|
23
24
|
# screenshot filenames should return because of terrible names
|
24
25
|
if terrible_filename?
|
25
|
-
add_issue("image has a terrible filename (#{@img.url})", line: line)
|
26
|
+
add_issue("image has a terrible filename (#{@img.url})", line: line, content: content)
|
26
27
|
next
|
27
28
|
end
|
28
29
|
|
29
30
|
# does the image exist?
|
30
31
|
if missing_src?
|
31
|
-
add_issue('image has no src or srcset attribute', line: line)
|
32
|
+
add_issue('image has no src or srcset attribute', line: line, content: content)
|
32
33
|
else
|
33
34
|
if @img.remote?
|
34
|
-
add_to_external_urls(@img.url
|
35
|
+
add_to_external_urls(@img.url)
|
35
36
|
elsif !@img.exists?
|
36
|
-
add_issue("internal image #{@img.url} does not exist", line: line)
|
37
|
+
add_issue("internal image #{@img.url} does not exist", line: line, content: content)
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
40
41
|
if !@img.ignore_alt? && (@img.alt.nil? || (empty_alt_tag? && !@img.ignore_empty_alt?))
|
41
|
-
add_issue("image #{@img.url} does not have an alt attribute", line: line)
|
42
|
+
add_issue("image #{@img.url} does not have an alt attribute", line: line, content: content)
|
42
43
|
end
|
43
44
|
|
44
45
|
if @img.check_img_http? && @img.scheme == 'http'
|
45
|
-
add_issue("image #{@img.url} uses the http scheme", line: line)
|
46
|
+
add_issue("image #{@img.url} uses the http scheme", line: line, content: content)
|
46
47
|
end
|
47
48
|
end
|
48
49
|
|
@@ -12,7 +12,8 @@ class LinkCheck < ::HTMLProofer::Check
|
|
12
12
|
def run
|
13
13
|
@html.css('a, link').each do |node|
|
14
14
|
@link = create_element(node)
|
15
|
-
line =
|
15
|
+
line = node.line
|
16
|
+
content = node.to_s
|
16
17
|
|
17
18
|
next if @link.ignore?
|
18
19
|
|
@@ -21,17 +22,17 @@ class LinkCheck < ::HTMLProofer::Check
|
|
21
22
|
|
22
23
|
# is it even a valid URL?
|
23
24
|
unless @link.valid?
|
24
|
-
add_issue("#{@link.href} is an invalid URL", line: line)
|
25
|
+
add_issue("#{@link.href} is an invalid URL", line: line, content: content)
|
25
26
|
next
|
26
27
|
end
|
27
28
|
|
28
|
-
check_schemes(@link, line)
|
29
|
+
check_schemes(@link, line, content)
|
29
30
|
|
30
31
|
# is there even an href?
|
31
32
|
if missing_href?
|
32
33
|
# HTML5 allows dropping the href: http://git.io/vBX0z
|
33
34
|
next if @html.internal_subset.name == 'html' && @html.internal_subset.external_id.nil?
|
34
|
-
add_issue('anchor has no href attribute', line: line)
|
35
|
+
add_issue('anchor has no href attribute', line: line, content: content)
|
35
36
|
next
|
36
37
|
end
|
37
38
|
|
@@ -39,66 +40,66 @@ class LinkCheck < ::HTMLProofer::Check
|
|
39
40
|
next if @link.non_http_remote?
|
40
41
|
# does the file even exist?
|
41
42
|
if @link.remote?
|
42
|
-
add_to_external_urls(@link.href
|
43
|
+
add_to_external_urls(@link.href)
|
43
44
|
next
|
44
45
|
elsif !@link.internal? && !@link.exists?
|
45
|
-
add_issue("internally linking to #{@link.href}, which does not exist", line: line)
|
46
|
+
add_issue("internally linking to #{@link.href}, which does not exist", line: line, content: content)
|
46
47
|
end
|
47
48
|
|
48
49
|
# does the local directory have a trailing slash?
|
49
50
|
if @link.unslashed_directory? @link.absolute_path
|
50
|
-
add_issue("internally linking to a directory #{@link.absolute_path} without trailing slash", line: line)
|
51
|
+
add_issue("internally linking to a directory #{@link.absolute_path} without trailing slash", line: line, content: content)
|
51
52
|
next
|
52
53
|
end
|
53
54
|
|
54
55
|
# verify the target hash
|
55
|
-
handle_hash(@link, line) if @link.hash
|
56
|
+
handle_hash(@link, line, content) if @link.hash
|
56
57
|
end
|
57
58
|
|
58
59
|
external_urls
|
59
60
|
end
|
60
61
|
|
61
|
-
def check_schemes(link, line)
|
62
|
+
def check_schemes(link, line, content)
|
62
63
|
case link.scheme
|
63
64
|
when 'mailto'
|
64
|
-
handle_mailto(link, line)
|
65
|
+
handle_mailto(link, line, content)
|
65
66
|
when 'tel'
|
66
|
-
handle_tel(link, line)
|
67
|
+
handle_tel(link, line, content)
|
67
68
|
when 'http'
|
68
69
|
return unless @options[:enforce_https]
|
69
|
-
add_issue("#{link.href} is not an HTTPS link", line: line)
|
70
|
+
add_issue("#{link.href} is not an HTTPS link", line: line, content: content)
|
70
71
|
end
|
71
72
|
end
|
72
73
|
|
73
|
-
def handle_mailto(link, line)
|
74
|
+
def handle_mailto(link, line, content)
|
74
75
|
if link.path.empty?
|
75
|
-
add_issue("#{link.href} contains no email address", line: line)
|
76
|
+
add_issue("#{link.href} contains no email address", line: line, content: content)
|
76
77
|
elsif !link.path.include?('@')
|
77
|
-
add_issue("#{link.href} contains an invalid email address", line: line)
|
78
|
+
add_issue("#{link.href} contains an invalid email address", line: line, content: content)
|
78
79
|
end
|
79
80
|
end
|
80
81
|
|
81
|
-
def handle_tel(link, line)
|
82
|
-
add_issue("#{link.href} contains no phone number", line: line) if link.path.empty?
|
82
|
+
def handle_tel(link, line, content)
|
83
|
+
add_issue("#{link.href} contains no phone number", line: line, content: content) if link.path.empty?
|
83
84
|
end
|
84
85
|
|
85
|
-
def handle_hash(link, line)
|
86
|
+
def handle_hash(link, line, content)
|
86
87
|
if link.internal?
|
87
88
|
unless hash_check @html, link.hash
|
88
|
-
add_issue("linking to internal hash ##{link.hash} that does not exist", line: line)
|
89
|
+
add_issue("linking to internal hash ##{link.hash} that does not exist", line: line, content: content)
|
89
90
|
end
|
90
91
|
elsif link.external?
|
91
|
-
external_link_check(link, line)
|
92
|
+
external_link_check(link, line, content)
|
92
93
|
end
|
93
94
|
end
|
94
95
|
|
95
|
-
def external_link_check(link, line)
|
96
|
+
def external_link_check(link, line, content)
|
96
97
|
if !link.exists?
|
97
|
-
add_issue("trying to find hash of #{link.href}, but #{link.absolute_path} does not exist", line: line)
|
98
|
+
add_issue("trying to find hash of #{link.href}, but #{link.absolute_path} does not exist", line: line, content: content)
|
98
99
|
else
|
99
100
|
target_html = create_nokogiri link.absolute_path
|
100
101
|
unless hash_check target_html, link.hash
|
101
|
-
add_issue("linking to #{link.href}, but #{link.hash} does not exist", line: line)
|
102
|
+
add_issue("linking to #{link.href}, but #{link.hash} does not exist", line: line, content: content)
|
102
103
|
end
|
103
104
|
end
|
104
105
|
end
|
@@ -9,17 +9,18 @@ class ScriptCheck < ::HTMLProofer::Check
|
|
9
9
|
@html.css('script').each do |node|
|
10
10
|
@script = create_element(node)
|
11
11
|
line = node.line
|
12
|
+
content = node.content
|
12
13
|
|
13
14
|
next if @script.ignore?
|
14
15
|
next unless node.text.strip.empty?
|
15
16
|
|
16
17
|
# does the script exist?
|
17
18
|
if missing_src?
|
18
|
-
add_issue('script is empty and has no src attribute', line: line)
|
19
|
+
add_issue('script is empty and has no src attribute', line: line, content: content)
|
19
20
|
elsif @script.remote?
|
20
|
-
add_to_external_urls(@script.src
|
21
|
+
add_to_external_urls(@script.src)
|
21
22
|
elsif !@script.exists?
|
22
|
-
add_issue("internal script #{@script.src} does not exist", line: line)
|
23
|
+
add_issue("internal script #{@script.src} does not exist", line: line, content: content)
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
data/lib/html-proofer/element.rb
CHANGED
@@ -22,6 +22,8 @@ module HTMLProofer
|
|
22
22
|
@type = check.class.name
|
23
23
|
@line = obj.line
|
24
24
|
|
25
|
+
@html = check.html
|
26
|
+
|
25
27
|
# fix up missing protocols
|
26
28
|
@href.insert 0, 'http:' if @href =~ %r{^//}
|
27
29
|
@src.insert 0, 'http:' if @src =~ %r{^//}
|
@@ -29,9 +31,13 @@ module HTMLProofer
|
|
29
31
|
end
|
30
32
|
|
31
33
|
def url
|
32
|
-
url
|
33
|
-
|
34
|
-
|
34
|
+
return @url if defined?(@url)
|
35
|
+
@url = (@src || @srcset || @href || '').gsub("\u200b", '')
|
36
|
+
if base
|
37
|
+
@url = Addressable::URI.join(base.attr('href'), url).to_s
|
38
|
+
end
|
39
|
+
return @url if @check.options[:url_swap].empty?
|
40
|
+
@url = swap(@url, @check.options[:url_swap])
|
35
41
|
end
|
36
42
|
|
37
43
|
def valid?
|
@@ -68,11 +74,11 @@ module HTMLProofer
|
|
68
74
|
def ignore?
|
69
75
|
return true if @data_proofer_ignore
|
70
76
|
|
71
|
-
return true if url
|
77
|
+
return true if url =~ /^javascript:/
|
72
78
|
|
73
79
|
# ignore base64 encoded images
|
74
80
|
if %w(ImageCheck FaviconCheck).include? @type
|
75
|
-
return true if url
|
81
|
+
return true if url =~ /^data:image/
|
76
82
|
end
|
77
83
|
|
78
84
|
# ignore user defined URLs
|
@@ -166,5 +172,9 @@ module HTMLProofer
|
|
166
172
|
def follow_location?
|
167
173
|
@check.options[:typhoeus] && @check.options[:typhoeus][:followlocation]
|
168
174
|
end
|
175
|
+
|
176
|
+
def base
|
177
|
+
@base ||= @html.at_css('base')
|
178
|
+
end
|
169
179
|
end
|
170
180
|
end
|
data/lib/html-proofer/issue.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
module HTMLProofer
|
2
2
|
class Issue
|
3
|
-
attr_reader :path, :desc, :status, :line
|
3
|
+
attr_reader :path, :desc, :status, :line, :content
|
4
4
|
|
5
|
-
def initialize(path, desc, line: nil, status: -1)
|
5
|
+
def initialize(path, desc, line: nil, status: -1, content: nil)
|
6
6
|
@line = line.nil? ? '' : " (line #{line})"
|
7
7
|
@path = path
|
8
8
|
@desc = desc
|
9
9
|
@status = status
|
10
|
+
@content = content
|
10
11
|
end
|
11
12
|
|
12
13
|
def to_s
|
@@ -52,7 +53,11 @@ module HTMLProofer
|
|
52
53
|
if first_report == :status
|
53
54
|
@logger.log :error, " * #{issue}"
|
54
55
|
else
|
55
|
-
|
56
|
+
msg = " * #{issue.send(second_report)}#{issue.line}"
|
57
|
+
if !issue.content.nil? && !issue.content.empty?
|
58
|
+
msg = "#{msg}\n #{issue.content}"
|
59
|
+
end
|
60
|
+
@logger.log(:error, msg)
|
56
61
|
end
|
57
62
|
end
|
58
63
|
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.2.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: 2016-09-
|
11
|
+
date: 2016-09-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mercenary
|