diff options
author | Mislav Marohnić <mislav.marohnic@gmail.com> | 2009-03-11 11:27:44 +0100 |
---|---|---|
committer | Mikel Lindsaar <raasdnil@gmail.com> | 2010-06-03 23:32:09 +1000 |
commit | 533b1311b082aab52d2fccebae03bb74c406f8be (patch) | |
tree | 2d44feeacfeabc6446186cc74564210fffde29d2 /actionpack/lib | |
parent | f00561e0f1e61e31f8957eda3897f15518942ed4 (diff) | |
download | rails-533b1311b082aab52d2fccebae03bb74c406f8be.tar.gz rails-533b1311b082aab52d2fccebae03bb74c406f8be.tar.bz2 rails-533b1311b082aab52d2fccebae03bb74c406f8be.zip |
avoid auto_linking already linked emails; more robust detection of linked URLs
References #1523 [#1862 state:resolved] [#3591 state:resolved]
Add test that shows how link text can contain HTML if needed:
the trick is using block form in combination with `raw`.
Let link text be automatically HTML-escaped
[#2017 state:resolved]
Diffstat (limited to 'actionpack/lib')
-rw-r--r-- | actionpack/lib/action_view/helpers/text_helper.rb | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index fa930ac626..41423d4e2e 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -539,7 +539,12 @@ module ActionView AUTO_LINK_RE = %r{ (?: ([\w+.:-]+:)// | www\. ) [^\s<]+ - }x unless const_defined?(:AUTO_LINK_RE) + }x + + # regexps for determining context, used high-volume + AUTO_LINK_CRE = [/<[^>]+$/, /^[^>]*>/, /<a\b.*?>/i, /<\/a>/i] + + AUTO_EMAIL_RE = /[\w.!#\$%+-]+@[\w-]+(?:\.[\w-]+)+/ BRACKETS = { ']' => '[', ')' => '(', '}' => '{' } @@ -550,9 +555,8 @@ module ActionView text.gsub(AUTO_LINK_RE) do scheme, href = $1, $& punctuation = [] - left, right = $`, $' - # detect already linked URLs and URLs in the middle of a tag - if left =~ /<[^>]+$/ && right =~ /^[^>]*>/ + + if auto_linked?($`, $') # do not change string; URL is already linked href else @@ -568,7 +572,7 @@ module ActionView link_text = block_given?? yield(href) : href href = 'http://' + href unless scheme - content_tag(:a, h(link_text), link_attributes.merge('href' => href)) + punctuation.reverse.join('') + content_tag(:a, link_text, link_attributes.merge('href' => href)) + punctuation.reverse.join('') end end end @@ -576,11 +580,10 @@ module ActionView # Turns all email addresses into clickable links. If a block is given, # each email is yielded and the result is used as the link text. def auto_link_email_addresses(text, html_options = {}) - body = text.dup - text.gsub(/([\w\.!#\$%\-+]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do - text = $1 + text.gsub(AUTO_EMAIL_RE) do + text = $& - if body.match(/<a\b[^>]*>(.*)(#{Regexp.escape(text)})(.*)<\/a>/) + if auto_linked?($`, $') text else display_text = (block_given?) ? yield(text) : text @@ -588,6 +591,12 @@ module ActionView end end end + + # Detects already linked context or position in the middle of a tag + def auto_linked?(left, right) + (left =~ AUTO_LINK_CRE[0] and right =~ AUTO_LINK_CRE[1]) or + (left.rindex(AUTO_LINK_CRE[2]) and $' !~ AUTO_LINK_CRE[3]) + end end end end |