From 506e40ee2876c16a7653c9bbc7ca88fc6f8a8aab Mon Sep 17 00:00:00 2001 From: Ben Balter Date: Wed, 9 Oct 2013 16:01:37 -0400 Subject: [PATCH 01/12] proper relative URL support --- lib/html/proofer.rb | 2 +- lib/html/proofer/check.rb | 28 +++++++++++++++++++++++++++- lib/html/proofer/checks/images.rb | 4 ++-- lib/html/proofer/checks/links.rb | 10 +++------- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/lib/html/proofer.rb b/lib/html/proofer.rb index 2c101290..fcbd08ba 100644 --- a/lib/html/proofer.rb +++ b/lib/html/proofer.rb @@ -16,7 +16,7 @@ def run Find.find(@srcDir) do |path| if File.extname(path) == @options[:ext] html = HTML::Proofer.create_nokogiri(path) - check = klass.new(path, html, @options) + check = klass.new(@srcDir, path, html, @options) check.run check.hydra.run self.print_issues(klass, check.issues) diff --git a/lib/html/proofer/check.rb b/lib/html/proofer/check.rb index dbc47f68..e2b0fad8 100644 --- a/lib/html/proofer/check.rb +++ b/lib/html/proofer/check.rb @@ -12,7 +12,8 @@ class Check attr_reader :issues, :hydra - def initialize(path, html, opts={}) + def initialize(src, path, html, opts={}) + @src = src @path = path @html = html @options = opts @@ -91,5 +92,30 @@ def self.subclasses classes end + + def resolve_path(path) + + if path =~ /^\// #path relative to root + base = @src + else #relative links + base = @path + end + + if path =~ /^#/ #anchor link, no trailing slash + path = "#{base}#{path}" + else # relative path, resolve trailing slashes automatically + path = File.join base, path + end + + # implicit /index.html support + begin + parts = URI.parse path + parts.path = File.join parts.path, "index.html" if File.directory? parts.path + path = parts.to_s + rescue + self.add_issue("#{@path}".blue + ": #{path} is not a valid URI") + end + path + end end end diff --git a/lib/html/proofer/checks/images.rb b/lib/html/proofer/checks/images.rb index be4ac68c..e0dc40d4 100644 --- a/lib/html/proofer/checks/images.rb +++ b/lib/html/proofer/checks/images.rb @@ -9,7 +9,7 @@ def run # check image sources if src && src.length > 0 if !external_href?(src) - self.add_issue("#{@path}".blue + ": internal image #{src} does not exist") unless src[0] != "/" and File.exist?(File.join(File.dirname(@path), src)) + self.add_issue("#{@path}".blue + ": internal image #{src} does not exist") unless File.exist?( resolve_path(src)) else validate_url(src, "#{@path}".blue + ": external image #{src} does not exist") end @@ -19,7 +19,7 @@ def run # check alt tag self.add_issue("#{@path}".blue + ": image #{src} does not have an alt attribute") unless img['alt'] and !img['alt'].empty? - + screenShotRegExp = /Screen(?: |%20)Shot(?: |%20)\d+-\d+-\d+(?: |%20)at(?: |%20)\d+.\d+.\d+/ if src =~ screenShotRegExp diff --git a/lib/html/proofer/checks/links.rb b/lib/html/proofer/checks/links.rb index 31da2fd1..a2c315a3 100644 --- a/lib/html/proofer/checks/links.rb +++ b/lib/html/proofer/checks/links.rb @@ -19,6 +19,7 @@ def run href_split = href.split('#') end if !external_href?(href) + # an internal link, with a hash if href_split && !href_split.empty? href_file = href_split[0] @@ -26,7 +27,7 @@ def run # it's not an internal hash; it's pointing to some other file if href_file.length > 0 - href_location = resolve_path File.join(File.dirname(@path), href_file) + href_location = resolve_path href if !File.exist?(href_location) self.add_issue("#{@path}".blue + ": internal link #{href_location} does not exist") else @@ -44,7 +45,7 @@ def run end # internal link, no hash else - href_location = resolve_path File.join(File.dirname(@path), href) + href_location = resolve_path href self.add_issue("#{@path}".blue + ": internally linking to #{href_location}, which does not exist") unless File.exist?(href_location) end else @@ -60,9 +61,4 @@ def hash_check(html, href_hash) html.xpath("//*[@id='#{href_hash}']", "//*[@name='#{href_hash}']").length > 0 end - #support for implicit /index.html in URLs - def resolve_path(path) - path << "index.html" if File.directory? path - path - end end From 892a600f014e194b85bc051b7ece559ec4488494 Mon Sep 17 00:00:00 2001 From: Ben Balter Date: Thu, 10 Oct 2013 14:33:15 -0400 Subject: [PATCH 02/12] check links relative to root --- spec/html/proofer/fixtures/rootLink.html | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/html/proofer/fixtures/rootLink.html b/spec/html/proofer/fixtures/rootLink.html index d3c31558..f22c5732 100644 --- a/spec/html/proofer/fixtures/rootLink.html +++ b/spec/html/proofer/fixtures/rootLink.html @@ -3,6 +3,7 @@

Blah blah blah. I am root.

+

Blah blah blah. I am relative to root.

From acc35cbc92447e4bd19f53d91bc77e86c8152154 Mon Sep 17 00:00:00 2001 From: Ben Balter Date: Thu, 10 Oct 2013 15:40:29 -0400 Subject: [PATCH 03/12] almost passing tests --- lib/html/proofer/check.rb | 13 ++++++++---- .../proofer/fixtures/folder/anchorLink.html | 0 spec/html/proofer/images_spec.rb | 16 +++++++-------- spec/html/proofer/links_spec.rb | 20 +++++++++---------- 4 files changed, 27 insertions(+), 22 deletions(-) create mode 100644 spec/html/proofer/fixtures/folder/anchorLink.html diff --git a/lib/html/proofer/check.rb b/lib/html/proofer/check.rb index e2b0fad8..bd00ee2d 100644 --- a/lib/html/proofer/check.rb +++ b/lib/html/proofer/check.rb @@ -104,18 +104,23 @@ def resolve_path(path) if path =~ /^#/ #anchor link, no trailing slash path = "#{base}#{path}" else # relative path, resolve trailing slashes automatically - path = File.join base, path + path = File.join File.dirname(base), path end - # implicit /index.html support begin - parts = URI.parse path + parts = URI.parse URI.encode path + + # implicit /index.html support, with support for tailing slashes parts.path = File.join parts.path, "index.html" if File.directory? parts.path + + # strip anchor which isn't necessary to resolve path + parts.fragment = nil + path = parts.to_s rescue self.add_issue("#{@path}".blue + ": #{path} is not a valid URI") end - path + URI.decode path end end end diff --git a/spec/html/proofer/fixtures/folder/anchorLink.html b/spec/html/proofer/fixtures/folder/anchorLink.html new file mode 100644 index 00000000..e69de29b diff --git a/spec/html/proofer/images_spec.rb b/spec/html/proofer/images_spec.rb index d3faadfa..4b96a55c 100644 --- a/spec/html/proofer/images_spec.rb +++ b/spec/html/proofer/images_spec.rb @@ -3,35 +3,35 @@ describe "Image tests" do it "passes for existing external images" do externalImageFilepath = "#{FIXTURES_DIR}/existingImageExternal.html" - @imageCheck = Images.new(externalImageFilepath, HTML::Proofer.create_nokogiri(externalImageFilepath)) + @imageCheck = Images.new("/", externalImageFilepath, HTML::Proofer.create_nokogiri(externalImageFilepath)) @imageCheck.run @imageCheck.issues[0].should eq(nil) end it "fails for image without alt attribute" do missingAltFilepath = "#{FIXTURES_DIR}/missingImageAlt.html" - @imageCheck = Images.new(missingAltFilepath, HTML::Proofer.create_nokogiri(missingAltFilepath)) + @imageCheck = Images.new("/", missingAltFilepath, HTML::Proofer.create_nokogiri(missingAltFilepath)) @imageCheck.run @imageCheck.issues[0].should eq("spec/html/proofer/fixtures/missingImageAlt.html".blue + ": image ./gpl.png does not have an alt attribute") end it "fails for image with an empty alt attribute" do missingAltFilepath = "#{FIXTURES_DIR}/missingImageAltText.html" - @imageCheck = Images.new(missingAltFilepath, HTML::Proofer.create_nokogiri(missingAltFilepath)) + @imageCheck = Images.new("/", missingAltFilepath, HTML::Proofer.create_nokogiri(missingAltFilepath)) @imageCheck.run @imageCheck.issues[0].should eq("spec/html/proofer/fixtures/missingImageAltText.html".blue + ": image ./gpl.png does not have an alt attribute") end it "fails for image without a dir prefix" do missingImageDirPrefixFilepath = "#{FIXTURES_DIR}/missingImageDirPrefix.html" - @imageCheck = Images.new(missingImageDirPrefixFilepath, HTML::Proofer.create_nokogiri(missingImageDirPrefixFilepath)) + @imageCheck = Images.new("/", missingImageDirPrefixFilepath, HTML::Proofer.create_nokogiri(missingImageDirPrefixFilepath)) @imageCheck.run @imageCheck.issues[0].should eq("spec/html/proofer/fixtures/missingImageDirPrefix.html".blue + ": internal image /gpl.png does not exist") end it "fails for missing external images" do externalImageFilepath = "#{FIXTURES_DIR}/missingImageExternal.html" - @imageCheck = Images.new(externalImageFilepath, HTML::Proofer.create_nokogiri(externalImageFilepath)) + @imageCheck = Images.new("/", externalImageFilepath, HTML::Proofer.create_nokogiri(externalImageFilepath)) @imageCheck.run @imageCheck.hydra.run @imageCheck.issues[0].sub!(/ #/, "") @@ -40,21 +40,21 @@ it "fails for missing internal images" do internalImageFilepath = "#{FIXTURES_DIR}/missingImageInternal.html" - @imageCheck = Images.new(internalImageFilepath, HTML::Proofer.create_nokogiri(internalImageFilepath)) + @imageCheck = Images.new("/", internalImageFilepath, HTML::Proofer.create_nokogiri(internalImageFilepath)) @imageCheck.run @imageCheck.issues[0].should eq("spec/html/proofer/fixtures/missingImageInternal.html".blue + ": internal image ./doesnotexist.png does not exist") end it "fails for image with no src" do imageSrcFilepath = "#{FIXTURES_DIR}/missingImageSrc.html" - @imageCheck = Images.new(imageSrcFilepath, HTML::Proofer.create_nokogiri(imageSrcFilepath)) + @imageCheck = Images.new("/", imageSrcFilepath, HTML::Proofer.create_nokogiri(imageSrcFilepath)) @imageCheck.run @imageCheck.issues[0].should eq("spec/html/proofer/fixtures/missingImageSrc.html".blue + ": image has no src attribute") end it "fails for image with default mac filename" do terribleImageName = "#{FIXTURES_DIR}/terribleImageName.html" - @imageCheck = Images.new(terribleImageName, HTML::Proofer.create_nokogiri(terribleImageName)) + @imageCheck = Images.new("/", terribleImageName, HTML::Proofer.create_nokogiri(terribleImageName)) @imageCheck.run @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)") end diff --git a/spec/html/proofer/links_spec.rb b/spec/html/proofer/links_spec.rb index 5cf5195a..6e6d7ee6 100644 --- a/spec/html/proofer/links_spec.rb +++ b/spec/html/proofer/links_spec.rb @@ -4,21 +4,21 @@ it "fails for broken external hash (even if the file exists)" do brokenHashExternalFilepath = "#{FIXTURES_DIR}/brokenHashExternal.html" - @linkCheck = Links.new(brokenHashExternalFilepath, HTML::Proofer.create_nokogiri(brokenHashExternalFilepath)) + @linkCheck = Links.new("/", brokenHashExternalFilepath, HTML::Proofer.create_nokogiri(brokenHashExternalFilepath)) @linkCheck.run @linkCheck.issues[1].should eq("spec/html/proofer/fixtures/brokenHashExternal.html".blue + ": linking to ./missingImageAlt.html#asdfasfdkafl, but asdfasfdkafl does not exist") end it "fails for broken internal hash" do brokenHashInternalFilepath = "#{FIXTURES_DIR}/brokenHashInternal.html" - @linkCheck = Links.new(brokenHashInternalFilepath, HTML::Proofer.create_nokogiri(brokenHashInternalFilepath)) + @linkCheck = Links.new("/", brokenHashInternalFilepath, HTML::Proofer.create_nokogiri(brokenHashInternalFilepath)) @linkCheck.run @linkCheck.issues[0].should eq("spec/html/proofer/fixtures/brokenHashInternal.html".blue + ": linking to an internal hash called noHash that does not exist") end it "fails for broken external links" do brokenLinkExternalFilepath = "#{FIXTURES_DIR}/brokenLinkExternal.html" - @linkCheck = Links.new(brokenLinkExternalFilepath, HTML::Proofer.create_nokogiri(brokenLinkExternalFilepath)) + @linkCheck = Links.new("/", brokenLinkExternalFilepath, HTML::Proofer.create_nokogiri(brokenLinkExternalFilepath)) @linkCheck.run @linkCheck.hydra.run @linkCheck.issues[0].sub!(/ #/, "") @@ -27,49 +27,49 @@ it "fails for broken internal links" do brokenLinkInternalFilepath = "#{FIXTURES_DIR}/brokenLinkInternal.html" - @linkCheck = Links.new(brokenLinkInternalFilepath, HTML::Proofer.create_nokogiri(brokenLinkInternalFilepath)) + @linkCheck = Links.new("/", brokenLinkInternalFilepath, HTML::Proofer.create_nokogiri(brokenLinkInternalFilepath)) @linkCheck.run @linkCheck.issues[0].should eq("spec/html/proofer/fixtures/brokenLinkInternal.html".blue + ": internally linking to spec/html/proofer/fixtures/./notreal.html, which does not exist") end it "fails for link with no href" do missingLinkHrefFilepath = "#{FIXTURES_DIR}/missingLinkHref.html" - @linkCheck = Links.new(missingLinkHrefFilepath, HTML::Proofer.create_nokogiri(missingLinkHrefFilepath)) + @linkCheck = Links.new("/", missingLinkHrefFilepath, HTML::Proofer.create_nokogiri(missingLinkHrefFilepath)) @linkCheck.run @linkCheck.issues[0].should eq("spec/html/proofer/fixtures/missingLinkHref.html".blue + ": link has no href attribute") end it "should follow redirects" do linkWithRedirectFilepath = "#{FIXTURES_DIR}/linkWithRedirect.html" - @linkCheck = Links.new(linkWithRedirectFilepath, HTML::Proofer.create_nokogiri(linkWithRedirectFilepath)) + @linkCheck = Links.new("/", linkWithRedirectFilepath, HTML::Proofer.create_nokogiri(linkWithRedirectFilepath)) @linkCheck.run @linkCheck.issues[0].should eq(nil) end it "should understand https" do linkWithHttpsFilepath = "#{FIXTURES_DIR}/linkWithHttps.html" - @linkCheck = Links.new(linkWithHttpsFilepath, HTML::Proofer.create_nokogiri(linkWithHttpsFilepath)) + @linkCheck = Links.new("/", linkWithHttpsFilepath, HTML::Proofer.create_nokogiri(linkWithHttpsFilepath)) @linkCheck.run @linkCheck.issues[0].should eq(nil) end it "fails for broken hash links with status code numbers" do brokenLinkWithNumberFilepath = "#{FIXTURES_DIR}/brokenLinkWithNumber.html" - @linkCheck = Links.new(brokenLinkWithNumberFilepath, HTML::Proofer.create_nokogiri(brokenLinkWithNumberFilepath)) + @linkCheck = Links.new("/", brokenLinkWithNumberFilepath, HTML::Proofer.create_nokogiri(brokenLinkWithNumberFilepath)) @linkCheck.run @linkCheck.issues[0].should eq(nil) end it 'properly resolves implicit /index.html in link paths' do linkToFolder = "#{FIXTURES_DIR}/linkToFolder.html" - @linkCheck = Links.new(linkToFolder, HTML::Proofer.create_nokogiri(linkToFolder)) + @linkCheck = Links.new("/", linkToFolder, HTML::Proofer.create_nokogiri(linkToFolder)) @linkCheck.run @linkCheck.issues[0].should eq(nil) end it 'properly checks links to root' do rootLink = "#{FIXTURES_DIR}/rootLink.html" - @linkCheck = Links.new(rootLink, HTML::Proofer.create_nokogiri(rootLink)) + @linkCheck = Links.new("/", rootLink, HTML::Proofer.create_nokogiri(rootLink)) @linkCheck.run @linkCheck.issues[0].should eq(nil) end From fa2fb031a2dc63338a4c363ba3f5b093034613a2 Mon Sep 17 00:00:00 2001 From: Ben Balter Date: Fri, 11 Oct 2013 14:37:47 -0400 Subject: [PATCH 04/12] passing tests --- lib/html/proofer/check.rb | 28 +++++++++--------- lib/html/proofer/checks/images.rb | 2 +- lib/html/proofer/checks/links.rb | 10 +++---- spec/html/proofer/fixtures/index.html | 2 +- .../fixtures/missingImageDirPrefix.html | 9 ------ spec/html/proofer/fixtures/relativeLinks.html | 4 +++ spec/html/proofer/images_spec.rb | 21 +++++--------- spec/html/proofer/links_spec.rb | 29 ++++++++++++------- 8 files changed, 49 insertions(+), 56 deletions(-) delete mode 100644 spec/html/proofer/fixtures/missingImageDirPrefix.html create mode 100644 spec/html/proofer/fixtures/relativeLinks.html diff --git a/lib/html/proofer/check.rb b/lib/html/proofer/check.rb index bd00ee2d..c92ffb15 100644 --- a/lib/html/proofer/check.rb +++ b/lib/html/proofer/check.rb @@ -95,32 +95,32 @@ def self.subclasses def resolve_path(path) + #Strip anchor, not needed to resolve file + path = path.split('#').first + if path =~ /^\// #path relative to root base = @src - else #relative links + elsif File.exist? File.join Dir.pwd, @path #relative links, path is a file + base = File.dirname(@path) + else #relative link, path is a directory base = @path end if path =~ /^#/ #anchor link, no trailing slash path = "#{base}#{path}" else # relative path, resolve trailing slashes automatically - path = File.join File.dirname(base), path + path = File.join base, path end - begin - parts = URI.parse URI.encode path - - # implicit /index.html support, with support for tailing slashes - parts.path = File.join parts.path, "index.html" if File.directory? parts.path + # implicit /index.html support, with support for tailing slashes + path = File.join path, "index.html" if File.directory? File.join Dir.pwd, path - # strip anchor which isn't necessary to resolve path - parts.fragment = nil + path + end - path = parts.to_s - rescue - self.add_issue("#{@path}".blue + ": #{path} is not a valid URI") - end - URI.decode path + # checks if a file exists relative to the current pwd + def file?(path) + File.exist? File.join Dir.pwd, resolve_path(path) end end end diff --git a/lib/html/proofer/checks/images.rb b/lib/html/proofer/checks/images.rb index e0dc40d4..0e18ac4a 100644 --- a/lib/html/proofer/checks/images.rb +++ b/lib/html/proofer/checks/images.rb @@ -9,7 +9,7 @@ def run # check image sources if src && src.length > 0 if !external_href?(src) - self.add_issue("#{@path}".blue + ": internal image #{src} does not exist") unless File.exist?( resolve_path(src)) + self.add_issue("#{@path}".blue + ": internal image #{src} does not exist") unless file? src else validate_url(src, "#{@path}".blue + ": external image #{src} does not exist") end diff --git a/lib/html/proofer/checks/links.rb b/lib/html/proofer/checks/links.rb index a2c315a3..b0b6772f 100644 --- a/lib/html/proofer/checks/links.rb +++ b/lib/html/proofer/checks/links.rb @@ -27,11 +27,10 @@ def run # it's not an internal hash; it's pointing to some other file if href_file.length > 0 - href_location = resolve_path href - if !File.exist?(href_location) - self.add_issue("#{@path}".blue + ": internal link #{href_location} does not exist") + if !file?(href_file) + self.add_issue("#{@path}".blue + ": internal link #{href_file} does not exist") else - href_html = HTML::Proofer.create_nokogiri(href_location) + href_html = HTML::Proofer.create_nokogiri(resolve_path(href_file)) found_hash_match = false unless hash_check(href_html, href_hash) self.add_issue("#{@path}".blue + ": linking to #{href}, but #{href_hash} does not exist") @@ -45,8 +44,7 @@ def run end # internal link, no hash else - href_location = resolve_path href - self.add_issue("#{@path}".blue + ": internally linking to #{href_location}, which does not exist") unless File.exist?(href_location) + self.add_issue("#{@path}".blue + ": internally linking to #{href}, which does not exist") unless file?(href) end else validate_url(href, "#{@path}".blue + ": externally linking to #{href}, which does not exist") diff --git a/spec/html/proofer/fixtures/index.html b/spec/html/proofer/fixtures/index.html index 0ce99707..8ec61e2d 100644 --- a/spec/html/proofer/fixtures/index.html +++ b/spec/html/proofer/fixtures/index.html @@ -1 +1 @@ -root. +

root. diff --git a/spec/html/proofer/fixtures/missingImageDirPrefix.html b/spec/html/proofer/fixtures/missingImageDirPrefix.html deleted file mode 100644 index 45319f6e..00000000 --- a/spec/html/proofer/fixtures/missingImageDirPrefix.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - -

Blah blah blah. A broken image, due to dir prefix

- - - - \ No newline at end of file diff --git a/spec/html/proofer/fixtures/relativeLinks.html b/spec/html/proofer/fixtures/relativeLinks.html new file mode 100644 index 00000000..08d061eb --- /dev/null +++ b/spec/html/proofer/fixtures/relativeLinks.html @@ -0,0 +1,4 @@ +Relative to root +Relative to self +Folder relative to self +Anchor relative to self diff --git a/spec/html/proofer/images_spec.rb b/spec/html/proofer/images_spec.rb index 4b96a55c..0bf12213 100644 --- a/spec/html/proofer/images_spec.rb +++ b/spec/html/proofer/images_spec.rb @@ -3,35 +3,28 @@ describe "Image tests" do it "passes for existing external images" do externalImageFilepath = "#{FIXTURES_DIR}/existingImageExternal.html" - @imageCheck = Images.new("/", externalImageFilepath, HTML::Proofer.create_nokogiri(externalImageFilepath)) + @imageCheck = Images.new("#{FIXTURES_DIR}", externalImageFilepath, HTML::Proofer.create_nokogiri(externalImageFilepath)) @imageCheck.run @imageCheck.issues[0].should eq(nil) end it "fails for image without alt attribute" do missingAltFilepath = "#{FIXTURES_DIR}/missingImageAlt.html" - @imageCheck = Images.new("/", missingAltFilepath, HTML::Proofer.create_nokogiri(missingAltFilepath)) + @imageCheck = Images.new("#{FIXTURES_DIR}", missingAltFilepath, HTML::Proofer.create_nokogiri(missingAltFilepath)) @imageCheck.run @imageCheck.issues[0].should eq("spec/html/proofer/fixtures/missingImageAlt.html".blue + ": image ./gpl.png does not have an alt attribute") end it "fails for image with an empty alt attribute" do missingAltFilepath = "#{FIXTURES_DIR}/missingImageAltText.html" - @imageCheck = Images.new("/", missingAltFilepath, HTML::Proofer.create_nokogiri(missingAltFilepath)) + @imageCheck = Images.new("#{FIXTURES_DIR}", missingAltFilepath, HTML::Proofer.create_nokogiri(missingAltFilepath)) @imageCheck.run @imageCheck.issues[0].should eq("spec/html/proofer/fixtures/missingImageAltText.html".blue + ": image ./gpl.png does not have an alt attribute") end - it "fails for image without a dir prefix" do - missingImageDirPrefixFilepath = "#{FIXTURES_DIR}/missingImageDirPrefix.html" - @imageCheck = Images.new("/", missingImageDirPrefixFilepath, HTML::Proofer.create_nokogiri(missingImageDirPrefixFilepath)) - @imageCheck.run - @imageCheck.issues[0].should eq("spec/html/proofer/fixtures/missingImageDirPrefix.html".blue + ": internal image /gpl.png does not exist") - end - it "fails for missing external images" do externalImageFilepath = "#{FIXTURES_DIR}/missingImageExternal.html" - @imageCheck = Images.new("/", externalImageFilepath, HTML::Proofer.create_nokogiri(externalImageFilepath)) + @imageCheck = Images.new("#{FIXTURES_DIR}", externalImageFilepath, HTML::Proofer.create_nokogiri(externalImageFilepath)) @imageCheck.run @imageCheck.hydra.run @imageCheck.issues[0].sub!(/ #/, "") @@ -40,21 +33,21 @@ it "fails for missing internal images" do internalImageFilepath = "#{FIXTURES_DIR}/missingImageInternal.html" - @imageCheck = Images.new("/", internalImageFilepath, HTML::Proofer.create_nokogiri(internalImageFilepath)) + @imageCheck = Images.new("#{FIXTURES_DIR}", internalImageFilepath, HTML::Proofer.create_nokogiri(internalImageFilepath)) @imageCheck.run @imageCheck.issues[0].should eq("spec/html/proofer/fixtures/missingImageInternal.html".blue + ": internal image ./doesnotexist.png does not exist") end it "fails for image with no src" do imageSrcFilepath = "#{FIXTURES_DIR}/missingImageSrc.html" - @imageCheck = Images.new("/", imageSrcFilepath, HTML::Proofer.create_nokogiri(imageSrcFilepath)) + @imageCheck = Images.new("#{FIXTURES_DIR}", imageSrcFilepath, HTML::Proofer.create_nokogiri(imageSrcFilepath)) @imageCheck.run @imageCheck.issues[0].should eq("spec/html/proofer/fixtures/missingImageSrc.html".blue + ": image has no src attribute") end it "fails for image with default mac filename" do terribleImageName = "#{FIXTURES_DIR}/terribleImageName.html" - @imageCheck = Images.new("/", terribleImageName, HTML::Proofer.create_nokogiri(terribleImageName)) + @imageCheck = Images.new("#{FIXTURES_DIR}", terribleImageName, HTML::Proofer.create_nokogiri(terribleImageName)) @imageCheck.run @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)") end diff --git a/spec/html/proofer/links_spec.rb b/spec/html/proofer/links_spec.rb index 6e6d7ee6..7331521f 100644 --- a/spec/html/proofer/links_spec.rb +++ b/spec/html/proofer/links_spec.rb @@ -4,21 +4,21 @@ it "fails for broken external hash (even if the file exists)" do brokenHashExternalFilepath = "#{FIXTURES_DIR}/brokenHashExternal.html" - @linkCheck = Links.new("/", brokenHashExternalFilepath, HTML::Proofer.create_nokogiri(brokenHashExternalFilepath)) + @linkCheck = Links.new("#{FIXTURES_DIR}", brokenHashExternalFilepath, HTML::Proofer.create_nokogiri(brokenHashExternalFilepath)) @linkCheck.run @linkCheck.issues[1].should eq("spec/html/proofer/fixtures/brokenHashExternal.html".blue + ": linking to ./missingImageAlt.html#asdfasfdkafl, but asdfasfdkafl does not exist") end it "fails for broken internal hash" do brokenHashInternalFilepath = "#{FIXTURES_DIR}/brokenHashInternal.html" - @linkCheck = Links.new("/", brokenHashInternalFilepath, HTML::Proofer.create_nokogiri(brokenHashInternalFilepath)) + @linkCheck = Links.new("#{FIXTURES_DIR}", brokenHashInternalFilepath, HTML::Proofer.create_nokogiri(brokenHashInternalFilepath)) @linkCheck.run @linkCheck.issues[0].should eq("spec/html/proofer/fixtures/brokenHashInternal.html".blue + ": linking to an internal hash called noHash that does not exist") end it "fails for broken external links" do brokenLinkExternalFilepath = "#{FIXTURES_DIR}/brokenLinkExternal.html" - @linkCheck = Links.new("/", brokenLinkExternalFilepath, HTML::Proofer.create_nokogiri(brokenLinkExternalFilepath)) + @linkCheck = Links.new("#{FIXTURES_DIR}", brokenLinkExternalFilepath, HTML::Proofer.create_nokogiri(brokenLinkExternalFilepath)) @linkCheck.run @linkCheck.hydra.run @linkCheck.issues[0].sub!(/ #/, "") @@ -27,49 +27,56 @@ it "fails for broken internal links" do brokenLinkInternalFilepath = "#{FIXTURES_DIR}/brokenLinkInternal.html" - @linkCheck = Links.new("/", brokenLinkInternalFilepath, HTML::Proofer.create_nokogiri(brokenLinkInternalFilepath)) + @linkCheck = Links.new("#{FIXTURES_DIR}", brokenLinkInternalFilepath, HTML::Proofer.create_nokogiri(brokenLinkInternalFilepath)) @linkCheck.run - @linkCheck.issues[0].should eq("spec/html/proofer/fixtures/brokenLinkInternal.html".blue + ": internally linking to spec/html/proofer/fixtures/./notreal.html, which does not exist") + @linkCheck.issues[0].should eq("spec/html/proofer/fixtures/brokenLinkInternal.html".blue + ": internally linking to ./notreal.html, which does not exist") end it "fails for link with no href" do missingLinkHrefFilepath = "#{FIXTURES_DIR}/missingLinkHref.html" - @linkCheck = Links.new("/", missingLinkHrefFilepath, HTML::Proofer.create_nokogiri(missingLinkHrefFilepath)) + @linkCheck = Links.new("#{FIXTURES_DIR}", missingLinkHrefFilepath, HTML::Proofer.create_nokogiri(missingLinkHrefFilepath)) @linkCheck.run @linkCheck.issues[0].should eq("spec/html/proofer/fixtures/missingLinkHref.html".blue + ": link has no href attribute") end it "should follow redirects" do linkWithRedirectFilepath = "#{FIXTURES_DIR}/linkWithRedirect.html" - @linkCheck = Links.new("/", linkWithRedirectFilepath, HTML::Proofer.create_nokogiri(linkWithRedirectFilepath)) + @linkCheck = Links.new("#{FIXTURES_DIR}", linkWithRedirectFilepath, HTML::Proofer.create_nokogiri(linkWithRedirectFilepath)) @linkCheck.run @linkCheck.issues[0].should eq(nil) end it "should understand https" do linkWithHttpsFilepath = "#{FIXTURES_DIR}/linkWithHttps.html" - @linkCheck = Links.new("/", linkWithHttpsFilepath, HTML::Proofer.create_nokogiri(linkWithHttpsFilepath)) + @linkCheck = Links.new("#{FIXTURES_DIR}", linkWithHttpsFilepath, HTML::Proofer.create_nokogiri(linkWithHttpsFilepath)) @linkCheck.run @linkCheck.issues[0].should eq(nil) end it "fails for broken hash links with status code numbers" do brokenLinkWithNumberFilepath = "#{FIXTURES_DIR}/brokenLinkWithNumber.html" - @linkCheck = Links.new("/", brokenLinkWithNumberFilepath, HTML::Proofer.create_nokogiri(brokenLinkWithNumberFilepath)) + @linkCheck = Links.new("#{FIXTURES_DIR}", brokenLinkWithNumberFilepath, HTML::Proofer.create_nokogiri(brokenLinkWithNumberFilepath)) @linkCheck.run @linkCheck.issues[0].should eq(nil) end it 'properly resolves implicit /index.html in link paths' do linkToFolder = "#{FIXTURES_DIR}/linkToFolder.html" - @linkCheck = Links.new("/", linkToFolder, HTML::Proofer.create_nokogiri(linkToFolder)) + @linkCheck = Links.new("#{FIXTURES_DIR}", linkToFolder, HTML::Proofer.create_nokogiri(linkToFolder)) @linkCheck.run @linkCheck.issues[0].should eq(nil) end it 'properly checks links to root' do rootLink = "#{FIXTURES_DIR}/rootLink.html" - @linkCheck = Links.new("/", rootLink, HTML::Proofer.create_nokogiri(rootLink)) + @linkCheck = Links.new("#{FIXTURES_DIR}", rootLink, HTML::Proofer.create_nokogiri(rootLink)) + @linkCheck.run + @linkCheck.issues[0].should eq(nil) + end + + it 'properly checks relative links' do + relativeLinks = "#{FIXTURES_DIR}/relativeLinks.html" + @linkCheck = Links.new("#{FIXTURES_DIR}", relativeLinks, HTML::Proofer.create_nokogiri(relativeLinks)) @linkCheck.run @linkCheck.issues[0].should eq(nil) end From 653f49cdadf05143a1c87bf63a00cac3747a0bac Mon Sep 17 00:00:00 2001 From: Ben Balter Date: Fri, 11 Oct 2013 16:18:24 -0400 Subject: [PATCH 05/12] refactor image test --- lib/html/proofer/check.rb | 3 +- lib/html/proofer/checks/images.rb | 53 ++++++++++++++++++++++--------- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/lib/html/proofer/check.rb b/lib/html/proofer/check.rb index c92ffb15..7d25604b 100644 --- a/lib/html/proofer/check.rb +++ b/lib/html/proofer/check.rb @@ -28,7 +28,7 @@ def run end def add_issue(desc) - @issues << desc + @issues << "#{@path.blue}: #{desc}" end def output_filenames @@ -122,5 +122,6 @@ def resolve_path(path) def file?(path) File.exist? File.join Dir.pwd, resolve_path(path) end + end end diff --git a/lib/html/proofer/checks/images.rb b/lib/html/proofer/checks/images.rb index 0e18ac4a..fccf3f94 100644 --- a/lib/html/proofer/checks/images.rb +++ b/lib/html/proofer/checks/images.rb @@ -1,30 +1,53 @@ # encoding: utf-8 +class Image + + SCREEN_SHOT_REGEX = /Screen(?: |%20)Shot(?: |%20)\d+-\d+-\d+(?: |%20)at(?: |%20)\d+.\d+.\d+/ + + def initialize(img) + @img = img + end + + def valid_alt_tag? + @img['alt'] and !@img['alt'].empty? + end + + def terrible_filename? + src =~ SCREEN_SHOT_REGEX + end + + def src + @img['src'] if @img['src'] && @img['src'].length > 0 + end + + def missing_src? + !src + end + +end + class Images < ::HTML::Proofer::Checks::Check def run @html.css('img').each do |img| - src = img['src'] - - # check image sources - if src && src.length > 0 - if !external_href?(src) - self.add_issue("#{@path}".blue + ": internal image #{src} does not exist") unless file? src - else - validate_url(src, "#{@path}".blue + ": external image #{src} does not exist") - end + + img = Image.new img + + # does the image exist? + if img.missing_src? + self.add_issue "image has no src attribute" + elsif external_href? img.src + validate_url img.src, "external image #{img.src} does not exist" else - self.add_issue("#{@path}".blue + ": image has no src attribute") + self.add_issue("internal image #{img.src} does not exist") unless file? img.src end # check alt tag - self.add_issue("#{@path}".blue + ": image #{src} does not have an alt attribute") unless img['alt'] and !img['alt'].empty? + self.add_issue "image #{img.src} does not have an alt attribute" unless img.valid_alt_tag? - screenShotRegExp = /Screen(?: |%20)Shot(?: |%20)\d+-\d+-\d+(?: |%20)at(?: |%20)\d+.\d+.\d+/ + # screenshot filenames + self.add_issue "image has a terrible filename (#{img.src})" if img.terrible_filename? - if src =~ screenShotRegExp - self.add_issue("#{@path}".blue + ": image has a terrible filename (#{src})") - end end end end From 83be48a876482ee55672d8cbeb657d625136e27c Mon Sep 17 00:00:00 2001 From: Ben Balter Date: Fri, 11 Oct 2013 16:25:08 -0400 Subject: [PATCH 06/12] image check refinements --- lib/html/proofer/checks/images.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/html/proofer/checks/images.rb b/lib/html/proofer/checks/images.rb index fccf3f94..658c1790 100644 --- a/lib/html/proofer/checks/images.rb +++ b/lib/html/proofer/checks/images.rb @@ -5,19 +5,20 @@ class Image SCREEN_SHOT_REGEX = /Screen(?: |%20)Shot(?: |%20)\d+-\d+-\d+(?: |%20)at(?: |%20)\d+.\d+.\d+/ def initialize(img) - @img = img + @src = img['src'] + @alt = img['alt'] end def valid_alt_tag? - @img['alt'] and !@img['alt'].empty? + @alt and !@alt.empty? end def terrible_filename? - src =~ SCREEN_SHOT_REGEX + @src =~ SCREEN_SHOT_REGEX end def src - @img['src'] if @img['src'] && @img['src'].length > 0 + @src unless @src.nil? || @src.empty? end def missing_src? From 0c48a35577f96dc06bdb94503a7c0970cb62f13e Mon Sep 17 00:00:00 2001 From: Ben Balter Date: Fri, 11 Oct 2013 19:46:33 -0400 Subject: [PATCH 07/12] link check refactor --- Gemfile.lock | 2 +- lib/html/proofer.rb | 1 + lib/html/proofer/check.rb | 50 +--------- lib/html/proofer/checkable.rb | 98 +++++++++++++++++++ lib/html/proofer/checks/images.rb | 13 +-- lib/html/proofer/checks/links.rb | 79 +++++++-------- lib/html/proofer/version.rb | 2 +- .../proofer/fixtures/brokenInternalLink.html | 0 spec/html/proofer/fixtures/notarealhash.html | 0 spec/html/proofer/links_spec.rb | 4 +- 10 files changed, 142 insertions(+), 107 deletions(-) create mode 100644 lib/html/proofer/checkable.rb create mode 100644 spec/html/proofer/fixtures/brokenInternalLink.html create mode 100644 spec/html/proofer/fixtures/notarealhash.html diff --git a/Gemfile.lock b/Gemfile.lock index 53c582e6..83ea09b4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - html-proofer (0.0.16) + html-proofer (0.0.16bb) colored (~> 1.2) nokogiri (= 1.6.0) typhoeus (~> 0.6.3) diff --git a/lib/html/proofer.rb b/lib/html/proofer.rb index fcbd08ba..1084bc05 100644 --- a/lib/html/proofer.rb +++ b/lib/html/proofer.rb @@ -1,4 +1,5 @@ require 'nokogiri' +require 'html/proofer/checkable' require 'html/proofer/checks' module HTML diff --git a/lib/html/proofer/check.rb b/lib/html/proofer/check.rb index 7d25604b..b49d1a39 100644 --- a/lib/html/proofer/check.rb +++ b/lib/html/proofer/check.rb @@ -10,7 +10,7 @@ class HTML::Proofer::Checks class Check - attr_reader :issues, :hydra + attr_reader :issues, :hydra, :src, :path, :options, :additional_href_ignores def initialize(src, path, html, opts={}) @src = src @@ -35,24 +35,6 @@ def output_filenames Dir[@site.config[:output_dir] + '/**/*'].select{ |f| File.file?(f) } end - def external_href?(href) - uri = URI.parse(href) - %w( http https ).include?(uri.scheme) - rescue URI::BadURIError - false - rescue URI::InvalidURIError - false - end - - def ignore_href?(href) - uri = URI.parse(href) - %w( mailto ).include?(uri.scheme) || @additional_href_ignores.include?(href) - rescue URI::BadURIError - false - rescue URI::InvalidURIError - false - end - def validate_url(href, issue_text) request = Typhoeus::Request.new(href, {:followlocation => true}) request.on_complete do |response| @@ -93,35 +75,5 @@ def self.subclasses classes end - def resolve_path(path) - - #Strip anchor, not needed to resolve file - path = path.split('#').first - - if path =~ /^\// #path relative to root - base = @src - elsif File.exist? File.join Dir.pwd, @path #relative links, path is a file - base = File.dirname(@path) - else #relative link, path is a directory - base = @path - end - - if path =~ /^#/ #anchor link, no trailing slash - path = "#{base}#{path}" - else # relative path, resolve trailing slashes automatically - path = File.join base, path - end - - # implicit /index.html support, with support for tailing slashes - path = File.join path, "index.html" if File.directory? File.join Dir.pwd, path - - path - end - - # checks if a file exists relative to the current pwd - def file?(path) - File.exist? File.join Dir.pwd, resolve_path(path) - end - end end diff --git a/lib/html/proofer/checkable.rb b/lib/html/proofer/checkable.rb new file mode 100644 index 00000000..78d403bb --- /dev/null +++ b/lib/html/proofer/checkable.rb @@ -0,0 +1,98 @@ +module HTML + class Proofer + class Checkable + + def initialize(obj, check) + @src = obj['src'] + @href = obj['href'] + @alt = obj['alt'] + @name = obj['name'] + @id = obj['id'] + @check = check + + if @href && @check.options[:href_swap] + @options[:href_swap].each do |link, replace| + @href = @href.gsub(link, replace) + end + end + + end + + def url + @src || @href || "" + end + + def parts + url.split('#') || [""] + end + + def path + parts.first + end + + def hash + parts.last if parts.length > 1 + end + + # path is to an external server + def remote? + uri = URI.parse url + %w( http https ).include?(uri.scheme) + rescue URI::BadURIError + false + rescue URI::InvalidURIError + false + end + + def ignore? + uri = URI.parse url + %w( mailto ).include?(uri.scheme) || @check.additional_href_ignores.include?(href) + rescue URI::BadURIError + false + rescue URI::InvalidURIError + false + end + + # path is external to the file + def external? + !internal? + end + + # path is an anchor + def internal? + url[0] == "#" + end + + def file_path + + return if path.nil? + + if path =~ /^\// #path relative to root + base = @check.src + elsif File.exist? File.expand_path path, @check.src #relative links, path is a file + base = File.dirname @check.path + else #relative link, path is a directory + base = @check.path + end + + file = File.join base, path + + # implicit /index.html support, with support for tailing slashes + file = File.join path, "index.html" if File.directory? File.expand_path file, @check.src + + file + end + + # checks if a file exists relative to the current pwd + def exists? + File.exist? absolute_path + end + + def absolute_path + path = file_path || @check.path + File.expand_path path, Dir.pwd + end + + end + end +end diff --git a/lib/html/proofer/checks/images.rb b/lib/html/proofer/checks/images.rb index 658c1790..c2c1290f 100644 --- a/lib/html/proofer/checks/images.rb +++ b/lib/html/proofer/checks/images.rb @@ -1,14 +1,9 @@ # encoding: utf-8 -class Image +class Image < ::HTML::Proofer::Checkable SCREEN_SHOT_REGEX = /Screen(?: |%20)Shot(?: |%20)\d+-\d+-\d+(?: |%20)at(?: |%20)\d+.\d+.\d+/ - def initialize(img) - @src = img['src'] - @alt = img['alt'] - end - def valid_alt_tag? @alt and !@alt.empty? end @@ -32,15 +27,15 @@ class Images < ::HTML::Proofer::Checks::Check def run @html.css('img').each do |img| - img = Image.new img + img = Image.new img, self # does the image exist? if img.missing_src? self.add_issue "image has no src attribute" - elsif external_href? img.src + elsif img.remote? validate_url img.src, "external image #{img.src} does not exist" else - self.add_issue("internal image #{img.src} does not exist") unless file? img.src + self.add_issue("internal image #{img.src} does not exist") unless img.exists? end # check alt tag diff --git a/lib/html/proofer/checks/links.rb b/lib/html/proofer/checks/links.rb index b0b6772f..4b67f79f 100644 --- a/lib/html/proofer/checks/links.rb +++ b/lib/html/proofer/checks/links.rb @@ -1,56 +1,45 @@ # encoding: utf-8 +class Link < ::HTML::Proofer::Checkable + + def href + @href unless @href.nil? || @href.empty? + end + + def missing_href? + href.nil? and @name.nil? and @id.nil? + end + +end + class Links < ::HTML::Proofer::Checks::Check def run - @html.css('a').each do |a| - href = a['href'] - - if href && href.length > 0 - if @options[:href_swap] - @options[:href_swap].each do |link, replace| - href = href.gsub(link, replace) - end - end + @html.css('a').each do |link| - return if ignore_href?(href) + link = Link.new link, self + return if link.ignore? - if href.include? '#' - href_split = href.split('#') - end - if !external_href?(href) - - # an internal link, with a hash - if href_split && !href_split.empty? - href_file = href_split[0] - href_hash = href_split[1] - - # it's not an internal hash; it's pointing to some other file - if href_file.length > 0 - if !file?(href_file) - self.add_issue("#{@path}".blue + ": internal link #{href_file} does not exist") - else - href_html = HTML::Proofer.create_nokogiri(resolve_path(href_file)) - found_hash_match = false - unless hash_check(href_html, href_hash) - self.add_issue("#{@path}".blue + ": linking to #{href}, but #{href_hash} does not exist") - end - end - # it is an internal link, with an internal hash - else - unless hash_check(@html, href_hash) - self.add_issue("#{@path}".blue + ": linking to an internal hash called #{href_hash} that does not exist") - end - end - # internal link, no hash - else - self.add_issue("#{@path}".blue + ": internally linking to #{href}, which does not exist") unless file?(href) - end - else - validate_url(href, "#{@path}".blue + ": externally linking to #{href}, which does not exist") - end + # is there even a href? + return self.add_issue("link has no href attribute") if link.missing_href? + + # does the file even exist? + if link.remote? + validate_url link.href, "externally linking to #{link.href}, which does not exist" else - self.add_issue("#{@path}".blue + ": link has no href attribute") unless a['name'] || a['id'] + self.add_issue "internally linking to #{link.href}, which does not exist" unless link.exists? + end + + # verify the target hash + if link.hash + if link.remote? + #not yet checked + elsif link.internal? + self.add_issue "linking to internal hash ##{link.hash} that does not exist" unless hash_check @html, link.hash + elsif link.external? + target_html = HTML::Proofer.create_nokogiri link.absolute_path + self.add_issue "linking to #{link.href}, but #{link.hash} does not exist" unless hash_check target_html, link.hash + end end end end diff --git a/lib/html/proofer/version.rb b/lib/html/proofer/version.rb index c76c46fc..964e9f41 100644 --- a/lib/html/proofer/version.rb +++ b/lib/html/proofer/version.rb @@ -1,5 +1,5 @@ module HTML class Proofer - VERSION = "0.0.16" + VERSION = "0.0.16bb" end end diff --git a/spec/html/proofer/fixtures/brokenInternalLink.html b/spec/html/proofer/fixtures/brokenInternalLink.html new file mode 100644 index 00000000..e69de29b diff --git a/spec/html/proofer/fixtures/notarealhash.html b/spec/html/proofer/fixtures/notarealhash.html new file mode 100644 index 00000000..e69de29b diff --git a/spec/html/proofer/links_spec.rb b/spec/html/proofer/links_spec.rb index 7331521f..166ec25e 100644 --- a/spec/html/proofer/links_spec.rb +++ b/spec/html/proofer/links_spec.rb @@ -13,7 +13,7 @@ brokenHashInternalFilepath = "#{FIXTURES_DIR}/brokenHashInternal.html" @linkCheck = Links.new("#{FIXTURES_DIR}", brokenHashInternalFilepath, HTML::Proofer.create_nokogiri(brokenHashInternalFilepath)) @linkCheck.run - @linkCheck.issues[0].should eq("spec/html/proofer/fixtures/brokenHashInternal.html".blue + ": linking to an internal hash called noHash that does not exist") + @linkCheck.issues[0].should eq("spec/html/proofer/fixtures/brokenHashInternal.html".blue + ": linking to internal hash #noHash that does not exist") end it "fails for broken external links" do @@ -57,7 +57,7 @@ brokenLinkWithNumberFilepath = "#{FIXTURES_DIR}/brokenLinkWithNumber.html" @linkCheck = Links.new("#{FIXTURES_DIR}", brokenLinkWithNumberFilepath, HTML::Proofer.create_nokogiri(brokenLinkWithNumberFilepath)) @linkCheck.run - @linkCheck.issues[0].should eq(nil) + @linkCheck.issues[0].should eq("\e[34mspec/html/proofer/fixtures/brokenLinkWithNumber.html\e[0m: internally linking to #25-method-not-allowed, which does not exist") end it 'properly resolves implicit /index.html in link paths' do From 6f06703df5e4617c43d0f91d617118d000adf63d Mon Sep 17 00:00:00 2001 From: Ben Balter Date: Fri, 11 Oct 2013 20:03:12 -0400 Subject: [PATCH 08/12] passing tests --- lib/html/proofer/checkable.rb | 14 +++++++++++--- lib/html/proofer/checks/images.rb | 5 +++-- lib/html/proofer/checks/links.rb | 3 +++ .../proofer/fixtures/brokenLinkWithNumber.html | 4 ++-- spec/html/proofer/links_spec.rb | 2 +- 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/html/proofer/checkable.rb b/lib/html/proofer/checkable.rb index 78d403bb..9922dd26 100644 --- a/lib/html/proofer/checkable.rb +++ b/lib/html/proofer/checkable.rb @@ -22,16 +22,24 @@ def url @src || @href || "" end + def valid? + begin + URI.parse url + rescue + false + end + end + def parts - url.split('#') || [""] + URI.parse url end def path - parts.first + parts.path end def hash - parts.last if parts.length > 1 + parts.fragment end # path is to an external server diff --git a/lib/html/proofer/checks/images.rb b/lib/html/proofer/checks/images.rb index c2c1290f..cd0d538c 100644 --- a/lib/html/proofer/checks/images.rb +++ b/lib/html/proofer/checks/images.rb @@ -29,6 +29,9 @@ def run img = Image.new img, self + # screenshot filenames, return because invalid URL + return self.add_issue "image has a terrible filename (#{img.src})" if img.terrible_filename? + # does the image exist? if img.missing_src? self.add_issue "image has no src attribute" @@ -41,8 +44,6 @@ def run # check alt tag self.add_issue "image #{img.src} does not have an alt attribute" unless img.valid_alt_tag? - # screenshot filenames - self.add_issue "image has a terrible filename (#{img.src})" if img.terrible_filename? end end diff --git a/lib/html/proofer/checks/links.rb b/lib/html/proofer/checks/links.rb index 4b67f79f..37182959 100644 --- a/lib/html/proofer/checks/links.rb +++ b/lib/html/proofer/checks/links.rb @@ -23,6 +23,9 @@ def run # is there even a href? return self.add_issue("link has no href attribute") if link.missing_href? + # is it even a valid URL? + return self.add_issue "#{link.href} is an invalid URL" unless link.valid? + # does the file even exist? if link.remote? validate_url link.href, "externally linking to #{link.href}, which does not exist" diff --git a/spec/html/proofer/fixtures/brokenLinkWithNumber.html b/spec/html/proofer/fixtures/brokenLinkWithNumber.html index 1e316b14..31a75f94 100644 --- a/spec/html/proofer/fixtures/brokenLinkWithNumber.html +++ b/spec/html/proofer/fixtures/brokenLinkWithNumber.html @@ -2,7 +2,7 @@ -

Blah blah blah. 25 Method not allowed

+

Blah blah blah. 25 Method not allowed

- \ No newline at end of file + diff --git a/spec/html/proofer/links_spec.rb b/spec/html/proofer/links_spec.rb index 166ec25e..51d4474e 100644 --- a/spec/html/proofer/links_spec.rb +++ b/spec/html/proofer/links_spec.rb @@ -57,7 +57,7 @@ brokenLinkWithNumberFilepath = "#{FIXTURES_DIR}/brokenLinkWithNumber.html" @linkCheck = Links.new("#{FIXTURES_DIR}", brokenLinkWithNumberFilepath, HTML::Proofer.create_nokogiri(brokenLinkWithNumberFilepath)) @linkCheck.run - @linkCheck.issues[0].should eq("\e[34mspec/html/proofer/fixtures/brokenLinkWithNumber.html\e[0m: internally linking to #25-method-not-allowed, which does not exist") + @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") end it 'properly resolves implicit /index.html in link paths' do From f5f9035448c70c20ebc9a2a8186cd0a4e56c21e1 Mon Sep 17 00:00:00 2001 From: Ben Balter Date: Sat, 12 Oct 2013 10:41:06 -0400 Subject: [PATCH 09/12] add find to proofer.rb --- lib/html/proofer.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/html/proofer.rb b/lib/html/proofer.rb index 1084bc05..cd26c76f 100644 --- a/lib/html/proofer.rb +++ b/lib/html/proofer.rb @@ -1,4 +1,5 @@ require 'nokogiri' +require 'find' require 'html/proofer/checkable' require 'html/proofer/checks' From f06f7e3b8c32acf73b999743572ef7ba38bb1ca8 Mon Sep 17 00:00:00 2001 From: Ben Balter Date: Mon, 14 Oct 2013 09:52:57 -0400 Subject: [PATCH 10/12] add leading slash to index on create nokigiri --- lib/html/proofer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/html/proofer.rb b/lib/html/proofer.rb index cd26c76f..b8f90e64 100644 --- a/lib/html/proofer.rb +++ b/lib/html/proofer.rb @@ -43,7 +43,7 @@ def run end def self.create_nokogiri(path) - path << "index.html" if File.directory? path #support for Jekyll-style links + path << "/index.html" if File.directory? path #support for Jekyll-style links Nokogiri::HTML(File.read(path)) end From f0e56f5ca1a1da1102ae589871e7e021d199fad6 Mon Sep 17 00:00:00 2001 From: Ben Balter Date: Mon, 14 Oct 2013 10:30:09 -0400 Subject: [PATCH 11/12] notify on passing tests --- lib/html/proofer.rb | 5 ++++- lib/html/proofer/version.rb | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/html/proofer.rb b/lib/html/proofer.rb index b8f90e64..967e0f7f 100644 --- a/lib/html/proofer.rb +++ b/lib/html/proofer.rb @@ -26,7 +26,10 @@ def run end end - if !@failedTests.empty? + if @failedTests.empty? + puts "Tests executed sucesfully.".green + exit 0 + else # make the hash default to 0 so that += will work correctly count = Hash.new(0) diff --git a/lib/html/proofer/version.rb b/lib/html/proofer/version.rb index 964e9f41..c76c46fc 100644 --- a/lib/html/proofer/version.rb +++ b/lib/html/proofer/version.rb @@ -1,5 +1,5 @@ module HTML class Proofer - VERSION = "0.0.16bb" + VERSION = "0.0.16" end end From b35e1f56f0671f0cbc42e437b3acad56fee60bb6 Mon Sep 17 00:00:00 2001 From: Ben Balter Date: Mon, 14 Oct 2013 12:33:03 -0400 Subject: [PATCH 12/12] bump gemfile.lock --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 83ea09b4..53c582e6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - html-proofer (0.0.16bb) + html-proofer (0.0.16) colored (~> 1.2) nokogiri (= 1.6.0) typhoeus (~> 0.6.3)