Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
refactor autolink helper. change tests to expect HTML-escaped URLs
Signed-off-by: Michael Koziarski <michael@koziarski.com>
  • Loading branch information
mislav authored and NZKoz committed Nov 15, 2008
1 parent 789a3f5 commit c6c5cd5
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 39 deletions.
46 changes: 20 additions & 26 deletions actionpack/lib/action_view/helpers/text_helper.rb
Expand Up @@ -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
Expand Down
37 changes: 24 additions & 13 deletions actionpack/test/template/text_helper_test.rb
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down

0 comments on commit c6c5cd5

Please sign in to comment.