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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c5f9520152e65b775e134ac987d42fdeb69a4448
4
- data.tar.gz: 6fb435127a7de49da70d5b9284d95bbb736bc19b
3
+ metadata.gz: 96ef995058e63021380229872126e11c18216d4a
4
+ data.tar.gz: 97f17a39a973e7819f52cbb0611f9f64f0152f94
5
5
  SHA512:
6
- metadata.gz: d2e355f14b84c62685a44b01e93109f7d4c6ddad4884c952f4c734c8a473ee22f94a258b09601bac4a648d9d3fa61f0f949d800208296755e5d63be5a4ca6f67
7
- data.tar.gz: 9e768b2b3920f5bf61fe1bcd257e890315cbe110c08afec49ba0a8e637341eef5c88f546adeeefcfa079a779b06b09f087ec18b00ed1c21f3f06ec038dd5c4c6
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.2.3)
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.3)
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.1)
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.6)
60
- ethon (~> 0.6.1)
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'` to your `Gemfile` as described above, and add the following to your `Rakefile`, using `rake test` to execute:
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: `mailto`)
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
- To any `<a>` or `<img>` tag, you may add the `data-proofer-ignore` attribute to ignore the link.
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.3"
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
- @options = {:ext => ".html"}.merge(opts)
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
- failed_tests = []
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
- Dir.glob("#{@srcDir}/**/*#{@options[:ext]}") do |path|
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.hydra.run
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
- Nokogiri::HTML(File.read(path))
111
+ content = File.open(path, "rb") {|f| f.read }
112
+ Nokogiri::HTML(content)
47
113
  end
48
114
 
49
115
  def get_checks
@@ -10,7 +10,7 @@ class HTML::Proofer::Checks
10
10
 
11
11
  class Check
12
12
 
13
- attr_reader :issues, :hydra, :src, :path, :options, :additional_href_ignores
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
- @checked_urls = {}
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 validate_url(href, issue_text)
40
- return @checked_urls[href] if @checked_urls.has_key? href
41
- request = Typhoeus::Request.new(href, {:followlocation => true})
42
- request.on_complete do |response|
43
- if response.success?
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?(href)
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? File.expand_path path, @check.src #relative links, path is a file
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 |img|
27
+ @html.css('img').each do |i|
28
+ img = Image.new i, self
28
29
 
29
- img = Image.new img, self
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
- validate_url img.src, "external image #{img.src} does not exist"
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 |link|
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
- validate_url link.href, "externally linking to #{link.href}, which does not exist"
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
- #not yet checked
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)
@@ -1,5 +1,5 @@
1
1
  module HTML
2
2
  class Proofer
3
- VERSION = "0.3.0"
3
+ VERSION = "0.4.0"
4
4
  end
5
5
  end
@@ -0,0 +1,2 @@
1
+
2
+ <ing alt="sure thing" src="assets/barrel.png">Folder relative to self</a>
@@ -2,8 +2,9 @@
2
2
 
3
3
  <body>
4
4
 
5
- <p>Blah blah blah. <a href="http://www.capify.org/">This is a redirect.</a>. </p>
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>
@@ -2,3 +2,5 @@
2
2
  <a href="index.html">Relative to self</a>
3
3
  <a href="folder/">Folder relative to self</a>
4
4
  <a href="index.html#anchor">Anchor relative to self</a>
5
+
6
+ <img alt="sure thing" src="gpl.png"/>Relative to self
@@ -0,0 +1,5 @@
1
+ <img src="assets/pro-git.jpg" alt="Pro Git">
2
+
3
+ <img src="assets/getting-good-with-git.jpg" alt="Getting Good with Git">
4
+
5
+ <img src="assets/version-control-with-git.jpg" alt="Version Control with Git, 2nd Edition">
@@ -0,0 +1,2 @@
1
+
2
+ <img alt="sure thing" src="/gpl.png"/>Relative to root
@@ -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
- @imageCheck = Images.new("#{FIXTURES_DIR}", externalImageFilepath, HTML::Proofer.create_nokogiri(externalImageFilepath))
7
- @imageCheck.run
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
- @imageCheck = Images.new("#{FIXTURES_DIR}", missingAltFilepath, HTML::Proofer.create_nokogiri(missingAltFilepath))
14
- @imageCheck.run
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
- @imageCheck = Images.new("#{FIXTURES_DIR}", missingAltFilepath, HTML::Proofer.create_nokogiri(missingAltFilepath))
21
- @imageCheck.run
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
- @imageCheck = Images.new("#{FIXTURES_DIR}", externalImageFilepath, HTML::Proofer.create_nokogiri(externalImageFilepath))
28
- @imageCheck.run
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
- @imageCheck = Images.new("#{FIXTURES_DIR}", internalImageFilepath, HTML::Proofer.create_nokogiri(internalImageFilepath))
37
- @imageCheck.run
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
- @imageCheck = Images.new("#{FIXTURES_DIR}", imageSrcFilepath, HTML::Proofer.create_nokogiri(imageSrcFilepath))
44
- @imageCheck.run
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
- @imageCheck = Images.new("#{FIXTURES_DIR}", terribleImageName, HTML::Proofer.create_nokogiri(terribleImageName))
51
- @imageCheck.run
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
- @linkCheck = Links.new("#{FIXTURES_DIR}", ignorableImages, HTML::Proofer.create_nokogiri(ignorableImages))
58
- @linkCheck.run
59
- @linkCheck.issues[0].should eq(nil)
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
- @linkCheck = Links.new("#{FIXTURES_DIR}", brokenHashExternalFilepath, HTML::Proofer.create_nokogiri(brokenHashExternalFilepath))
8
- @linkCheck.run
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
- @linkCheck = Links.new("#{FIXTURES_DIR}", brokenHashInternalFilepath, HTML::Proofer.create_nokogiri(brokenHashInternalFilepath))
15
- @linkCheck.run
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
- @linkCheck = Links.new("#{FIXTURES_DIR}", brokenLinkExternalFilepath, HTML::Proofer.create_nokogiri(brokenLinkExternalFilepath))
22
- @linkCheck.run
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
- @linkCheck = Links.new("#{FIXTURES_DIR}", brokenLinkInternalFilepath, HTML::Proofer.create_nokogiri(brokenLinkInternalFilepath))
31
- @linkCheck.run
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
- @linkCheck = Links.new("#{FIXTURES_DIR}", missingLinkHrefFilepath, HTML::Proofer.create_nokogiri(missingLinkHrefFilepath))
38
- @linkCheck.run
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
- @linkCheck = Links.new("#{FIXTURES_DIR}", linkWithRedirectFilepath, HTML::Proofer.create_nokogiri(linkWithRedirectFilepath))
45
- @linkCheck.run
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
- @linkCheck = Links.new("#{FIXTURES_DIR}", linkWithHttpsFilepath, HTML::Proofer.create_nokogiri(linkWithHttpsFilepath))
52
- @linkCheck.run
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
- @linkCheck = Links.new("#{FIXTURES_DIR}", brokenLinkWithNumberFilepath, HTML::Proofer.create_nokogiri(brokenLinkWithNumberFilepath))
59
- @linkCheck.run
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
- @linkCheck = Links.new("#{FIXTURES_DIR}", linkToFolder, HTML::Proofer.create_nokogiri(linkToFolder))
66
- @linkCheck.run
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
- @linkCheck = Links.new("#{FIXTURES_DIR}", rootLink, HTML::Proofer.create_nokogiri(rootLink))
73
- @linkCheck.run
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
- @linkCheck = Links.new("#{FIXTURES_DIR}", relativeLinks, HTML::Proofer.create_nokogiri(relativeLinks))
80
- @linkCheck.run
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
- @linkCheck = Links.new("#{FIXTURES_DIR}", ignorableLinks, HTML::Proofer.create_nokogiri(ignorableLinks))
87
- @linkCheck.run
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
- @linkCheck = Links.new("#{FIXTURES_DIR}", translatedLink, HTML::Proofer.create_nokogiri(translatedLink), {:href_swap => { /\A\/articles\/([\w-]+)/ => "\\1.html" }})
94
- @linkCheck.run
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.3.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-05 00:00:00.000000000 Z
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.3
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.3
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