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..c92ffb15 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,35 @@ 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/checks/images.rb b/lib/html/proofer/checks/images.rb
index be4ac68c..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 src[0] != "/" and File.exist?(File.join(File.dirname(@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
@@ -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..b0b6772f 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,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 File.join(File.dirname(@path), href_file)
- 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")
@@ -44,8 +44,7 @@ def run
end
# internal link, no hash
else
- href_location = resolve_path File.join(File.dirname(@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")
@@ -60,9 +59,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
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/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.
-
-
-
-
\ 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/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.
diff --git a/spec/html/proofer/images_spec.rb b/spec/html/proofer/images_spec.rb
index d3faadfa..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 5cf5195a..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