Permalink
Browse files

refactor autolink helper. change tests to expect HTML-escaped URLs

Signed-off-by: Michael Koziarski <michael@koziarski.com>
  • Loading branch information...
1 parent 789a3f5 commit c6c5cd554110f6e62290de3e3008076b2f69e7cb @mislav mislav committed with NZKoz Nov 12, 2008
Showing with 44 additions and 39 deletions.
  1. +20 −26 actionpack/lib/action_view/helpers/text_helper.rb
  2. +24 −13 actionpack/test/template/text_helper_test.rb
@@ -545,38 +545,32 @@ def set_cycle(name, cycle_object)
end
AUTO_LINK_RE = %r{
- ( # leading text
- <\w+.*?>| # leading HTML tag, or
- [^=!:'"/]| # leading punctuation, or
- ^ # beginning of line
- )
- (
- (?:https?://)| # protocol spec, or
- (?:www\.) # www.*
- )
- (
- [-\w]+ # subdomain or domain
- (?:\.[-\w]+)* # remaining subdomains or domain
- (?::\d+)? # port
- (?:/(?:[~\w\+@%=\(\)-]|(?:[,.;:'][^\s$]))*)* # path
- (?:\?[\w\+@%&=.;:-]+)? # query string
- (?:\#[\w\-]*)? # trailing anchor
- )
- ([[:punct:]]|<|$|) # trailing text
- }x unless const_defined?(:AUTO_LINK_RE)
+ ( https?:// | www\. )
+ [^\s<]+
+ }x unless const_defined?(:AUTO_LINK_RE)
# Turns all urls into clickable links. If a block is given, each url
# is yielded and the result is used as the link text.
def auto_link_urls(text, html_options = {})
- extra_options = tag_options(html_options.stringify_keys) || ""
+ link_attributes = html_options.stringify_keys
text.gsub(AUTO_LINK_RE) do
- all, a, b, c, d = $&, $1, $2, $3, $4
- if a =~ /<a\s/i # don't replace URL's that are already linked
- all
+ href = $&
+ # detect already linked URLs
+ unless $` =~ /<a\s[^>]*href="$/
+ if href =~ /[^\w\/-]$/
+ punctuation = href[-1, 1]
+ href = href[0, href.length - 1]
+ else
+ punctuation = ''
+ end
+
+ link_text = block_given?? yield(href) : href
+ href = 'http://' + href unless href.index('http') == 0
+
+ content_tag(:a, h(link_text), link_attributes.merge('href' => href)) + punctuation
else
- text = b + c
- text = yield(text) if block_given?
- %(#{a}<a href="#{b=="www."?"http://www.":b}#{c}"#{extra_options}>#{text}</a>#{d})
+ # do not change string; URL is alreay linked
+ href
end
end
end
@@ -225,36 +225,41 @@ def test_auto_link_parsing
)
urls.each do |url|
- assert_equal %(<a href="#{url}">#{url}</a>), auto_link(url)
+ assert_equal %(<a href="#{CGI::escapeHTML url}">#{CGI::escapeHTML url}</a>), auto_link(url)
end
end
+ def generate_result(link_text, href = nil)
+ href ||= link_text
+ %{<a href="#{CGI::escapeHTML href}">#{CGI::escapeHTML link_text}</a>}
+ end
+
def test_auto_linking
email_raw = 'david@loudthinking.com'
email_result = %{<a href="mailto:#{email_raw}">#{email_raw}</a>}
email2_raw = '+david@loudthinking.com'
email2_result = %{<a href="mailto:#{email2_raw}">#{email2_raw}</a>}
link_raw = 'http://www.rubyonrails.com'
- link_result = %{<a href="#{link_raw}">#{link_raw}</a>}
+ link_result = generate_result(link_raw)
link_result_with_options = %{<a href="#{link_raw}" target="_blank">#{link_raw}</a>}
link2_raw = 'www.rubyonrails.com'
- link2_result = %{<a href="http://#{link2_raw}">#{link2_raw}</a>}
+ link2_result = generate_result(link2_raw, "http://#{link2_raw}")
link3_raw = 'http://manuals.ruby-on-rails.com/read/chapter.need_a-period/103#page281'
- link3_result = %{<a href="#{link3_raw}">#{link3_raw}</a>}
+ link3_result = generate_result(link3_raw)
link4_raw = 'http://foo.example.com/controller/action?parm=value&p2=v2#anchor123'
- link4_result = %{<a href="#{link4_raw}">#{link4_raw}</a>}
+ link4_result = generate_result(link4_raw)
link5_raw = 'http://foo.example.com:3000/controller/action'
- link5_result = %{<a href="#{link5_raw}">#{link5_raw}</a>}
+ link5_result = generate_result(link5_raw)
link6_raw = 'http://foo.example.com:3000/controller/action+pack'
- link6_result = %{<a href="#{link6_raw}">#{link6_raw}</a>}
+ link6_result = generate_result(link6_raw)
link7_raw = 'http://foo.example.com/controller/action?parm=value&p2=v2#anchor-123'
- link7_result = %{<a href="#{link7_raw}">#{link7_raw}</a>}
+ link7_result = generate_result(link7_raw)
link8_raw = 'http://foo.example.com:3000/controller/action.html'
- link8_result = %{<a href="#{link8_raw}">#{link8_raw}</a>}
+ link8_result = generate_result(link8_raw)
link9_raw = 'http://business.timesonline.co.uk/article/0,,9065-2473189,00.html'
- link9_result = %{<a href="#{link9_raw}">#{link9_raw}</a>}
+ link9_result = generate_result(link9_raw)
link10_raw = 'http://www.mail-archive.com/ruby-talk@ruby-lang.org/'
- link10_result = %{<a href="#{link10_raw}">#{link10_raw}</a>}
+ link10_result = generate_result(link10_raw)
assert_equal %(hello #{email_result}), auto_link("hello #{email_raw}", :email_addresses)
assert_equal %(Go to #{link_result}), auto_link("Go to #{link_raw}", :urls)
@@ -299,7 +304,13 @@ def test_auto_linking
assert_equal '', auto_link(nil)
assert_equal '', auto_link('')
assert_equal "#{link_result} #{link_result} #{link_result}", auto_link("#{link_raw} #{link_raw} #{link_raw}")
- assert_equal '<a href="http://www.rubyonrails.com">Ruby On Rails</a>', auto_link('<a href="http://www.rubyonrails.com">Ruby On Rails</a>')
+ end
+
+ def test_auto_link_already_linked
+ linked1 = generate_result('Ruby On Rails', 'http://www.rubyonrails.com')
+ linked2 = generate_result('www.rubyonrails.com', 'http://www.rubyonrails.com')
+ assert_equal linked1, auto_link(linked1)
+ assert_equal linked2, auto_link(linked2)
end
def test_auto_link_at_eol
@@ -317,7 +328,7 @@ def test_auto_link_with_block
end
def test_auto_link_with_options_hash
- assert_equal 'Welcome to my new blog at <a href="http://www.myblog.com/" class="menu" target="_blank">http://www.myblog.com/</a>. Please e-mail me at <a href="mailto:me@email.com">me@email.com</a>.',
+ assert_dom_equal 'Welcome to my new blog at <a href="http://www.myblog.com/" class="menu" target="_blank">http://www.myblog.com/</a>. Please e-mail me at <a href="mailto:me@email.com">me@email.com</a>.',
auto_link("Welcome to my new blog at http://www.myblog.com/. Please e-mail me at me@email.com.",
:link => :all, :html => { :class => "menu", :target => "_blank" })
end

0 comments on commit c6c5cd5

Please sign in to comment.