Skip to content

Commit df01202

Browse files
committed
Change code structure. Easy testing.
1 parent 68daf9e commit df01202

File tree

3 files changed

+154
-151
lines changed

3 files changed

+154
-151
lines changed

lib/rails_autolink.rb

Lines changed: 1 addition & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -4,154 +4,7 @@ module RailsAutolink
44
class Railtie < ::Rails::Railtie
55
initializer 'rails_autolink' do |app|
66
ActiveSupport.on_load(:action_view) do
7-
require 'active_support/core_ext/object/blank'
8-
require 'active_support/core_ext/array/extract_options'
9-
require 'active_support/core_ext/hash/reverse_merge'
10-
require 'active_support/core_ext/hash/keys'
11-
12-
module ::ActionView
13-
module Helpers # :nodoc:
14-
module TextHelper
15-
# Turns all URLs and e-mail addresses into clickable links. The <tt>:link</tt> option
16-
# will limit what should be linked. You can add HTML attributes to the links using
17-
# <tt>:html</tt>. Possible values for <tt>:link</tt> are <tt>:all</tt> (default),
18-
# <tt>:email_addresses</tt>, and <tt>:urls</tt>. If a block is given, each URL and
19-
# e-mail address is yielded and the result is used as the link text. By default the
20-
# text given is sanitized, you can override this behaviour setting the
21-
# <tt>:sanitize</tt> option to false.
22-
#
23-
# ==== Examples
24-
# auto_link("Go to http://www.rubyonrails.org and say hello to [email protected]")
25-
# # => "Go to <a href=\"http://www.rubyonrails.org\">http://www.rubyonrails.org</a> and
26-
# # say hello to <a href=\"mailto:[email protected]\">[email protected]</a>"
27-
#
28-
# auto_link("Visit http://www.loudthinking.com/ or e-mail [email protected]", :link => :urls)
29-
# # => "Visit <a href=\"http://www.loudthinking.com/\">http://www.loudthinking.com/</a>
30-
# # or e-mail [email protected]"
31-
#
32-
# auto_link("Visit http://www.loudthinking.com/ or e-mail [email protected]", :link => :email_addresses)
33-
# # => "Visit http://www.loudthinking.com/ or e-mail <a href=\"mailto:[email protected]\">[email protected]</a>"
34-
#
35-
# post_body = "Welcome to my new blog at http://www.myblog.com/. Please e-mail me at [email protected]."
36-
# auto_link(post_body, :html => { :target => '_blank' }) do |text|
37-
# truncate(text, :length => 15)
38-
# end
39-
# # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\" target=\"_blank\">http://www.m...</a>.
40-
# Please e-mail me at <a href=\"mailto:[email protected]\">[email protected]</a>."
41-
#
42-
#
43-
# You can still use <tt>auto_link</tt> with the old API that accepts the
44-
# +link+ as its optional second parameter and the +html_options+ hash
45-
# as its optional third parameter:
46-
# post_body = "Welcome to my new blog at http://www.myblog.com/. Please e-mail me at [email protected]."
47-
# auto_link(post_body, :urls)
48-
# # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\">http://www.myblog.com</a>.
49-
# Please e-mail me at [email protected]."
50-
#
51-
# auto_link(post_body, :all, :target => "_blank")
52-
# # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\" target=\"_blank\">http://www.myblog.com</a>.
53-
# Please e-mail me at <a href=\"mailto:[email protected]\">[email protected]</a>."
54-
def auto_link(text, *args, &block)#link = :all, html = {}, &block)
55-
return ''.html_safe if text.blank?
56-
57-
options = args.size == 2 ? {} : args.extract_options! # this is necessary because the old auto_link API has a Hash as its last parameter
58-
unless args.empty?
59-
options[:link] = args[0] || :all
60-
options[:html] = args[1] || {}
61-
end
62-
options.reverse_merge!(:link => :all, :html => {})
63-
sanitize = (options[:sanitize] != false)
64-
text = conditional_sanitize(text, sanitize).to_str
65-
case options[:link].to_sym
66-
when :all then conditional_html_safe(auto_link_email_addresses(auto_link_urls(text, options[:html], options, &block), options[:html], &block), sanitize)
67-
when :email_addresses then conditional_html_safe(auto_link_email_addresses(text, options[:html], &block), sanitize)
68-
when :urls then conditional_html_safe(auto_link_urls(text, options[:html], options, &block), sanitize)
69-
end
70-
end
71-
72-
private
73-
74-
AUTO_LINK_RE = %r{
75-
(?: ([0-9A-Za-z+.:-]+:)// | www\. )
76-
[^\s<]+
77-
}x
78-
79-
# regexps for determining context, used high-volume
80-
AUTO_LINK_CRE = [/<[^>]+$/, /^[^>]*>/, /<a\b.*?>/i, /<\/a>/i]
81-
82-
AUTO_EMAIL_RE = /[\w.!#\$%+-]+@[\w-]+(?:\.[\w-]+)+/
83-
84-
BRACKETS = { ']' => '[', ')' => '(', '}' => '{' }
85-
86-
# Turns all urls into clickable links. If a block is given, each url
87-
# is yielded and the result is used as the link text.
88-
def auto_link_urls(text, html_options = {}, options = {})
89-
link_attributes = html_options.stringify_keys
90-
text.gsub(AUTO_LINK_RE) do
91-
scheme, href = $1, $&
92-
punctuation = []
93-
94-
if auto_linked?($`, $')
95-
# do not change string; URL is already linked
96-
href
97-
else
98-
# don't include trailing punctuation character as part of the URL
99-
while href.sub!(/[^\w\/-]$/, '')
100-
punctuation.push $&
101-
if opening = BRACKETS[punctuation.last] and href.scan(opening).size > href.scan(punctuation.last).size
102-
href << punctuation.pop
103-
break
104-
end
105-
end
106-
107-
link_text = block_given?? yield(href) : href
108-
href = 'http://' + href unless scheme
109-
110-
unless options[:sanitize] == false
111-
link_text = sanitize(link_text)
112-
href = sanitize(href)
113-
end
114-
content_tag(:a, link_text, link_attributes.merge('href' => href), !!options[:sanitize]) + punctuation.reverse.join('')
115-
end
116-
end
117-
end
118-
119-
# Turns all email addresses into clickable links. If a block is given,
120-
# each email is yielded and the result is used as the link text.
121-
def auto_link_email_addresses(text, html_options = {}, options = {})
122-
text.gsub(AUTO_EMAIL_RE) do
123-
text = $&
124-
125-
if auto_linked?($`, $')
126-
text.html_safe
127-
else
128-
display_text = (block_given?) ? yield(text) : text
129-
130-
unless options[:sanitize] == false
131-
text = sanitize(text)
132-
display_text = sanitize(display_text) unless text == display_text
133-
end
134-
mail_to text, display_text, html_options
135-
end
136-
end
137-
end
138-
139-
# Detects already linked context or position in the middle of a tag
140-
def auto_linked?(left, right)
141-
(left =~ AUTO_LINK_CRE[0] and right =~ AUTO_LINK_CRE[1]) or
142-
(left.rindex(AUTO_LINK_CRE[2]) and $' !~ AUTO_LINK_CRE[3])
143-
end
144-
145-
def conditional_sanitize(target, condition)
146-
condition ? sanitize(target) : target
147-
end
148-
149-
def conditional_html_safe(target, condition)
150-
condition ? target.html_safe : target
151-
end
152-
end
153-
end
154-
end
7+
require 'rails_autolink/helpers'
1558
end
1569
end
15710
end

lib/rails_autolink/helpers.rb

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
module RailsAutolink
2+
require 'active_support/core_ext/object/blank'
3+
require 'active_support/core_ext/array/extract_options'
4+
require 'active_support/core_ext/hash/reverse_merge'
5+
require 'active_support/core_ext/hash/keys'
6+
7+
module ::ActionView
8+
module Helpers # :nodoc:
9+
module TextHelper
10+
# Turns all URLs and e-mail addresses into clickable links. The <tt>:link</tt> option
11+
# will limit what should be linked. You can add HTML attributes to the links using
12+
# <tt>:html</tt>. Possible values for <tt>:link</tt> are <tt>:all</tt> (default),
13+
# <tt>:email_addresses</tt>, and <tt>:urls</tt>. If a block is given, each URL and
14+
# e-mail address is yielded and the result is used as the link text. By default the
15+
# text given is sanitized, you can override this behaviour setting the
16+
# <tt>:sanitize</tt> option to false.
17+
#
18+
# ==== Examples
19+
# auto_link("Go to http://www.rubyonrails.org and say hello to [email protected]")
20+
# # => "Go to <a href=\"http://www.rubyonrails.org\">http://www.rubyonrails.org</a> and
21+
# # say hello to <a href=\"mailto:[email protected]\">[email protected]</a>"
22+
#
23+
# auto_link("Visit http://www.loudthinking.com/ or e-mail [email protected]", :link => :urls)
24+
# # => "Visit <a href=\"http://www.loudthinking.com/\">http://www.loudthinking.com/</a>
25+
# # or e-mail [email protected]"
26+
#
27+
# auto_link("Visit http://www.loudthinking.com/ or e-mail [email protected]", :link => :email_addresses)
28+
# # => "Visit http://www.loudthinking.com/ or e-mail <a href=\"mailto:[email protected]\">[email protected]</a>"
29+
#
30+
# post_body = "Welcome to my new blog at http://www.myblog.com/. Please e-mail me at [email protected]."
31+
# auto_link(post_body, :html => { :target => '_blank' }) do |text|
32+
# truncate(text, :length => 15)
33+
# end
34+
# # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\" target=\"_blank\">http://www.m...</a>.
35+
# Please e-mail me at <a href=\"mailto:[email protected]\">[email protected]</a>."
36+
#
37+
#
38+
# You can still use <tt>auto_link</tt> with the old API that accepts the
39+
# +link+ as its optional second parameter and the +html_options+ hash
40+
# as its optional third parameter:
41+
# post_body = "Welcome to my new blog at http://www.myblog.com/. Please e-mail me at [email protected]."
42+
# auto_link(post_body, :urls)
43+
# # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\">http://www.myblog.com</a>.
44+
# Please e-mail me at [email protected]."
45+
#
46+
# auto_link(post_body, :all, :target => "_blank")
47+
# # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\" target=\"_blank\">http://www.myblog.com</a>.
48+
# Please e-mail me at <a href=\"mailto:[email protected]\">[email protected]</a>."
49+
def auto_link(text, *args, &block)#link = :all, html = {}, &block)
50+
return ''.html_safe if text.blank?
51+
52+
options = args.size == 2 ? {} : args.extract_options! # this is necessary because the old auto_link API has a Hash as its last parameter
53+
unless args.empty?
54+
options[:link] = args[0] || :all
55+
options[:html] = args[1] || {}
56+
end
57+
options.reverse_merge!(:link => :all, :html => {})
58+
sanitize = (options[:sanitize] != false)
59+
text = conditional_sanitize(text, sanitize).to_str
60+
case options[:link].to_sym
61+
when :all then conditional_html_safe(auto_link_email_addresses(auto_link_urls(text, options[:html], options, &block), options[:html], &block), sanitize)
62+
when :email_addresses then conditional_html_safe(auto_link_email_addresses(text, options[:html], &block), sanitize)
63+
when :urls then conditional_html_safe(auto_link_urls(text, options[:html], options, &block), sanitize)
64+
end
65+
end
66+
67+
private
68+
69+
AUTO_LINK_RE = %r{
70+
(?: ([0-9A-Za-z+.:-]+:)// | www\. )
71+
[^\s<]+
72+
}x
73+
74+
# regexps for determining context, used high-volume
75+
AUTO_LINK_CRE = [/<[^>]+$/, /^[^>]*>/, /<a\b.*?>/i, /<\/a>/i]
76+
77+
AUTO_EMAIL_RE = /[\w.!#\$%+-]+@[\w-]+(?:\.[\w-]+)+/
78+
79+
BRACKETS = { ']' => '[', ')' => '(', '}' => '{' }
80+
81+
# Turns all urls into clickable links. If a block is given, each url
82+
# is yielded and the result is used as the link text.
83+
def auto_link_urls(text, html_options = {}, options = {})
84+
link_attributes = html_options.stringify_keys
85+
text.gsub(AUTO_LINK_RE) do
86+
scheme, href = $1, $&
87+
punctuation = []
88+
89+
if auto_linked?($`, $')
90+
# do not change string; URL is already linked
91+
href
92+
else
93+
# don't include trailing punctuation character as part of the URL
94+
while href.sub!(/[^\w\/-]$/, '')
95+
punctuation.push $&
96+
if opening = BRACKETS[punctuation.last] and href.scan(opening).size > href.scan(punctuation.last).size
97+
href << punctuation.pop
98+
break
99+
end
100+
end
101+
102+
link_text = block_given?? yield(href) : href
103+
href = 'http://' + href unless scheme
104+
105+
unless options[:sanitize] == false
106+
link_text = sanitize(link_text)
107+
href = sanitize(href)
108+
end
109+
content_tag(:a, link_text, link_attributes.merge('href' => href), !!options[:sanitize]) + punctuation.reverse.join('')
110+
end
111+
end
112+
end
113+
114+
# Turns all email addresses into clickable links. If a block is given,
115+
# each email is yielded and the result is used as the link text.
116+
def auto_link_email_addresses(text, html_options = {}, options = {})
117+
text.gsub(AUTO_EMAIL_RE) do
118+
text = $&
119+
120+
if auto_linked?($`, $')
121+
text.html_safe
122+
else
123+
display_text = (block_given?) ? yield(text) : text
124+
125+
unless options[:sanitize] == false
126+
text = sanitize(text)
127+
display_text = sanitize(display_text) unless text == display_text
128+
end
129+
mail_to text, display_text, html_options
130+
end
131+
end
132+
end
133+
134+
# Detects already linked context or position in the middle of a tag
135+
def auto_linked?(left, right)
136+
(left =~ AUTO_LINK_CRE[0] and right =~ AUTO_LINK_CRE[1]) or
137+
(left.rindex(AUTO_LINK_CRE[2]) and $' !~ AUTO_LINK_CRE[3])
138+
end
139+
140+
def conditional_sanitize(target, condition)
141+
condition ? sanitize(target) : target
142+
end
143+
144+
def conditional_html_safe(target, condition)
145+
condition ? target.html_safe : target
146+
end
147+
end
148+
end
149+
end
150+
end

test/test_rails_autolink.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
# encoding: utf-8
22

33
require "minitest/autorun"
4-
require "rails_autolink"
4+
require "rails"
5+
require "rails_autolink/helpers"
56
require 'erb'
67
require 'cgi'
78
require 'active_support/core_ext/class/attribute_accessors'
8-
require 'active_support'
99
require 'action_pack'
1010
require 'action_view/helpers/capture_helper'
1111
require 'action_view/helpers/sanitize_helper'
1212
require 'action_view/helpers/url_helper'
1313
require 'action_view/helpers/tag_helper'
1414
require 'active_support/core_ext/module/attribute_accessors'
1515
require 'active_support/core_ext/string/encoding'
16-
require 'action_dispatch/testing/assertions/dom'
16+
require 'action_dispatch/testing/assertions'
1717
require 'action_view/helpers/text_helper'
1818
require 'action_view/helpers/output_safety_helper'
1919

0 commit comments

Comments
 (0)