Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proper relative URL support #5

Merged
merged 4 commits into from
Oct 14, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/html/proofer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
33 changes: 32 additions & 1 deletion lib/html/proofer/check.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
4 changes: 2 additions & 2 deletions lib/html/proofer/checks/images.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
16 changes: 5 additions & 11 deletions lib/html/proofer/checks/links.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@ 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]
href_hash = href_split[1]

# 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")
Expand All @@ -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")
Expand All @@ -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
Empty file.
2 changes: 1 addition & 1 deletion spec/html/proofer/fixtures/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
root.
<h1 id="anchor">root.</a>
9 changes: 0 additions & 9 deletions spec/html/proofer/fixtures/missingImageDirPrefix.html

This file was deleted.

4 changes: 4 additions & 0 deletions spec/html/proofer/fixtures/relativeLinks.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<a href="/index.html">Relative to root</a>
<a href="index.html">Relative to self</a>
<a href="folder/">Folder relative to self</a>
<a href="index.html#anchor">Anchor relative to self</a>
1 change: 1 addition & 0 deletions spec/html/proofer/fixtures/rootLink.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<body>

<p>Blah blah blah. <a href="/">I am root.</a></p>
<p>Blah blah blah. <a href="/folder">I am relative to root.</a></p>

</body>

Expand Down
21 changes: 7 additions & 14 deletions spec/html/proofer/images_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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!(/ #<Typhoeus::Response:[\w]+>/, "")
Expand All @@ -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
Expand Down
29 changes: 18 additions & 11 deletions spec/html/proofer/links_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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!(/ #<Typhoeus::Response:[\w]+>/, "")
Expand All @@ -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
Expand Down