diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 7503437c..394e05ae 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -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> # 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))
diff --git a/test/unit/helpers/application_helper_test.rb b/test/unit/helpers/application_helper_test.rb
index 48c99c05..8c9af006 100644
--- a/test/unit/helpers/application_helper_test.rb
+++ b/test/unit/helpers/application_helper_test.rb
@@ -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 " #{result}
#{result}
", 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 link', + 'This is an intern "link":/foo/bar' => 'This is an intern link', + 'This is an intern "link":/foo/bar and an extern "link":http://foo.bar' => 'This is an intern link and an extern link', + }.each { |text, result| assert_equal "#{result}
", 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)')