diff options
-rw-r--r-- | lib/redmine/wiki_formatting.rb | 60 | ||||
-rw-r--r-- | lib/redmine/wiki_formatting/textile/formatter.rb | 56 | ||||
-rw-r--r-- | test/unit/helpers/application_helper_test.rb | 2 | ||||
-rw-r--r-- | test/unit/lib/redmine/wiki_formatting_test.rb | 4 |
4 files changed, 66 insertions, 56 deletions
diff --git a/lib/redmine/wiki_formatting.rb b/lib/redmine/wiki_formatting.rb index 63f833dce..63914e8ce 100644 --- a/lib/redmine/wiki_formatting.rb +++ b/lib/redmine/wiki_formatting.rb @@ -80,19 +80,77 @@ module Redmine end end + module LinksHelper + AUTO_LINK_RE = %r{ + ( # leading text + <\w+.*?>| # leading HTML tag, or + [^=<>!:'"/]| # leading punctuation, or + ^ # beginning of line + ) + ( + (?:https?://)| # protocol spec, or + (?:s?ftps?://)| + (?:www\.) # www.* + ) + ( + (\S+?) # url + (\/)? # slash + ) + ((?:>)?|[^\w\=\/;\(\)]*?) # post + (?=<|\s|$) + }x unless const_defined?(:AUTO_LINK_RE) + + # Destructively remplaces urls into clickable links + def auto_link!(text) + text.gsub!(AUTO_LINK_RE) do + all, leading, proto, url, post = $&, $1, $2, $3, $6 + if leading =~ /<a\s/i || leading =~ /![<>=]?/ + # don't replace URL's that are already linked + # and URL's prefixed with ! !> !< != (textile images) + all + else + # Idea below : an URL with unbalanced parethesis and + # ending by ')' is put into external parenthesis + if ( url[-1]==?) and ((url.count("(") - url.count(")")) < 0 ) ) + url=url[0..-2] # discard closing parenth from url + post = ")"+post # add closing parenth to post + end + tag = content_tag('a', proto + url, :href => "#{proto=="www."?"http://www.":proto}#{url}", :class => 'external') + %(#{leading}#{tag}#{post}) + end + end + end + + # Destructively remplaces email addresses into clickable links + def auto_mailto!(text) + text.gsub!(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do + mail = $1 + if text.match(/<a\b[^>]*>(.*)(#{Regexp.escape(mail)})(.*)<\/a>/) + mail + else + content_tag('a', mail, :href => "mailto:#{mail}", :class => "email") + end + end + end + end + # Default formatter module module NullFormatter class Formatter include ActionView::Helpers::TagHelper include ActionView::Helpers::TextHelper include ActionView::Helpers::UrlHelper + include Redmine::WikiFormatting::LinksHelper def initialize(text) @text = text end def to_html(*args) - simple_format(auto_link(CGI::escapeHTML(@text))) + t = CGI::escapeHTML(@text) + auto_link!(t) + auto_mailto!(t) + simple_format(t) end end diff --git a/lib/redmine/wiki_formatting/textile/formatter.rb b/lib/redmine/wiki_formatting/textile/formatter.rb index bbe47a15c..5f0c1cb3e 100644 --- a/lib/redmine/wiki_formatting/textile/formatter.rb +++ b/lib/redmine/wiki_formatting/textile/formatter.rb @@ -23,6 +23,10 @@ module Redmine module Textile class Formatter < RedCloth3 include ActionView::Helpers::TagHelper + include Redmine::WikiFormatting::LinksHelper + + alias :inline_auto_link :auto_link! + alias :inline_auto_mailto :auto_mailto! # auto_link rule after textile rules so that it doesn't break !image_url! tags RULES = [:textile, :block_markdown_rule, :inline_auto_link, :inline_auto_mailto] @@ -124,58 +128,6 @@ module Redmine end end end - - AUTO_LINK_RE = %r{ - ( # leading text - <\w+.*?>| # leading HTML tag, or - [^=<>!:'"/]| # leading punctuation, or - ^ # beginning of line - ) - ( - (?:https?://)| # protocol spec, or - (?:s?ftps?://)| - (?:www\.) # www.* - ) - ( - (\S+?) # url - (\/)? # slash - ) - ((?:>)?|[^\w\=\/;\(\)]*?) # post - (?=<|\s|$) - }x unless const_defined?(:AUTO_LINK_RE) - - # Turns all urls into clickable links (code from Rails). - def inline_auto_link(text) - text.gsub!(AUTO_LINK_RE) do - all, leading, proto, url, post = $&, $1, $2, $3, $6 - if leading =~ /<a\s/i || leading =~ /![<>=]?/ - # don't replace URL's that are already linked - # and URL's prefixed with ! !> !< != (textile images) - all - else - # Idea below : an URL with unbalanced parethesis and - # ending by ')' is put into external parenthesis - if ( url[-1]==?) and ((url.count("(") - url.count(")")) < 0 ) ) - url=url[0..-2] # discard closing parenth from url - post = ")"+post # add closing parenth to post - end - tag = content_tag('a', proto + url, :href => "#{proto=="www."?"http://www.":proto}#{url}", :class => 'external') - %(#{leading}#{tag}#{post}) - end - end - end - - # Turns all email addresses into clickable links (code from Rails). - def inline_auto_mailto(text) - text.gsub!(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do - mail = $1 - if text.match(/<a\b[^>]*>(.*)(#{Regexp.escape(mail)})(.*)<\/a>/) - mail - else - content_tag('a', mail, :href => "mailto:#{mail}", :class => "email") - end - end - end end end end diff --git a/test/unit/helpers/application_helper_test.rb b/test/unit/helpers/application_helper_test.rb index 2fcb0309c..a9dd4b3b4 100644 --- a/test/unit/helpers/application_helper_test.rb +++ b/test/unit/helpers/application_helper_test.rb @@ -940,7 +940,7 @@ RAW def test_default_formatter with_settings :text_formatting => 'unknown' do text = 'a *link*: http://www.example.net/' - assert_equal '<p>a *link*: <a href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text) + assert_equal '<p>a *link*: <a class="external" href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text) end end diff --git a/test/unit/lib/redmine/wiki_formatting_test.rb b/test/unit/lib/redmine/wiki_formatting_test.rb index 909acdea7..915b08621 100644 --- a/test/unit/lib/redmine/wiki_formatting_test.rb +++ b/test/unit/lib/redmine/wiki_formatting_test.rb @@ -36,8 +36,8 @@ and an email address foo@example.net DIFF expected = <<-EXPECTED -<p>This is a sample *text* with a link: <a href="http://www.redmine.org">http://www.redmine.org</a><br /> -and an email address <a href="mailto:foo@example.net">foo@example.net</a></p> +<p>This is a sample *text* with a link: <a class="external" href="http://www.redmine.org">http://www.redmine.org</a><br /> +and an email address <a class="email" href="mailto:foo@example.net">foo@example.net</a></p> EXPECTED assert_equal expected.gsub(%r{[\r\n\t]}, ''), Redmine::WikiFormatting::NullFormatter::Formatter.new(raw).to_html.gsub(%r{[\r\n\t]}, '') |