Merge pull request #438 from bhollis/link_to

Make link_to magical
This commit is contained in:
Thomas Reynolds 2012-05-19 19:43:42 -07:00
commit 671dcde65f
4 changed files with 136 additions and 8 deletions

View file

@ -46,10 +46,21 @@ Feature: Directory Index
unknown_link_to: <%= link_to "Unknown", "/unknown.html" %>
relative_link_to: <%= link_to "Relative", "needs_index.html" %>
"""
And a file named "source/link_to/sub.html.erb" with:
"""
link_to: <%= link_to "Needs Index", "/needs_index.html" %>
explicit_link_to: <%= link_to "Explicit", "/needs_index/index.html" %>
unknown_link_to: <%= link_to "Unknown", "/unknown.html" %>
relative_link_to: <%= link_to "Relative", "../needs_index.html" %>
"""
And the Server is running at "indexable-app"
When I go to "/link_to/"
Then I should see 'link_to: <a href="/needs_index/">Needs Index</a>'
Then I should see 'explicit_link_to: <a href="/needs_index/index.html">Explicit</a>'
Then I should see 'unknown_link_to: <a href="/unknown.html">Unknown</a>'
# Relative links aren't touched
Then I should see 'relative_link_to: <a href="needs_index.html">Relative</a>'
Then I should see 'relative_link_to: <a href="/needs_index/">Relative</a>'
When I go to "/link_to/sub/"
Then I should see 'link_to: <a href="/needs_index/">Needs Index</a>'
Then I should see 'explicit_link_to: <a href="/needs_index/index.html">Explicit</a>'
Then I should see 'unknown_link_to: <a href="/unknown.html">Unknown</a>'
Then I should see 'relative_link_to: <a href="/needs_index/">Relative</a>'

View file

@ -0,0 +1,68 @@
Feature: relative_link_to helper
Scenario: relative_link_to produces relative links
Given a fixture app "indexable-app"
And an empty file named "config.rb"
And a file named "source/link_to.html.erb" with:
"""
absolute: <%= link_to "Needs Index", "/needs_index.html", :relative => true %>
relative: <%= link_to "Relative", "needs_index.html", :relative => true %>
"""
And a file named "source/link_to/sub.html.erb" with:
"""
absolute: <%= link_to "Needs Index", "/needs_index.html", :relative => true %>
relative: <%= link_to "Relative", "../needs_index.html", :relative => true %>
"""
And the Server is running at "indexable-app"
When I go to "/link_to.html"
Then I should see 'absolute: <a href="needs_index.html">Needs Index</a>'
Then I should see 'relative: <a href="needs_index.html">Relative</a>'
When I go to "/link_to/sub.html"
Then I should see 'absolute: <a href="../needs_index.html">Needs Index</a>'
Then I should see 'relative: <a href="../needs_index.html">Relative</a>'
Scenario: relative_link_to produces relative links when :relative_links is set to true
Given a fixture app "indexable-app"
And a file named "config.rb" with:
"""
set :relative_links, true
"""
And a file named "source/link_to.html.erb" with:
"""
absolute: <%= link_to "Needs Index", "/needs_index.html" %>
relative: <%= link_to "Relative", "needs_index.html", :relative => false %>
unknown: <%= link_to "Unknown", "foo.html" %>
"""
And a file named "source/link_to/sub.html.erb" with:
"""
absolute: <%= link_to "Needs Index", "/needs_index.html" %>
relative: <%= link_to "Relative", "../needs_index.html" %>
"""
And the Server is running at "indexable-app"
When I go to "/link_to.html"
Then I should see 'absolute: <a href="needs_index.html">Needs Index</a>'
Then I should see 'relative: <a href="/needs_index.html">Relative</a>'
Then I should see 'unknown: <a href="foo.html">Unknown</a>'
When I go to "/link_to/sub.html"
Then I should see 'absolute: <a href="../needs_index.html">Needs Index</a>'
Then I should see 'relative: <a href="../needs_index.html">Relative</a>'
Scenario: relative_link_to knows about directory indexes
Given a fixture app "indexable-app"
And a file named "source/link_to.html.erb" with:
"""
absolute: <%= link_to "Needs Index", "/needs_index.html", :relative => true %>
relative: <%= link_to "Relative", "needs_index.html", :relative => true %>
"""
And a file named "source/link_to/sub.html.erb" with:
"""
absolute: <%= link_to "Needs Index", "/needs_index.html", :relative => true %>
relative: <%= link_to "Relative", "../needs_index.html", :relative => true %>
"""
And the Server is running at "indexable-app"
When I go to "/link_to/"
Then I should see 'absolute: <a href="needs_index/">Needs Index</a>'
Then I should see 'relative: <a href="needs_index/">Relative</a>'
When I go to "/link_to/sub/"
Then I should see 'absolute: <a href="../needs_index/">Needs Index</a>'
Then I should see 'relative: <a href="../needs_index/">Relative</a>'

View file

@ -20,6 +20,8 @@ module Middleman
# app.helpers ::Padrino::Helpers::TranslationHelpers
app.helpers Helpers
app.set :relative_links, false
end
alias :included :registered
end
@ -106,15 +108,62 @@ module Middleman
"#{result_path}"
end
# Overload the regular link_to to be sitemap-aware - if you
# reference a source path, either absolutely or relatively,
# you'll get that resource's nice URL. Also, there is a
# :relative option which, if set to true, will produce
# relative URLs instead of absolute URLs. You can also add
#
# set :relative_links, true
#
# to config.rb to have all links default to relative.
def link_to(*args, &block)
url_arg_index = block_given? ? 0 : 1
options_index = block_given? ? 1 : 2
if url = args[url_arg_index]
# Only try to work with absolute URLs
if url.start_with? '/'
options = args[options_index] || {}
relative = options.delete(:relative)
if url.include? '://'
raise "Can't use the relative option with an external URL" if relative
else
# Handle relative urls
current_dir = Pathname('/' + current_resource.path).dirname
path = Pathname(url)
url = current_dir.join(path).to_s if path.relative?
resource = sitemap.find_resource_by_path(url)
args[url_arg_index] = resource.url if resource
# Allow people to turn on relative paths for all links with set :relative_links, true
# but still override on a case by case basis with the :relative parameter.
effective_relative = relative || false
if relative.nil? && relative_links
effective_relative = true
end
if resource
if effective_relative
resource_url = resource.url
new_url = Pathname(resource_url).relative_path_from(current_dir).to_s
# Put back the trailing slash to avoid unnecessary Apache redirects
if resource_url.end_with?('/') && !new_url.end_with?('/')
new_url << '/'
end
else
new_url = resource.url
end
args[url_arg_index] = new_url
else
raise "No resource exists at #{url}" if relative
end
end
end
super(*args, &block)
end
end

View file

@ -140,7 +140,7 @@ module Middleman
# just foo. Best for linking.
# @return [String]
def url
'/' + destination_path.sub(/#{Regexp.escape(app.index_file)}$/, '')
('/' + destination_path).sub(/\/#{Regexp.escape(app.index_file)}$/, '/')
end
end
end