html-proofer 2.5.2 → 3.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 +85 -0
- data/lib/html-proofer/cache.rb +153 -0
- data/lib/{html/proofer/checks → html-proofer/check}/favicon.rb +2 -8
- data/lib/html-proofer/check/html.rb +21 -0
- data/lib/html-proofer/check/images.rb +47 -0
- data/lib/html-proofer/check/links.rb +120 -0
- data/lib/html-proofer/check/scripts.rb +28 -0
- data/lib/html-proofer/check.rb +63 -0
- data/lib/html-proofer/configuration.rb +56 -0
- data/lib/html-proofer/element.rb +165 -0
- data/lib/{html/proofer/check_runner → html-proofer}/issue.rb +8 -10
- data/lib/html-proofer/log.rb +49 -0
- data/lib/html-proofer/runner.rb +160 -0
- data/lib/html-proofer/url_validator.rb +218 -0
- data/lib/html-proofer/utils.rb +40 -0
- data/lib/html-proofer/version.rb +3 -0
- data/lib/html-proofer.rb +47 -0
- metadata +49 -20
- data/bin/htmlproof +0 -85
- data/lib/html/proofer/cache.rb +0 -16
- data/lib/html/proofer/check_runner.rb +0 -69
- data/lib/html/proofer/checkable.rb +0 -164
- data/lib/html/proofer/checks/html.rb +0 -46
- data/lib/html/proofer/checks/images.rb +0 -54
- data/lib/html/proofer/checks/links.rb +0 -124
- data/lib/html/proofer/checks/scripts.rb +0 -40
- data/lib/html/proofer/log.rb +0 -42
- data/lib/html/proofer/url_validator.rb +0 -179
- data/lib/html/proofer/utils.rb +0 -26
- data/lib/html/proofer/version.rb +0 -5
- data/lib/html/proofer/xpathfunctions.rb +0 -9
- data/lib/html/proofer.rb +0 -202
data/lib/html-proofer.rb
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
def require_all(path)
|
|
2
|
+
glob = File.join(File.dirname(__FILE__), path, '*.rb')
|
|
3
|
+
Dir[glob].each do |f|
|
|
4
|
+
require f
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
require_all 'html-proofer'
|
|
9
|
+
require_all 'html-proofer/check'
|
|
10
|
+
|
|
11
|
+
require 'parallel'
|
|
12
|
+
require 'fileutils'
|
|
13
|
+
|
|
14
|
+
begin
|
|
15
|
+
require 'awesome_print'
|
|
16
|
+
rescue LoadError; end
|
|
17
|
+
|
|
18
|
+
module HTMLProofer
|
|
19
|
+
|
|
20
|
+
def check_file(file, options = {})
|
|
21
|
+
fail ArgumentError unless file.is_a?(String)
|
|
22
|
+
options[:type] = :file
|
|
23
|
+
HTMLProofer::Runner.new(file, options)
|
|
24
|
+
end
|
|
25
|
+
module_function :check_file
|
|
26
|
+
|
|
27
|
+
def check_directory(directory, options = {})
|
|
28
|
+
fail ArgumentError unless directory.is_a?(String)
|
|
29
|
+
options[:type] = :directory
|
|
30
|
+
HTMLProofer::Runner.new([directory], options)
|
|
31
|
+
end
|
|
32
|
+
module_function :check_directory
|
|
33
|
+
|
|
34
|
+
def check_directories(directories, options = {})
|
|
35
|
+
fail ArgumentError unless directories.is_a?(Array)
|
|
36
|
+
options[:type] = :directory
|
|
37
|
+
HTMLProofer::Runner.new(directories, options)
|
|
38
|
+
end
|
|
39
|
+
module_function :check_directories
|
|
40
|
+
|
|
41
|
+
def check_links(links, options = {})
|
|
42
|
+
fail ArgumentError unless links.is_a?(Array)
|
|
43
|
+
options[:type] = :links
|
|
44
|
+
HTMLProofer::Runner.new(links, options)
|
|
45
|
+
end
|
|
46
|
+
module_function :check_links
|
|
47
|
+
end
|
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
|
+
version: 3.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:
|
|
11
|
+
date: 2016-03-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: mercenary
|
|
@@ -108,6 +108,20 @@ dependencies:
|
|
|
108
108
|
- - "~>"
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
110
|
version: '2.3'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: activesupport
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - "~>"
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '4.2'
|
|
118
|
+
type: :runtime
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - "~>"
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '4.2'
|
|
111
125
|
- !ruby/object:Gem::Dependency
|
|
112
126
|
name: redcarpet
|
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -178,30 +192,45 @@ dependencies:
|
|
|
178
192
|
- - "~>"
|
|
179
193
|
- !ruby/object:Gem::Version
|
|
180
194
|
version: '2.9'
|
|
195
|
+
- !ruby/object:Gem::Dependency
|
|
196
|
+
name: timecop
|
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
|
198
|
+
requirements:
|
|
199
|
+
- - "~>"
|
|
200
|
+
- !ruby/object:Gem::Version
|
|
201
|
+
version: '0.8'
|
|
202
|
+
type: :development
|
|
203
|
+
prerelease: false
|
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
205
|
+
requirements:
|
|
206
|
+
- - "~>"
|
|
207
|
+
- !ruby/object:Gem::Version
|
|
208
|
+
version: '0.8'
|
|
181
209
|
description: Test your rendered HTML files to make sure they're accurate.
|
|
182
210
|
email:
|
|
183
211
|
- gjtorikian@gmail.com
|
|
184
212
|
executables:
|
|
185
|
-
-
|
|
213
|
+
- htmlproofer
|
|
186
214
|
extensions: []
|
|
187
215
|
extra_rdoc_files: []
|
|
188
216
|
files:
|
|
189
|
-
- bin/
|
|
190
|
-
- lib/html
|
|
191
|
-
- lib/html
|
|
192
|
-
- lib/html
|
|
193
|
-
- lib/html
|
|
194
|
-
- lib/html
|
|
195
|
-
- lib/html
|
|
196
|
-
- lib/html
|
|
197
|
-
- lib/html
|
|
198
|
-
- lib/html
|
|
199
|
-
- lib/html
|
|
200
|
-
- lib/html
|
|
201
|
-
- lib/html
|
|
202
|
-
- lib/html
|
|
203
|
-
- lib/html
|
|
204
|
-
- lib/html
|
|
217
|
+
- bin/htmlproofer
|
|
218
|
+
- lib/html-proofer.rb
|
|
219
|
+
- lib/html-proofer/cache.rb
|
|
220
|
+
- lib/html-proofer/check.rb
|
|
221
|
+
- lib/html-proofer/check/favicon.rb
|
|
222
|
+
- lib/html-proofer/check/html.rb
|
|
223
|
+
- lib/html-proofer/check/images.rb
|
|
224
|
+
- lib/html-proofer/check/links.rb
|
|
225
|
+
- lib/html-proofer/check/scripts.rb
|
|
226
|
+
- lib/html-proofer/configuration.rb
|
|
227
|
+
- lib/html-proofer/element.rb
|
|
228
|
+
- lib/html-proofer/issue.rb
|
|
229
|
+
- lib/html-proofer/log.rb
|
|
230
|
+
- lib/html-proofer/runner.rb
|
|
231
|
+
- lib/html-proofer/url_validator.rb
|
|
232
|
+
- lib/html-proofer/utils.rb
|
|
233
|
+
- lib/html-proofer/version.rb
|
|
205
234
|
homepage: https://github.com/gjtorikian/html-proofer
|
|
206
235
|
licenses:
|
|
207
236
|
- MIT
|
|
@@ -222,7 +251,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
222
251
|
version: '0'
|
|
223
252
|
requirements: []
|
|
224
253
|
rubyforge_project:
|
|
225
|
-
rubygems_version: 2.4.5
|
|
254
|
+
rubygems_version: 2.4.5.1
|
|
226
255
|
signing_key:
|
|
227
256
|
specification_version: 4
|
|
228
257
|
summary: A set of tests to validate your HTML output. These tests check if your image
|
data/bin/htmlproof
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
STDOUT.sync = true
|
|
3
|
-
|
|
4
|
-
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), *%w( .. lib ))
|
|
5
|
-
|
|
6
|
-
require 'html/proofer'
|
|
7
|
-
require 'mercenary'
|
|
8
|
-
require 'rubygems'
|
|
9
|
-
|
|
10
|
-
def to_regex?(item)
|
|
11
|
-
if item.start_with?('/') && item.end_with?('/')
|
|
12
|
-
Regexp.new item[1...-1]
|
|
13
|
-
else
|
|
14
|
-
item
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
Mercenary.program(:htmlproof) do |p|
|
|
19
|
-
p.version HTML::Proofer::VERSION
|
|
20
|
-
p.description %(Test your rendered HTML files to make sure they're accurate.)
|
|
21
|
-
p.syntax 'htmlproof PATH [options]'
|
|
22
|
-
|
|
23
|
-
p.description 'Runs the HTML-Proofer suite on the files in PATH. For more details, see the README.'
|
|
24
|
-
|
|
25
|
-
p.option 'as_links', '--as-links', 'Assumes that `PATH` is a comma-separated array of links to check.'
|
|
26
|
-
p.option 'alt_ignore', '--alt-ignore image1,[image2,...]', Array, 'Comma-separated list of Strings or RegExps containing `img`s whose missing `alt` tags are safe to ignore'
|
|
27
|
-
p.option 'empty_alt_ignore', '--empty-alt-ignore', 'Ignores images with empty alt tags.'
|
|
28
|
-
p.option 'checks_to_ignore', '--checks-to-ignore check1,[check2,...]', Array, ' An array of Strings indicating which checks you\'d like to not perform.'
|
|
29
|
-
p.option 'check_external_hash', '--check-external-hash', 'Checks whether external hashes exist (even if the website exists). This slows the checker down (default: `false`).'
|
|
30
|
-
p.option 'check_favicon', '--check-favicon', 'Enables the favicon checker (default: `false`).'
|
|
31
|
-
p.option 'check_html', '--check-html', 'Enables HTML validation errors from Nokogiri (default: `false`).'
|
|
32
|
-
p.option 'directory_index_file', '--directory-index-file', String, 'Sets the file to look for when a link refers to a directory. (default: `index.html`)'
|
|
33
|
-
p.option 'disable_external', '--disable-external', 'Disables the external link checker (default: `false`)'
|
|
34
|
-
p.option 'error_sort', '--error-sort SORT', 'Defines the sort order for error output. Can be `path`, `desc`, or `status` (default: `path`).'
|
|
35
|
-
p.option 'enforce_https', '--enforce-https', 'Fails a link if it\'s not marked as `https` (default: `false`).'
|
|
36
|
-
p.option 'ext', '--ext EXT', String, 'The extension of your HTML files (default: `.html`)'
|
|
37
|
-
p.option 'file_ignore', '--file-ignore file1,[file2,...]', Array, 'Comma-separated list of Strings or RegExps containing file paths that are safe to ignore'
|
|
38
|
-
p.option 'href_ignore', '--href-ignore link1,[link2,...]', Array, 'Comma-separated list of Strings or RegExps containing `href`s that are safe to ignore.'
|
|
39
|
-
p.option 'href_swap', '--href-swap re:string,[re:string,...]', Array, 'Comma-separated list of key-value pairs of `RegExp:String`. Transforms links matching `RegExp` into `String`'
|
|
40
|
-
p.option 'ignore_script_embeds', '--ignore-script-embeds', 'Ignore `check_html` errors associated with `script`s (default: `false`)'
|
|
41
|
-
p.option 'only_4xx', '--only-4xx', 'Only reports errors for links that fall within the 4x status code range.'
|
|
42
|
-
p.option 'url_ignore', '--url-ignore link1,[link2,...]', Array, 'Comma-separated list of Strings or RegExps containing URLs that are safe to ignore.'
|
|
43
|
-
p.option 'verbose', '--verbose', 'Enables more verbose logging.'
|
|
44
|
-
p.option 'verbosity', '--verbosity', String, 'Sets the logging level, as determined by Yell'
|
|
45
|
-
|
|
46
|
-
p.action do |args, opts|
|
|
47
|
-
args = ['.'] if args.empty?
|
|
48
|
-
path = args.first
|
|
49
|
-
|
|
50
|
-
options = {}
|
|
51
|
-
|
|
52
|
-
# prepare everything to go to proofer
|
|
53
|
-
p.options.select { |o| !opts[o.config_key].nil? }.each do |option|
|
|
54
|
-
if option.return_type.to_s == 'Array' # TODO: is_a? doesn't work here?
|
|
55
|
-
opts[option.config_key] = opts[option.config_key].map { |i| to_regex?(i) }
|
|
56
|
-
end
|
|
57
|
-
options[option.config_key.to_sym] = opts[option.config_key]
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# some minor manipulation of a special option
|
|
61
|
-
unless opts['href_swap'].nil?
|
|
62
|
-
options[:href_swap] = {}
|
|
63
|
-
opts['href_swap'].each do |s|
|
|
64
|
-
pair = s.split(':', 2)
|
|
65
|
-
options[:href_swap][Regexp.new(pair[0])] = pair[1]
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
# check for ignore_scripts_embeds as it should be set in :validation
|
|
70
|
-
unless opts['ignore_script_embeds'].nil?
|
|
71
|
-
options[:validation] = { :ignore_script_embeds => true }
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
options[:error_sort] = opts['error-sort'].to_sym unless opts['error-sort'].nil?
|
|
75
|
-
options[:verbosity] = opts['verbosity'].to_sym unless opts['verbosity'].nil?
|
|
76
|
-
|
|
77
|
-
# FIXME: this is gross
|
|
78
|
-
options[:validation] = {}
|
|
79
|
-
options[:validation][:ignore_script_embeds] = opts['ignore_script_embeds']
|
|
80
|
-
|
|
81
|
-
path = path.delete(' ').split(',') if opts['as_links']
|
|
82
|
-
|
|
83
|
-
HTML::Proofer.new(path, options).run
|
|
84
|
-
end
|
|
85
|
-
end
|
data/lib/html/proofer/cache.rb
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
module HTML
|
|
2
|
-
class Proofer
|
|
3
|
-
module Cache
|
|
4
|
-
def create_nokogiri(path)
|
|
5
|
-
if File.exist? path
|
|
6
|
-
content = File.open(path).read
|
|
7
|
-
else
|
|
8
|
-
content = path
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
Nokogiri::HTML(content)
|
|
12
|
-
end
|
|
13
|
-
module_function :create_nokogiri
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
|
|
3
|
-
module HTML
|
|
4
|
-
class Proofer
|
|
5
|
-
# Mostly handles issue management and collecting of external URLs.
|
|
6
|
-
class CheckRunner
|
|
7
|
-
|
|
8
|
-
attr_reader :issues, :src, :path, :options, :typhoeus_opts, :hydra_opts, :parallel_opts, \
|
|
9
|
-
:validation_opts, :external_urls, :href_ignores, :url_ignores, :alt_ignores, \
|
|
10
|
-
:empty_alt_ignore
|
|
11
|
-
|
|
12
|
-
def initialize(src, path, html, options, typhoeus_opts, hydra_opts, parallel_opts, validation_opts)
|
|
13
|
-
@src = src
|
|
14
|
-
@path = path
|
|
15
|
-
@html = remove_ignored(html)
|
|
16
|
-
@options = options
|
|
17
|
-
@typhoeus_opts = typhoeus_opts
|
|
18
|
-
@hydra_opts = hydra_opts
|
|
19
|
-
@parallel_opts = parallel_opts
|
|
20
|
-
@validation_opts = validation_opts
|
|
21
|
-
@issues = []
|
|
22
|
-
@href_ignores = @options[:href_ignore]
|
|
23
|
-
@url_ignores = @options[:url_ignore]
|
|
24
|
-
@alt_ignores = @options[:alt_ignore]
|
|
25
|
-
@empty_alt_ignore = @options[:empty_alt_ignore]
|
|
26
|
-
@external_urls = {}
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def run
|
|
30
|
-
fail NotImplementedError, 'HTML::Proofer::CheckRunner subclasses must implement #run'
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def add_issue(desc, line_number = nil, status = -1)
|
|
34
|
-
@issues << Issue.new(@path, desc, line_number, status)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def add_to_external_urls(url, line)
|
|
38
|
-
return if @external_urls[url]
|
|
39
|
-
add_path_for_url(url)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def add_path_for_url(url)
|
|
43
|
-
if @external_urls[url]
|
|
44
|
-
@external_urls[url] << @path
|
|
45
|
-
else
|
|
46
|
-
@external_urls[url] = [@path]
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def self.checks
|
|
51
|
-
classes = []
|
|
52
|
-
|
|
53
|
-
ObjectSpace.each_object(Class) do |c|
|
|
54
|
-
next unless c.superclass == self
|
|
55
|
-
classes << c
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
classes
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
private
|
|
62
|
-
|
|
63
|
-
def remove_ignored(html)
|
|
64
|
-
html.css('code, pre, tt').each(&:unlink)
|
|
65
|
-
html
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
require 'addressable/uri'
|
|
2
|
-
require_relative './utils'
|
|
3
|
-
|
|
4
|
-
module HTML
|
|
5
|
-
class Proofer
|
|
6
|
-
# Represents the superclass from which all checks derive.
|
|
7
|
-
class Checkable
|
|
8
|
-
include HTML::Proofer::Utils
|
|
9
|
-
|
|
10
|
-
attr_reader :line
|
|
11
|
-
|
|
12
|
-
def initialize(obj, check)
|
|
13
|
-
obj.attributes.each_pair do |attribute, value|
|
|
14
|
-
instance_variable_set("@#{attribute.tr('-:.', '_')}".to_sym, value.value)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
@text = obj.content
|
|
18
|
-
@check = check
|
|
19
|
-
@checked_paths = {}
|
|
20
|
-
@type = self.class.name
|
|
21
|
-
@line = obj.line
|
|
22
|
-
|
|
23
|
-
if @href && @check.options[:href_swap]
|
|
24
|
-
@href = swap(@href, @check.options[:href_swap])
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# fix up missing protocols
|
|
28
|
-
@href.insert 0, 'http:' if @href =~ %r{^//}
|
|
29
|
-
@src.insert 0, 'http:' if @src =~ %r{^//}
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def url
|
|
33
|
-
@src || @srcset || @href || ''
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def valid?
|
|
37
|
-
!parts.nil?
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def parts
|
|
41
|
-
@parts ||= Addressable::URI.parse url
|
|
42
|
-
rescue URI::Error, Addressable::URI::InvalidURIError
|
|
43
|
-
@parts = nil
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def path
|
|
47
|
-
Addressable::URI.unencode parts.path unless parts.nil?
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def hash
|
|
51
|
-
parts.fragment unless parts.nil?
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def scheme
|
|
55
|
-
parts.scheme unless parts.nil?
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# path is to an external server
|
|
59
|
-
def remote?
|
|
60
|
-
%w( http https ).include? scheme
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def non_http_remote?
|
|
64
|
-
!scheme.nil? && !remote?
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def ignore?
|
|
68
|
-
return true if @data_proofer_ignore
|
|
69
|
-
|
|
70
|
-
# ignore base64 encoded images
|
|
71
|
-
if %w(ImageCheckable FaviconCheckable).include? @type
|
|
72
|
-
return true if url.match(/^data:image/)
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
# ignore user defined URLs
|
|
76
|
-
return true if ignores_pattern_check(@check.url_ignores)
|
|
77
|
-
|
|
78
|
-
# ignore user defined hrefs
|
|
79
|
-
if 'LinkCheckable' == @type
|
|
80
|
-
return true if ignores_pattern_check(@check.href_ignores)
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
# ignore user defined alts
|
|
84
|
-
if 'ImageCheckable' == @type
|
|
85
|
-
return true if ignores_pattern_check(@check.alt_ignores)
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def ignore_empty_alt?
|
|
90
|
-
@check.empty_alt_ignore
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# path is external to the file
|
|
94
|
-
def external?
|
|
95
|
-
!internal?
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
# path is an anchor or a query
|
|
99
|
-
def internal?
|
|
100
|
-
url.start_with? '#', '?'
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def file_path
|
|
104
|
-
return if path.nil?
|
|
105
|
-
|
|
106
|
-
if path =~ %r{^/} # path relative to root
|
|
107
|
-
base = File.directory?(@check.src) ? @check.src : File.dirname(@check.src)
|
|
108
|
-
elsif File.exist?(File.expand_path path, @check.src) # relative links, path is a file
|
|
109
|
-
base = File.dirname @check.path
|
|
110
|
-
elsif File.exist?(File.join(File.dirname(@check.path), path)) # relative links in nested dir, path is a file
|
|
111
|
-
base = File.dirname @check.path
|
|
112
|
-
else # relative link, path is a directory
|
|
113
|
-
base = @check.path
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
file = File.join base, path
|
|
117
|
-
|
|
118
|
-
# implicit index support
|
|
119
|
-
if File.directory?(file) && !unslashed_directory?(file)
|
|
120
|
-
file = File.join file, @check.options[:directory_index_file]
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
file
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
# checks if a file exists relative to the current pwd
|
|
127
|
-
def exists?
|
|
128
|
-
return @checked_paths[absolute_path] if @checked_paths.key? absolute_path
|
|
129
|
-
@checked_paths[absolute_path] = File.exist? absolute_path
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
def absolute_path
|
|
133
|
-
path = file_path || @check.path
|
|
134
|
-
File.expand_path path, Dir.pwd
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
def ignores_pattern_check(links)
|
|
138
|
-
links.each do |ignore|
|
|
139
|
-
if ignore.is_a? String
|
|
140
|
-
return true if ignore == url
|
|
141
|
-
elsif ignore.is_a? Regexp
|
|
142
|
-
return true if ignore =~ url
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
false
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
def unslashed_directory?(file)
|
|
150
|
-
File.directory?(file) && !file.end_with?(File::SEPARATOR) && !follow_location?
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
def follow_location?
|
|
154
|
-
@check.typhoeus_opts && @check.typhoeus_opts[:followlocation]
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
private
|
|
158
|
-
|
|
159
|
-
def real_attr(attr)
|
|
160
|
-
attr.to_s unless attr.nil? || attr.empty?
|
|
161
|
-
end
|
|
162
|
-
end
|
|
163
|
-
end
|
|
164
|
-
end
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
|
|
3
|
-
class HtmlCheck < ::HTML::Proofer::CheckRunner
|
|
4
|
-
# new html5 tags (source: http://www.w3schools.com/html/html5_new_elements.asp)
|
|
5
|
-
# and svg child tags (source: https://developer.mozilla.org/en-US/docs/Web/SVG/Element)
|
|
6
|
-
HTML5_TAGS = %w(article aside bdi details dialog figcaption
|
|
7
|
-
figure footer header main mark menuitem meter
|
|
8
|
-
nav progress rp rt ruby section summary
|
|
9
|
-
time wbr datalist keygen output color date
|
|
10
|
-
datetime datetime-local email month number
|
|
11
|
-
range search tel time url week canvas
|
|
12
|
-
svg audio embed source track video
|
|
13
|
-
altGlyph altGlyphDef altGlyphItem animate
|
|
14
|
-
animateColor animateMotion animateTransform
|
|
15
|
-
circle clipPath color-profile cursor defs
|
|
16
|
-
desc ellipse feBlend feColorMatrix
|
|
17
|
-
feComponentTransfer feComposite feConvolveMatrix
|
|
18
|
-
feDiffuseLighting feDisplacementMap feDistantLight
|
|
19
|
-
feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur
|
|
20
|
-
feImage feMerge feMergeNode feMorphology feOffset
|
|
21
|
-
fePointLight feSpecularLighting feSpotLight feTile
|
|
22
|
-
feTurbulence filter font font-face font-face-format
|
|
23
|
-
font-face-name font-face-src font-face-uri
|
|
24
|
-
foreignObject g glyph glyphRef hkern image line
|
|
25
|
-
linearGradient marker mask metadata missing-glyph
|
|
26
|
-
mpath path pattern polygon polyline radialGradient
|
|
27
|
-
rect set stop switch symbol text textPath tref tspan use
|
|
28
|
-
view vkern)
|
|
29
|
-
|
|
30
|
-
SCRIPT_EMBEDS_MSG = /Element script embeds close tag/
|
|
31
|
-
|
|
32
|
-
def run
|
|
33
|
-
@html.errors.each do |error|
|
|
34
|
-
message = error.message
|
|
35
|
-
line = error.line
|
|
36
|
-
# Nokogiri (or rather libxml2 underhood) only recognizes html4 tags,
|
|
37
|
-
# so we need to skip errors caused by the new tags in html5
|
|
38
|
-
next if HTML5_TAGS.include? message[/Tag ([\w-]+) invalid/o, 1]
|
|
39
|
-
|
|
40
|
-
# tags embedded in scripts are used in templating languages: http://git.io/vOovv
|
|
41
|
-
next if @validation_opts[:ignore_script_embeds] && message =~ SCRIPT_EMBEDS_MSG
|
|
42
|
-
|
|
43
|
-
add_issue(message, line)
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
|
|
3
|
-
class ImageCheckable < ::HTML::Proofer::Checkable
|
|
4
|
-
SCREEN_SHOT_REGEX = /Screen(?: |%20)Shot(?: |%20)\d+-\d+-\d+(?: |%20)at(?: |%20)\d+.\d+.\d+/
|
|
5
|
-
|
|
6
|
-
attr_reader :alt
|
|
7
|
-
|
|
8
|
-
def empty_alt_tag?
|
|
9
|
-
alt.strip.empty?
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def terrible_filename?
|
|
13
|
-
src =~ SCREEN_SHOT_REGEX
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def src
|
|
17
|
-
real_attr(@src) || real_attr(@srcset)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def missing_src?
|
|
21
|
-
!src
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
class ImageCheck < ::HTML::Proofer::CheckRunner
|
|
26
|
-
def run
|
|
27
|
-
@html.css('img').each do |node|
|
|
28
|
-
img = ImageCheckable.new(node, self)
|
|
29
|
-
line = node.line
|
|
30
|
-
|
|
31
|
-
next if img.ignore?
|
|
32
|
-
|
|
33
|
-
# screenshot filenames should return because of terrible names
|
|
34
|
-
next add_issue("image has a terrible filename (#{img.src})", line) if img.terrible_filename?
|
|
35
|
-
|
|
36
|
-
# does the image exist?
|
|
37
|
-
if img.missing_src?
|
|
38
|
-
add_issue('image has no src or srcset attribute', line)
|
|
39
|
-
else
|
|
40
|
-
if img.remote?
|
|
41
|
-
add_to_external_urls(img.src, line)
|
|
42
|
-
else
|
|
43
|
-
add_issue("internal image #{img.src} does not exist", line) unless img.exists?
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
if img.alt.nil? || (img.empty_alt_tag? && !img.ignore_empty_alt?)
|
|
48
|
-
add_issue("image #{img.src} does not have an alt attribute", line)
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
external_urls
|
|
53
|
-
end
|
|
54
|
-
end
|