html-proofer 0.3.0 → 0.4.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/Gemfile.lock +5 -5
- data/README.md +17 -4
- data/html-proofer.gemspec +1 -1
- data/lib/html/proofer.rb +77 -11
- data/lib/html/proofer/check.rb +8 -42
- data/lib/html/proofer/checkable.rb +7 -7
- data/lib/html/proofer/checks/images.rb +8 -5
- data/lib/html/proofer/checks/links.rb +6 -5
- data/lib/html/proofer/version.rb +1 -1
- data/spec/html/proofer/fixtures/folder/assets/barrel.png +0 -0
- data/spec/html/proofer/fixtures/folder/relativeImage.html +2 -0
- data/spec/html/proofer/fixtures/linkWithRedirect.html +3 -2
- data/spec/html/proofer/fixtures/relativeLinks.html +2 -0
- data/spec/html/proofer/fixtures/resources/books/assets/getting-good-with-git.jpg +0 -0
- data/spec/html/proofer/fixtures/resources/books/assets/pro-git.jpg +0 -0
- data/spec/html/proofer/fixtures/resources/books/assets/version-control-with-git.jpg +0 -0
- data/spec/html/proofer/fixtures/resources/books/nestedRelativeImages.html +5 -0
- data/spec/html/proofer/fixtures/rootRelativeImages.html +2 -0
- data/spec/html/proofer/images_spec.rb +26 -26
- data/spec/html/proofer/links_spec.rb +26 -41
- data/spec/spec_helper.rb +16 -1
- metadata +18 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 96ef995058e63021380229872126e11c18216d4a
|
4
|
+
data.tar.gz: 97f17a39a973e7819f52cbb0611f9f64f0152f94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 459bf3c2a753d660993f17ba982367a2ae395a04d3866bacb590f687c82b5929138fa596282d2ecac95f7644128777fceaa2fbeb2967737beb3d02cdd9d37c5d
|
7
|
+
data.tar.gz: 953d20ddcd61d8af3bec8eb7b9ffc2c8f532a16f9241960ee7040255b87079a4c8b72ba0210c411fbd4597833bf8f94d0d3f65c57870f88471d29bbf3c284838
|
data/Gemfile.lock
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
html-proofer (0.
|
4
|
+
html-proofer (0.3.0)
|
5
5
|
colored (~> 1.2)
|
6
6
|
mercenary (~> 0.2.0)
|
7
7
|
nokogiri (~> 1.6.0)
|
8
|
-
typhoeus (~> 0.6.
|
8
|
+
typhoeus (~> 0.6.7)
|
9
9
|
|
10
10
|
GEM
|
11
11
|
remote: http://rubygems.org/
|
@@ -20,7 +20,7 @@ GEM
|
|
20
20
|
colored (1.2)
|
21
21
|
diff-lcs (1.2.4)
|
22
22
|
escape_utils (0.3.2)
|
23
|
-
ethon (0.6.
|
23
|
+
ethon (0.6.2)
|
24
24
|
ffi (>= 1.3.0)
|
25
25
|
mime-types (~> 1.18)
|
26
26
|
ffi (1.9.3)
|
@@ -56,8 +56,8 @@ GEM
|
|
56
56
|
nokogiri (>= 1.4.4)
|
57
57
|
thread_safe (0.1.3)
|
58
58
|
atomic
|
59
|
-
typhoeus (0.6.
|
60
|
-
ethon (~> 0.6.
|
59
|
+
typhoeus (0.6.7)
|
60
|
+
ethon (~> 0.6.2)
|
61
61
|
tzinfo (0.3.38)
|
62
62
|
|
63
63
|
PLATFORMS
|
data/README.md
CHANGED
@@ -69,7 +69,9 @@ Note: since `swap` is a bit special, you'll pass in a pair of `RegEx:String` val
|
|
69
69
|
|
70
70
|
## Usage with Jekyll
|
71
71
|
|
72
|
-
Want to use HTML Proofer with your Jekyll site? Awesome. Simply add `gem 'html-proofer'`
|
72
|
+
Want to use HTML Proofer with your Jekyll site? Awesome. Simply add `gem 'html-proofer'`
|
73
|
+
to your `Gemfile` as described above, and add the following to your `Rakefile`,
|
74
|
+
using `rake test` to execute:
|
73
75
|
|
74
76
|
```ruby
|
75
77
|
require 'html/proofer'
|
@@ -94,12 +96,23 @@ htmlproof ./_site
|
|
94
96
|
* Whether your internal links are not broken; this includes hash references (`#linkToMe`)
|
95
97
|
* Whether external links are working
|
96
98
|
|
97
|
-
## Configuration
|
99
|
+
## Configuration
|
98
100
|
|
99
101
|
The `HTML::Proofer` constructor takes an optional hash of additional options:
|
100
102
|
|
101
103
|
* `:ext`: the extension (including the `.`) of your HTML files (default: `.html`)
|
102
104
|
* `:href_swap`: a hash containing key-value pairs of `RegExp => String`. It transforms links that match `RegExp` into `String` via `gsub`.
|
103
|
-
* `:href_ignore`: an array of Strings containing `href`s that are safe to ignore (default
|
105
|
+
* `:href_ignore`: an array of Strings containing `href`s that are safe to ignore (by default, `mailto` is always ignored)
|
106
|
+
* `:disable_external`: if `true`, does not run the external link checker, which can take a lot of time (default: `false`)
|
104
107
|
|
105
|
-
|
108
|
+
You can also pass in any of Typhoeus' options for the external link check. For example:
|
109
|
+
|
110
|
+
``` ruby
|
111
|
+
HTML::Proofer.new("out/", {:ext => ".htm", :verbose = > true, :ssl_verifyhost => 2 })
|
112
|
+
```
|
113
|
+
|
114
|
+
This sets `HTML::Proofer`'s' extensions to use _.htm_, and gives Typhoeus a configurtion for it to be verbose, and use specific SSL settings. Check [the Typhoeus documentation](https://github.com/typhoeus/typhoeus#other-curl-options) for more information on what options it can receive.
|
115
|
+
|
116
|
+
## Ignoring links
|
117
|
+
|
118
|
+
To any `<a>` or `<img>` tag, you may add the `data-proofer-ignore` attribute to ignore the link.
|
data/html-proofer.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.add_dependency "mercenary", "~> 0.2.0"
|
19
19
|
gem.add_dependency "nokogiri", "~> 1.6.0"
|
20
20
|
gem.add_dependency "colored", "~> 1.2"
|
21
|
-
gem.add_dependency "typhoeus", "~> 0.6.
|
21
|
+
gem.add_dependency "typhoeus", "~> 0.6.7"
|
22
22
|
|
23
23
|
gem.add_development_dependency "html-pipeline", "~> 0.0.12"
|
24
24
|
gem.add_development_dependency "rspec", "~> 2.13.0"
|
data/lib/html/proofer.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'nokogiri'
|
2
|
+
|
2
3
|
require File.dirname(__FILE__) + '/proofer/checkable'
|
3
4
|
require File.dirname(__FILE__) + '/proofer/checks'
|
4
5
|
|
@@ -6,44 +7,109 @@ module HTML
|
|
6
7
|
class Proofer
|
7
8
|
def initialize(src, opts={})
|
8
9
|
@srcDir = src
|
9
|
-
|
10
|
+
|
11
|
+
@proofer_opts = {:ext => ".html", :href_swap => [], :href_ignore => [], :disable_external => false }
|
12
|
+
@options = @proofer_opts.merge({:followlocation => true}).merge(opts)
|
13
|
+
|
14
|
+
@failed_tests = []
|
10
15
|
end
|
11
16
|
|
12
17
|
def run
|
13
18
|
total_files = 0
|
14
|
-
|
19
|
+
external_urls = {}
|
15
20
|
|
16
|
-
puts "Running #{get_checks} checks on #{@srcDir}... \n\n"
|
21
|
+
puts "Running #{get_checks} checks on #{@srcDir} on *#{@options[:ext]}... \n\n"
|
17
22
|
|
18
|
-
|
23
|
+
files.each do |path|
|
19
24
|
total_files += 1
|
20
25
|
html = HTML::Proofer.create_nokogiri(path)
|
21
26
|
|
22
27
|
get_checks.each do |klass|
|
23
28
|
check = klass.new(@srcDir, path, html, @options)
|
24
29
|
check.run
|
25
|
-
check.
|
26
|
-
failed_tests.concat(check.issues) if check.issues.length > 0
|
30
|
+
external_urls.merge!(check.external_urls)
|
31
|
+
@failed_tests.concat(check.issues) if check.issues.length > 0
|
27
32
|
end
|
28
33
|
end
|
29
34
|
|
35
|
+
# the hypothesis is that Proofer runs way faster if we pull out
|
36
|
+
# all the external URLs and run the checks at the end. Otherwise, we're halting
|
37
|
+
# the consuming process for every file. In addition, sorting the list lets
|
38
|
+
# libcurl keep connections to hosts alive. Finally, we'll make a HEAD request,
|
39
|
+
# rather than GETing all the contents
|
40
|
+
external_urls = Hash[external_urls.sort]
|
41
|
+
|
42
|
+
unless @options[:disable_external]
|
43
|
+
puts "Checking #{external_urls.length} external links... \n\n"
|
44
|
+
|
45
|
+
# Typhoeus won't let you pass any non-Typhoeus option
|
46
|
+
@proofer_opts.each_key do |opt|
|
47
|
+
@options.delete opt
|
48
|
+
end
|
49
|
+
|
50
|
+
external_urls.each_pair do |href, filenames|
|
51
|
+
request = Typhoeus::Request.new(href, @options.merge({:method => :head}))
|
52
|
+
request.on_complete { |response| response_handler(response, filenames) }
|
53
|
+
hydra.queue request
|
54
|
+
end
|
55
|
+
hydra.run
|
56
|
+
end
|
57
|
+
|
30
58
|
puts "Ran on #{total_files} files!"
|
31
59
|
|
32
|
-
if failed_tests.empty?
|
60
|
+
if @failed_tests.empty?
|
33
61
|
puts "HTML-Proofer finished successfully.".green
|
34
|
-
exit 0
|
35
62
|
else
|
36
|
-
failed_tests.each do |issue|
|
63
|
+
@failed_tests.each do |issue|
|
37
64
|
$stderr.puts issue + "\n\n"
|
38
65
|
end
|
39
66
|
|
40
|
-
raise "HTML-Proofer found #{failed_tests.length} failures!"
|
67
|
+
raise "HTML-Proofer found #{@failed_tests.length} failures!"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def response_handler(response, filenames)
|
72
|
+
href = response.options[:effective_url]
|
73
|
+
method = response.request.options[:method]
|
74
|
+
response_code = response.code
|
75
|
+
|
76
|
+
if response_code.between?(200, 299)
|
77
|
+
# continue with no op
|
78
|
+
elsif response.timed_out?
|
79
|
+
@failed_tests << "#{filenames.join(' ').blue}: External link #{href} failed: got a time out"
|
80
|
+
# hey here's a funny bug: sometimes HEAD requests return a 404, even on legitimate pages! The
|
81
|
+
# bug seems to affect curl; try `curl -I -X HEAD https://help.github.com/changing-author-info`
|
82
|
+
# so in these cases, try a regular `GET`. if it fails, it fails.
|
83
|
+
elsif response_code == 404 && method == :head
|
84
|
+
next_response = Typhoeus.get(href, @options)
|
85
|
+
response_handler(next_response, filenames)
|
86
|
+
elsif (response_code == 420 || response_code == 503) && method == :head
|
87
|
+
# 420s usually come from rate limiting; let's ignore the query and try just the path with a GET
|
88
|
+
uri = URI(href)
|
89
|
+
next_response = Typhoeus.get(uri.scheme + "://" + uri.host + uri.path, @options)
|
90
|
+
response_handler(next_response, filenames)
|
91
|
+
else
|
92
|
+
# Received a non-successful http response.
|
93
|
+
@failed_tests << "#{filenames.join(' ').blue}: External link #{href} failed: #{response_code} #{response.return_message}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def hydra
|
98
|
+
@hydra ||= Typhoeus::Hydra.new
|
99
|
+
end
|
100
|
+
|
101
|
+
def files
|
102
|
+
if File.directory? @srcDir
|
103
|
+
Dir.glob("#{@srcDir}/**/*#{@options[:ext]}")
|
104
|
+
else
|
105
|
+
File.extname(@srcDir) == @options[:ext] ? [@srcDir] : []
|
41
106
|
end
|
42
107
|
end
|
43
108
|
|
44
109
|
def self.create_nokogiri(path)
|
45
110
|
path << "/index.html" if File.directory? path # support for Jekyll-style links
|
46
|
-
|
111
|
+
content = File.open(path, "rb") {|f| f.read }
|
112
|
+
Nokogiri::HTML(content)
|
47
113
|
end
|
48
114
|
|
49
115
|
def get_checks
|
data/lib/html/proofer/check.rb
CHANGED
@@ -10,7 +10,7 @@ class HTML::Proofer::Checks
|
|
10
10
|
|
11
11
|
class Check
|
12
12
|
|
13
|
-
attr_reader :issues, :
|
13
|
+
attr_reader :issues, :src, :path, :options, :external_urls, :additional_href_ignores
|
14
14
|
|
15
15
|
def initialize(src, path, html, opts={})
|
16
16
|
@src = src
|
@@ -18,10 +18,8 @@ class HTML::Proofer::Checks
|
|
18
18
|
@html = html
|
19
19
|
@options = opts
|
20
20
|
@issues = []
|
21
|
-
@
|
22
|
-
|
23
|
-
@hydra = Typhoeus::Hydra.hydra
|
24
|
-
@additional_href_ignores = @options[:href_ignore] || []
|
21
|
+
@additional_href_ignores = @options[:href_ignore]
|
22
|
+
@external_urls = {}
|
25
23
|
end
|
26
24
|
|
27
25
|
def run
|
@@ -36,44 +34,12 @@ class HTML::Proofer::Checks
|
|
36
34
|
Dir[@site.config[:output_dir] + '/**/*'].select{ |f| File.file?(f) }
|
37
35
|
end
|
38
36
|
|
39
|
-
def
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
@checked_urls[href] = true
|
45
|
-
elsif response.timed_out?
|
46
|
-
self.add_issue(issue_text + " got a time out")
|
47
|
-
elsif response.code == 0
|
48
|
-
# Could not get an http response, something's wrong.
|
49
|
-
self.add_issue(issue_text + ". #{response.return_message}!")
|
50
|
-
else
|
51
|
-
response_code = response.code.to_s
|
52
|
-
if %w(420 503).include?(response_code)
|
53
|
-
# 420s usually come from rate limiting; let's ignore the query and try just the path
|
54
|
-
uri = URI(href)
|
55
|
-
response = Typhoeus.get(uri.scheme + "://" + uri.host + uri.path, {:followlocation => true})
|
56
|
-
self.add_issue("#{issue_text} Originally, this was a #{response_code}. Now, the HTTP request failed again: #{response.code.to_s}") unless response.success?
|
57
|
-
else
|
58
|
-
# Received a non-successful http response.
|
59
|
-
self.add_issue("#{issue_text} HTTP request failed: #{response_code}")
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
@checked_urls[href] = false unless response.success?
|
64
|
-
end
|
65
|
-
hydra.queue(request)
|
66
|
-
end
|
67
|
-
|
68
|
-
def request_url(url)
|
69
|
-
path = (url.path.nil? || url.path.empty? ? '/' : url.path)
|
70
|
-
req = Net::HTTP::Head.new(path)
|
71
|
-
http = Net::HTTP.new(url.host, url.port)
|
72
|
-
if url.instance_of? URI::HTTPS
|
73
|
-
http.use_ssl = true
|
74
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
37
|
+
def add_to_external_urls(href)
|
38
|
+
if @external_urls[href]
|
39
|
+
@external_urls[href] << @path
|
40
|
+
else
|
41
|
+
@external_urls[href] = [@path]
|
75
42
|
end
|
76
|
-
res = http.request(req)
|
77
43
|
end
|
78
44
|
|
79
45
|
def self.subclasses
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module HTML
|
2
2
|
class Proofer
|
3
3
|
class Checkable
|
4
|
-
|
5
4
|
def initialize(obj, check)
|
6
5
|
@src = obj['src']
|
7
6
|
@href = obj['href']
|
@@ -56,7 +55,7 @@ module HTML
|
|
56
55
|
|
57
56
|
def ignore?
|
58
57
|
uri = URI.parse url
|
59
|
-
@data_ignore_proofer || %w( mailto ).include?(uri.scheme) || @check.additional_href_ignores.include?(
|
58
|
+
@data_ignore_proofer || %w( mailto ).include?(uri.scheme) || @check.additional_href_ignores.include?(url)
|
60
59
|
rescue URI::BadURIError
|
61
60
|
false
|
62
61
|
rescue URI::InvalidURIError
|
@@ -76,11 +75,13 @@ module HTML
|
|
76
75
|
def file_path
|
77
76
|
return if path.nil?
|
78
77
|
|
79
|
-
if path =~ /^\// #path relative to root
|
80
|
-
base = @check.src
|
81
|
-
elsif File.exist?
|
78
|
+
if path =~ /^\// # path relative to root
|
79
|
+
base = File.directory?(@check.src) ? @check.src : File.dirname(@check.src)
|
80
|
+
elsif File.exist?(File.expand_path path, @check.src) # relative links, path is a file
|
81
|
+
base = File.dirname @check.path
|
82
|
+
elsif File.exist?(File.join(File.dirname(@check.path), path)) # relative links in nested dir, path is a file
|
82
83
|
base = File.dirname @check.path
|
83
|
-
else #relative link, path is a directory
|
84
|
+
else # relative link, path is a directory
|
84
85
|
base = @check.path
|
85
86
|
end
|
86
87
|
|
@@ -102,7 +103,6 @@ module HTML
|
|
102
103
|
path = file_path || @check.path
|
103
104
|
File.expand_path path, Dir.pwd
|
104
105
|
end
|
105
|
-
|
106
106
|
end
|
107
107
|
end
|
108
108
|
end
|
@@ -24,24 +24,27 @@ end
|
|
24
24
|
|
25
25
|
class Images < ::HTML::Proofer::Checks::Check
|
26
26
|
def run
|
27
|
-
@html.css('img').each do |
|
27
|
+
@html.css('img').each do |i|
|
28
|
+
img = Image.new i, self
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
# screenshot filenames, return because invalid URL
|
30
|
+
# screenshot filenames should return because of terrible names
|
32
31
|
return self.add_issue "image has a terrible filename (#{img.src})" if img.terrible_filename?
|
33
32
|
|
34
33
|
# does the image exist?
|
35
34
|
if img.missing_src?
|
36
35
|
self.add_issue "image has no src attribute"
|
37
36
|
elsif img.remote?
|
38
|
-
|
37
|
+
return if img.ignore?
|
38
|
+
add_to_external_urls img.src
|
39
39
|
else
|
40
|
+
return if img.ignore?
|
40
41
|
self.add_issue("internal image #{img.src} does not exist") unless img.exists?
|
41
42
|
end
|
42
43
|
|
43
44
|
# check alt tag
|
44
45
|
self.add_issue "image #{img.src} does not have an alt attribute" unless img.valid_alt_tag?
|
45
46
|
end
|
47
|
+
|
48
|
+
return external_urls
|
46
49
|
end
|
47
50
|
end
|
@@ -15,9 +15,8 @@ end
|
|
15
15
|
class Links < ::HTML::Proofer::Checks::Check
|
16
16
|
|
17
17
|
def run
|
18
|
-
@html.css('a').each do |
|
19
|
-
|
20
|
-
link = Link.new link, self
|
18
|
+
@html.css('a').each do |l|
|
19
|
+
link = Link.new l, self
|
21
20
|
return if link.ignore?
|
22
21
|
|
23
22
|
# is there even a href?
|
@@ -28,7 +27,7 @@ class Links < ::HTML::Proofer::Checks::Check
|
|
28
27
|
|
29
28
|
# does the file even exist?
|
30
29
|
if link.remote?
|
31
|
-
|
30
|
+
add_to_external_urls link.href
|
32
31
|
else
|
33
32
|
self.add_issue "internally linking to #{link.href}, which does not exist" unless link.exists?
|
34
33
|
end
|
@@ -36,7 +35,7 @@ class Links < ::HTML::Proofer::Checks::Check
|
|
36
35
|
# verify the target hash
|
37
36
|
if link.hash
|
38
37
|
if link.remote?
|
39
|
-
|
38
|
+
add_to_external_urls link.href
|
40
39
|
elsif link.internal?
|
41
40
|
self.add_issue "linking to internal hash ##{link.hash} that does not exist" unless hash_check @html, link.hash
|
42
41
|
elsif link.external?
|
@@ -49,6 +48,8 @@ class Links < ::HTML::Proofer::Checks::Check
|
|
49
48
|
end
|
50
49
|
end
|
51
50
|
end
|
51
|
+
|
52
|
+
return external_urls
|
52
53
|
end
|
53
54
|
|
54
55
|
def hash_check(html, href_hash)
|
data/lib/html/proofer/version.rb
CHANGED
Binary file
|
@@ -2,8 +2,9 @@
|
|
2
2
|
|
3
3
|
<body>
|
4
4
|
|
5
|
-
<p>Blah blah blah. <a href="http://
|
5
|
+
<p>Blah blah blah. <a href="http://github.github.com/github-flavored-markdown/">This is a redirect.</a>. </p>
|
6
6
|
|
7
|
+
<p>Blah blah blah. <a href="https://help.github.com/changing-author-info/">This is another redirect.</a>. </p>
|
7
8
|
</body>
|
8
9
|
|
9
|
-
</html>
|
10
|
+
</html>
|
Binary file
|
Binary file
|
@@ -3,59 +3,59 @@ require "spec_helper"
|
|
3
3
|
describe "Image tests" do
|
4
4
|
it "passes for existing external images" do
|
5
5
|
externalImageFilepath = "#{FIXTURES_DIR}/existingImageExternal.html"
|
6
|
-
|
7
|
-
|
8
|
-
@imageCheck.issues[0].should eq(nil)
|
6
|
+
output = capture_stderr { HTML::Proofer.new(externalImageFilepath).run }
|
7
|
+
output.should == ""
|
9
8
|
end
|
10
9
|
|
11
10
|
it "fails for image without alt attribute" do
|
12
11
|
missingAltFilepath = "#{FIXTURES_DIR}/missingImageAlt.html"
|
13
|
-
|
14
|
-
|
15
|
-
@imageCheck.issues[0].should eq("spec/html/proofer/fixtures/missingImageAlt.html".blue + ": image ./gpl.png does not have an alt attribute")
|
12
|
+
output = capture_stderr { HTML::Proofer.new(missingAltFilepath).run }
|
13
|
+
output.should match /gpl.png does not have an alt attribute/
|
16
14
|
end
|
17
15
|
|
18
16
|
it "fails for image with an empty alt attribute" do
|
19
17
|
missingAltFilepath = "#{FIXTURES_DIR}/missingImageAltText.html"
|
20
|
-
|
21
|
-
|
22
|
-
@imageCheck.issues[0].should eq("spec/html/proofer/fixtures/missingImageAltText.html".blue + ": image ./gpl.png does not have an alt attribute")
|
18
|
+
output = capture_stderr { HTML::Proofer.new(missingAltFilepath).run }
|
19
|
+
output.should match /gpl.png does not have an alt attribute/
|
23
20
|
end
|
24
21
|
|
25
22
|
it "fails for missing external images" do
|
26
23
|
externalImageFilepath = "#{FIXTURES_DIR}/missingImageExternal.html"
|
27
|
-
|
28
|
-
|
29
|
-
@imageCheck.hydra.run
|
30
|
-
@imageCheck.issues[0].sub!(/ #<Typhoeus::Response:[\w]+>/, "")
|
31
|
-
@imageCheck.issues[0].should eq("spec/html/proofer/fixtures/missingImageExternal.html".blue + ": external image http://www.whatthehell does not exist. Couldn't resolve host name!")
|
24
|
+
output = capture_stderr { HTML::Proofer.new(externalImageFilepath).run }
|
25
|
+
output.should match /External link http:\/\/www.whatthehell\/? failed: 0 Couldn't resolve host/
|
32
26
|
end
|
33
27
|
|
34
28
|
it "fails for missing internal images" do
|
35
29
|
internalImageFilepath = "#{FIXTURES_DIR}/missingImageInternal.html"
|
36
|
-
|
37
|
-
|
38
|
-
@imageCheck.issues[0].should eq("spec/html/proofer/fixtures/missingImageInternal.html".blue + ": internal image ./doesnotexist.png does not exist")
|
30
|
+
output = capture_stderr { HTML::Proofer.new(internalImageFilepath).run }
|
31
|
+
output.should match /doesnotexist.png does not exist/
|
39
32
|
end
|
40
33
|
|
41
34
|
it "fails for image with no src" do
|
42
35
|
imageSrcFilepath = "#{FIXTURES_DIR}/missingImageSrc.html"
|
43
|
-
|
44
|
-
|
45
|
-
@imageCheck.issues[0].should eq("spec/html/proofer/fixtures/missingImageSrc.html".blue + ": image has no src attribute")
|
36
|
+
output = capture_stderr { HTML::Proofer.new(imageSrcFilepath).run }
|
37
|
+
output.should match /image has no src attribute/
|
46
38
|
end
|
47
39
|
|
48
40
|
it "fails for image with default mac filename" do
|
49
41
|
terribleImageName = "#{FIXTURES_DIR}/terribleImageName.html"
|
50
|
-
|
51
|
-
|
52
|
-
@imageCheck.issues[0].should eq("spec/html/proofer/fixtures/terribleImageName.html".blue + ": image has a terrible filename (./Screen Shot 2012-08-09 at 7.51.18 AM.png)")
|
42
|
+
output = capture_stderr { HTML::Proofer.new(terribleImageName).run }
|
43
|
+
output.should match /image has a terrible filename/
|
53
44
|
end
|
54
45
|
|
55
46
|
it 'ignores images marked as ignore data-proofer-ignore' do
|
56
47
|
ignorableImages = "#{FIXTURES_DIR}/ignorableImages.html"
|
57
|
-
|
58
|
-
|
59
|
-
|
48
|
+
output = capture_stderr { HTML::Proofer.new(ignorableImages).run }
|
49
|
+
output.should == ""
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'properly checks relative images' do
|
53
|
+
relativeImages = "#{FIXTURES_DIR}/rootRelativeImages.html"
|
54
|
+
output = capture_stderr { HTML::Proofer.new(relativeImages).run }
|
55
|
+
output.should == ""
|
56
|
+
|
57
|
+
relativeImages = "#{FIXTURES_DIR}/resources/books/nestedRelativeImages.html"
|
58
|
+
output = capture_stderr { HTML::Proofer.new(relativeImages).run }
|
59
|
+
output.should == ""
|
60
60
|
end
|
61
61
|
end
|
@@ -4,94 +4,79 @@ describe "Links tests" do
|
|
4
4
|
|
5
5
|
it "fails for broken external hash (even if the file exists)" do
|
6
6
|
brokenHashExternalFilepath = "#{FIXTURES_DIR}/brokenHashExternal.html"
|
7
|
-
|
8
|
-
|
9
|
-
@linkCheck.issues[1].should eq("spec/html/proofer/fixtures/brokenHashExternal.html".blue + ": linking to ./missingImageAlt.html#asdfasfdkafl, but asdfasfdkafl does not exist")
|
7
|
+
output = capture_stderr { HTML::Proofer.new(brokenHashExternalFilepath).run }
|
8
|
+
output.should match /linking to .\/missingImageAlt.html#asdfasfdkafl, but asdfasfdkafl does not exist/
|
10
9
|
end
|
11
10
|
|
12
11
|
it "fails for broken internal hash" do
|
13
12
|
brokenHashInternalFilepath = "#{FIXTURES_DIR}/brokenHashInternal.html"
|
14
|
-
|
15
|
-
|
16
|
-
@linkCheck.issues[0].should eq("spec/html/proofer/fixtures/brokenHashInternal.html".blue + ": linking to internal hash #noHash that does not exist")
|
13
|
+
output = capture_stderr { HTML::Proofer.new(brokenHashInternalFilepath).run }
|
14
|
+
output.should match /linking to internal hash #noHash that does not exist/
|
17
15
|
end
|
18
16
|
|
19
17
|
it "fails for broken external links" do
|
20
18
|
brokenLinkExternalFilepath = "#{FIXTURES_DIR}/brokenLinkExternal.html"
|
21
|
-
|
22
|
-
|
23
|
-
@linkCheck.hydra.run
|
24
|
-
@linkCheck.issues[0].sub!(/ #<Typhoeus::Response:[\w]+>/, "")
|
25
|
-
@linkCheck.issues[0].should eq("spec/html/proofer/fixtures/brokenLinkExternal.html".blue + ": externally linking to http://www.asdo3IRJ395295jsingrkrg4.com, which does not exist. Couldn't resolve host name!")
|
19
|
+
output = capture_stderr { HTML::Proofer.new(brokenLinkExternalFilepath).run }
|
20
|
+
output.should match /External link http:\/\/www.asdo3IRJ395295jsingrkrg4.com\/? failed: 0 Couldn't resolve host name/
|
26
21
|
end
|
27
22
|
|
28
23
|
it "fails for broken internal links" do
|
29
24
|
brokenLinkInternalFilepath = "#{FIXTURES_DIR}/brokenLinkInternal.html"
|
30
|
-
|
31
|
-
|
32
|
-
@linkCheck.issues[0].should eq("spec/html/proofer/fixtures/brokenLinkInternal.html".blue + ": internally linking to ./notreal.html, which does not exist")
|
25
|
+
output = capture_stderr { HTML::Proofer.new(brokenLinkInternalFilepath).run }
|
26
|
+
output.should match /internally linking to .\/notreal.html, which does not exist/
|
33
27
|
end
|
34
28
|
|
35
29
|
it "fails for link with no href" do
|
36
30
|
missingLinkHrefFilepath = "#{FIXTURES_DIR}/missingLinkHref.html"
|
37
|
-
|
38
|
-
|
39
|
-
@linkCheck.issues[0].should eq("spec/html/proofer/fixtures/missingLinkHref.html".blue + ": link has no href attribute")
|
31
|
+
output = capture_stderr { HTML::Proofer.new(missingLinkHrefFilepath).run }
|
32
|
+
output.should match /link has no href attribute/
|
40
33
|
end
|
41
34
|
|
42
35
|
it "should follow redirects" do
|
43
36
|
linkWithRedirectFilepath = "#{FIXTURES_DIR}/linkWithRedirect.html"
|
44
|
-
|
45
|
-
|
46
|
-
@linkCheck.issues[0].should eq(nil)
|
37
|
+
output = capture_stderr { HTML::Proofer.new(linkWithRedirectFilepath).run }
|
38
|
+
output.should == ""
|
47
39
|
end
|
48
40
|
|
49
41
|
it "should understand https" do
|
50
42
|
linkWithHttpsFilepath = "#{FIXTURES_DIR}/linkWithHttps.html"
|
51
|
-
|
52
|
-
|
53
|
-
@linkCheck.issues[0].should eq(nil)
|
43
|
+
output = capture_stderr { HTML::Proofer.new(linkWithHttpsFilepath).run }
|
44
|
+
output.should == ""
|
54
45
|
end
|
55
46
|
|
56
47
|
it "fails for broken hash links with status code numbers" do
|
57
48
|
brokenLinkWithNumberFilepath = "#{FIXTURES_DIR}/brokenLinkWithNumber.html"
|
58
|
-
|
59
|
-
|
60
|
-
@linkCheck.issues[0].should eq("\e[34mspec/html/proofer/fixtures/brokenLinkWithNumber.html\e[0m: linking to internal hash #25-method-not-allowed that does not exist")
|
49
|
+
output = capture_stderr { HTML::Proofer.new(brokenLinkWithNumberFilepath).run }
|
50
|
+
output.should match /linking to internal hash #25-method-not-allowed that does not exist/
|
61
51
|
end
|
62
52
|
|
63
53
|
it 'properly resolves implicit /index.html in link paths' do
|
64
54
|
linkToFolder = "#{FIXTURES_DIR}/linkToFolder.html"
|
65
|
-
|
66
|
-
|
67
|
-
@linkCheck.issues[0].should eq(nil)
|
55
|
+
output = capture_stderr { HTML::Proofer.new(linkToFolder).run }
|
56
|
+
output.should == ""
|
68
57
|
end
|
69
58
|
|
70
59
|
it 'properly checks links to root' do
|
71
60
|
rootLink = "#{FIXTURES_DIR}/rootLink.html"
|
72
|
-
|
73
|
-
|
74
|
-
@linkCheck.issues[0].should eq(nil)
|
61
|
+
output = capture_stderr { HTML::Proofer.new(rootLink).run }
|
62
|
+
output.should == ""
|
75
63
|
end
|
76
64
|
|
77
65
|
it 'properly checks relative links' do
|
78
66
|
relativeLinks = "#{FIXTURES_DIR}/relativeLinks.html"
|
79
|
-
|
80
|
-
|
81
|
-
@linkCheck.issues[0].should eq(nil)
|
67
|
+
output = capture_stderr { HTML::Proofer.new(relativeLinks).run }
|
68
|
+
output.should == ""
|
82
69
|
end
|
83
70
|
|
84
71
|
it 'ignores links marked as ignore data-proofer-ignore' do
|
85
72
|
ignorableLinks = "#{FIXTURES_DIR}/ignorableLinks.html"
|
86
|
-
|
87
|
-
|
88
|
-
@linkCheck.issues[0].should eq(nil)
|
73
|
+
output = capture_stderr { HTML::Proofer.new(ignorableLinks).run }
|
74
|
+
output.should == ""
|
89
75
|
end
|
90
76
|
|
91
77
|
it 'translates links via href_swap' do
|
92
78
|
translatedLink = "#{FIXTURES_DIR}/linkTranslatedViaHrefSwap.html"
|
93
|
-
|
94
|
-
|
95
|
-
@linkCheck.issues[0].should eq(nil)
|
79
|
+
output = capture_stderr { HTML::Proofer.new(translatedLink, {:href_swap => { /\A\/articles\/([\w-]+)/ => "\\1.html" }}).run }
|
80
|
+
output.should == ""
|
96
81
|
end
|
97
82
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -14,4 +14,19 @@ RSpec.configure do |config|
|
|
14
14
|
|
15
15
|
# Use the specified formatter
|
16
16
|
config.formatter = :documentation # :progress, :html, :textmate
|
17
|
-
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def capture_stderr(&block)
|
20
|
+
original_stderr = $stderr
|
21
|
+
original_stdout = $stdout
|
22
|
+
$stderr = fake_err = StringIO.new
|
23
|
+
$stdout = fake_out = StringIO.new
|
24
|
+
begin
|
25
|
+
yield
|
26
|
+
rescue RuntimeError
|
27
|
+
ensure
|
28
|
+
$stderr = original_stderr
|
29
|
+
# $stdout = original_stdout
|
30
|
+
end
|
31
|
+
fake_err.string
|
32
|
+
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: 0.
|
4
|
+
version: 0.4.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: 2013-12-
|
11
|
+
date: 2013-12-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mercenary
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0.6.
|
61
|
+
version: 0.6.7
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - ~>
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 0.6.
|
68
|
+
version: 0.6.7
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: html-pipeline
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -140,7 +140,9 @@ files:
|
|
140
140
|
- spec/html/proofer/fixtures/brokenLinkWithNumber.html
|
141
141
|
- spec/html/proofer/fixtures/existingImageExternal.html
|
142
142
|
- spec/html/proofer/fixtures/folder/anchorLink.html
|
143
|
+
- spec/html/proofer/fixtures/folder/assets/barrel.png
|
143
144
|
- spec/html/proofer/fixtures/folder/index.html
|
145
|
+
- spec/html/proofer/fixtures/folder/relativeImage.html
|
144
146
|
- spec/html/proofer/fixtures/gpl.png
|
145
147
|
- spec/html/proofer/fixtures/ignorableImages.html
|
146
148
|
- spec/html/proofer/fixtures/ignorableLinks.html
|
@@ -157,7 +159,12 @@ files:
|
|
157
159
|
- spec/html/proofer/fixtures/missingLinkHref.html
|
158
160
|
- spec/html/proofer/fixtures/notarealhash.html
|
159
161
|
- spec/html/proofer/fixtures/relativeLinks.html
|
162
|
+
- spec/html/proofer/fixtures/resources/books/assets/getting-good-with-git.jpg
|
163
|
+
- spec/html/proofer/fixtures/resources/books/assets/pro-git.jpg
|
164
|
+
- spec/html/proofer/fixtures/resources/books/assets/version-control-with-git.jpg
|
165
|
+
- spec/html/proofer/fixtures/resources/books/nestedRelativeImages.html
|
160
166
|
- spec/html/proofer/fixtures/rootLink.html
|
167
|
+
- spec/html/proofer/fixtures/rootRelativeImages.html
|
161
168
|
- spec/html/proofer/fixtures/terribleImageName.html
|
162
169
|
- spec/html/proofer/images_spec.rb
|
163
170
|
- spec/html/proofer/links_spec.rb
|
@@ -199,7 +206,9 @@ test_files:
|
|
199
206
|
- spec/html/proofer/fixtures/brokenLinkWithNumber.html
|
200
207
|
- spec/html/proofer/fixtures/existingImageExternal.html
|
201
208
|
- spec/html/proofer/fixtures/folder/anchorLink.html
|
209
|
+
- spec/html/proofer/fixtures/folder/assets/barrel.png
|
202
210
|
- spec/html/proofer/fixtures/folder/index.html
|
211
|
+
- spec/html/proofer/fixtures/folder/relativeImage.html
|
203
212
|
- spec/html/proofer/fixtures/gpl.png
|
204
213
|
- spec/html/proofer/fixtures/ignorableImages.html
|
205
214
|
- spec/html/proofer/fixtures/ignorableLinks.html
|
@@ -216,7 +225,12 @@ test_files:
|
|
216
225
|
- spec/html/proofer/fixtures/missingLinkHref.html
|
217
226
|
- spec/html/proofer/fixtures/notarealhash.html
|
218
227
|
- spec/html/proofer/fixtures/relativeLinks.html
|
228
|
+
- spec/html/proofer/fixtures/resources/books/assets/getting-good-with-git.jpg
|
229
|
+
- spec/html/proofer/fixtures/resources/books/assets/pro-git.jpg
|
230
|
+
- spec/html/proofer/fixtures/resources/books/assets/version-control-with-git.jpg
|
231
|
+
- spec/html/proofer/fixtures/resources/books/nestedRelativeImages.html
|
219
232
|
- spec/html/proofer/fixtures/rootLink.html
|
233
|
+
- spec/html/proofer/fixtures/rootRelativeImages.html
|
220
234
|
- spec/html/proofer/fixtures/terribleImageName.html
|
221
235
|
- spec/html/proofer/images_spec.rb
|
222
236
|
- spec/html/proofer/links_spec.rb
|