Commit 20eed684 authored by Felix Schäfer's avatar Felix Schäfer

[#739] Convert relative links to full links in textile

Textile doesn't "understand" :only_path => false and thus doesn't convert links of the form

<pre>"foo":/bar</pre>

to full URLs, this is done in a subsequent method akin to the wiki_lins and so on
parent 26c847a4
......@@ -502,7 +502,7 @@ module ApplicationHelper
@parsed_headings = []
text = parse_non_pre_blocks(text) do |text|
[:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links, :parse_headings].each do |method_name|
[:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links, :parse_headings, :parse_relative_urls].each do |method_name|
send method_name, text, project, obj, attr, only_path, options
end
end
......@@ -543,6 +543,41 @@ module ApplicationHelper
parsed
end
RELATIVE_LINK_RE = %r{
<a
(?:
(\shref=
(?: # the href and link
(?:'(\/[^>]+?)')|
(?:"(\/[^>]+?)")
)
)|
[^>]
)*
>
[^<]*?<\/a> # content and closing link tag.
}x unless const_defined?(:RELATIVE_LINK_RE)
def parse_relative_urls(text, project, obj, attr, only_path, options)
return if only_path
text.gsub!(RELATIVE_LINK_RE) do |m|
href, relative_url = $1, $2 || $3
next m unless href.present?
if defined?(request) && request.present?
# we have a request!
protocol, host_with_port = request.protocol, request.host_with_port
elsif @controller
# use the same methods as url_for in the Mailer
url_opts = @controller.class.default_url_options
next m unless url_opts && url_opts[:protocol] && url_opts[:host]
protocol, host_with_port = "#{url_opts[:protocol]}://", url_opts[:host]
else
next m
end
m.sub href, " href=\"#{protocol}#{host_with_port}#{relative_url}\""
end
end
def parse_inline_attachments(text, project, obj, attr, only_path, options)
# when using an image link, try to use an attachment, if possible
if options[:attachments] || (obj && obj.respond_to?(:attachments))
......
......@@ -27,6 +27,10 @@ class ApplicationHelperTest < ActionView::TestCase
super
end
def request
@request ||= ActionController::TestRequest.new
end
context "#link_to_if_authorized" do
context "authorized user" do
should "be tested"
......@@ -144,6 +148,34 @@ RAW
to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
end
def test_textile_relative_to_full_links_in_a_controller
# we have a request here
{
# shouldn't change non-relative links
'This is a "link":http://foo.bar' => 'This is a <a href="http://foo.bar" class="external">link</a>',
'This is an intern "link":/foo/bar' => 'This is an intern <a href="http://test.host/foo/bar">link</a>',
'This is an intern "link":/foo/bar and an extern "link":http://foo.bar' => 'This is an intern <a href="http://test.host/foo/bar">link</a> and an extern <a href="http://foo.bar" class="external">link</a>',
}.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :only_path => false) }
end
def test_textile_relative_to_full_links_in_the_mailer
# we don't a request here
undef request
# mimic the mailer default_url_options
@controller.class.class_eval {
def self.default_url_options
::Mailer.default_url_options
end
}
{
# shouldn't change non-relative links
'This is a "link":http://foo.bar' => 'This is a <a href="http://foo.bar" class="external">link</a>',
'This is an intern "link":/foo/bar' => 'This is an intern <a href="http://localhost:3000/foo/bar">link</a>',
'This is an intern "link":/foo/bar and an extern "link":http://foo.bar' => 'This is an intern <a href="http://localhost:3000/foo/bar">link</a> and an extern <a href="http://foo.bar" class="external">link</a>',
}.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :only_path => false) }
end
def test_redmine_links
issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3},
:class => 'issue status-1 priority-1 overdue', :title => 'Error 281 when updating a recipe (New)')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment