Skip to content

Commit 9d17e2c

Browse files
committed
Merge branch 'master' of github.com:tenderlove/rails_autolink
* 'master' of github.com:tenderlove/rails_autolink: shall I build a gem? make it work with 3.1.0.beta1 ensure the whole freedom patching to be loaded AFTER intializing AV Readme return sanitized strings remove local tenderloving-paths from gemfile Conflicts: Manifest.txt
2 parents 3683d21 + 1895cec commit 9d17e2c

File tree

5 files changed

+180
-148
lines changed

5 files changed

+180
-148
lines changed

Gemfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
source 'http://rubygems.org'
22

3-
gem 'rails', :path => '/Users/aaron/git/rails'
4-
gem 'arel', :path => '/Users/aaron/git/arel'
5-
gem 'rack', :path => '/Users/aaron/git/rack'
3+
gem 'rails'
4+
gem 'arel'
5+
gem 'rack'
66
gem 'hoe'
77
gem 'minitest'
88

README.rdoc

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ This is an extraction of the `auto_link` method from rails. The `auto_link`
88
method was removed from Rails in version Rails 3.1. This gem is meant to
99
bridge the gap for people migrating.
1010

11-
== FEATURES/PROBLEMS:
11+
== FEATURES:
1212

13-
* May not be safe!
13+
By default auto_link returns sanitized html_safe strings.
14+
This behaviour can be overriden setting the <tt>:sanitize</tt> option to false
15+
(thus making it insecure if you don't have the content under control).
1416

1517
== SYNOPSIS:
1618

@@ -27,6 +29,12 @@ bridge the gap for people migrating.
2729
auto_link("Visit http://www.loudthinking.com/ or e-mail [email protected]", :link => :email_addresses)
2830
# => "Visit http://www.loudthinking.com/ or e-mail <a href=\"mailto:[email protected]\">[email protected]</a>"
2931

32+
auto_link("Go to http://www.rubyonrails.org <script>Malicious code!</script>")
33+
# => "Go to <a href=\"http://www.rubyonrails.org\">http://www.rubyonrails.org</a> "
34+
35+
auto_link("Go to http://www.rubyonrails.org <script>alert('Script!')</script>", :sanitize => false)
36+
# => "Go to <a href=\"http://www.rubyonrails.org\">http://www.rubyonrails.org</a> <script>alert('Script!')</script>"
37+
3038
post_body = "Welcome to my new blog at http://www.myblog.com/. Please e-mail me at [email protected]."
3139
auto_link(post_body, :html => { :target => '_blank' }) do |text|
3240
truncate(text, :length => 15)
@@ -35,11 +43,11 @@ bridge the gap for people migrating.
3543

3644
== REQUIREMENTS:
3745

38-
* rails
46+
* rails >= 3.1
3947

4048
== INSTALL:
4149

42-
* gem install rails
50+
* gem install rails_autolink
4351

4452
== LICENSE:
4553

Rakefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Hoe.spec 'rails_autolink' do
1313
self.readme_file = 'README.rdoc'
1414
self.history_file = 'CHANGELOG.rdoc'
1515
self.extra_rdoc_files = FileList['*.rdoc']
16-
self.extra_deps << ['rails', '~> 3.1.0']
16+
self.extra_deps << ['rails', '~> 3.1.0.a']
1717
end
1818

1919
# vim: syntax=ruby

lib/rails_autolink.rb

Lines changed: 137 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -1,141 +1,149 @@
1-
require 'active_support/core_ext/object/blank'
2-
require 'active_support/core_ext/array/extract_options'
3-
require 'active_support/core_ext/hash/reverse_merge'
4-
require 'active_support/core_ext/hash/keys'
5-
61
module RailsAutolink
7-
VERSION = '1.0.0'
8-
end
9-
10-
module ActionView
11-
module Helpers # :nodoc:
12-
module TextHelper
13-
# Turns all URLs and e-mail addresses into clickable links. The <tt>:link</tt> option
14-
# will limit what should be linked. You can add HTML attributes to the links using
15-
# <tt>:html</tt>. Possible values for <tt>:link</tt> are <tt>:all</tt> (default),
16-
# <tt>:email_addresses</tt>, and <tt>:urls</tt>. If a block is given, each URL and
17-
# e-mail address is yielded and the result is used as the link text.
18-
#
19-
# ==== Examples
20-
# auto_link("Go to http://www.rubyonrails.org and say hello to [email protected]")
21-
# # => "Go to <a href=\"http://www.rubyonrails.org\">http://www.rubyonrails.org</a> and
22-
# # say hello to <a href=\"mailto:[email protected]\">[email protected]</a>"
23-
#
24-
# auto_link("Visit http://www.loudthinking.com/ or e-mail [email protected]", :link => :urls)
25-
# # => "Visit <a href=\"http://www.loudthinking.com/\">http://www.loudthinking.com/</a>
26-
# # or e-mail [email protected]"
27-
#
28-
# auto_link("Visit http://www.loudthinking.com/ or e-mail [email protected]", :link => :email_addresses)
29-
# # => "Visit http://www.loudthinking.com/ or e-mail <a href=\"mailto:[email protected]\">[email protected]</a>"
30-
#
31-
# post_body = "Welcome to my new blog at http://www.myblog.com/. Please e-mail me at [email protected]."
32-
# auto_link(post_body, :html => { :target => '_blank' }) do |text|
33-
# truncate(text, :length => 15)
34-
# end
35-
# # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\" target=\"_blank\">http://www.m...</a>.
36-
# Please e-mail me at <a href=\"mailto:[email protected]\">[email protected]</a>."
37-
#
38-
#
39-
# You can still use <tt>auto_link</tt> with the old API that accepts the
40-
# +link+ as its optional second parameter and the +html_options+ hash
41-
# as its optional third parameter:
42-
# post_body = "Welcome to my new blog at http://www.myblog.com/. Please e-mail me at [email protected]."
43-
# auto_link(post_body, :urls)
44-
# # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\">http://www.myblog.com</a>.
45-
# Please e-mail me at [email protected]."
46-
#
47-
# auto_link(post_body, :all, :target => "_blank")
48-
# # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\" target=\"_blank\">http://www.myblog.com</a>.
49-
# Please e-mail me at <a href=\"mailto:[email protected]\">[email protected]</a>."
50-
def auto_link(text, *args, &block)#link = :all, html = {}, &block)
51-
return '' if text.blank?
52-
53-
options = args.size == 2 ? {} : args.extract_options! # this is necessary because the old auto_link API has a Hash as its last parameter
54-
unless args.empty?
55-
options[:link] = args[0] || :all
56-
options[:html] = args[1] || {}
57-
end
58-
options.reverse_merge!(:link => :all, :html => {})
59-
60-
case options[:link].to_sym
61-
when :all then auto_link_email_addresses(auto_link_urls(text, options[:html], options, &block), options[:html], &block)
62-
when :email_addresses then auto_link_email_addresses(text, options[:html], &block)
63-
when :urls then auto_link_urls(text, options[:html], options, &block)
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
2+
VERSION = '1.0.1'
3+
4+
class Railtie < ::Rails::Railtie
5+
initializer 'nested_form' do |app|
6+
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+
text = sanitize(text) unless options[:sanitize] == false
64+
case options[:link].to_sym
65+
when :all then auto_link_email_addresses(auto_link_urls(text, options[:html], options, &block), options[:html], &block)
66+
when :email_addresses then auto_link_email_addresses(text, options[:html], &block)
67+
when :urls then auto_link_urls(text, options[:html], options, &block)
9968
end
10069
end
10170

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 = $&
71+
private
72+
73+
AUTO_LINK_RE = %r{
74+
(?: ([0-9A-Za-z+.:-]+:)// | www\. )
75+
[^\s<]+
76+
}x
77+
78+
# regexps for determining context, used high-volume
79+
AUTO_LINK_CRE = [/<[^>]+$/, /^[^>]*>/, /<a\b.*?>/i, /<\/a>/i]
80+
81+
AUTO_EMAIL_RE = /[\w.!#\$%+-]+@[\w-]+(?:\.[\w-]+)+/
82+
83+
BRACKETS = { ']' => '[', ')' => '(', '}' => '{' }
84+
85+
# Turns all urls into clickable links. If a block is given, each url
86+
# is yielded and the result is used as the link text.
87+
def auto_link_urls(text, html_options = {}, options = {})
88+
link_attributes = html_options.stringify_keys
89+
text.gsub(AUTO_LINK_RE) do
90+
scheme, href = $1, $&
91+
punctuation = []
92+
93+
if auto_linked?($`, $')
94+
# do not change string; URL is already linked
95+
href
96+
else
97+
# don't include trailing punctuation character as part of the URL
98+
while href.sub!(/[^\w\/-]$/, '')
99+
punctuation.push $&
100+
if opening = BRACKETS[punctuation.last] and href.scan(opening).size > href.scan(punctuation.last).size
101+
href << punctuation.pop
102+
break
103+
end
104+
end
105+
106+
link_text = block_given?? yield(href) : href
107+
href = 'http://' + href unless scheme
108+
109+
unless options[:sanitize] == false
110+
link_text = sanitize(link_text)
111+
href = sanitize(href)
112+
end
113+
content_tag(:a, link_text, link_attributes.merge('href' => href), !!options[:sanitize]) + punctuation.reverse.join('')
114+
end
115+
end
116+
end
119117

120-
if auto_linked?($`, $')
121-
text.html_safe
122-
else
123-
display_text = (block_given?) ? yield(text) : text
118+
# Turns all email addresses into clickable links. If a block is given,
119+
# each email is yielded and the result is used as the link text.
120+
def auto_link_email_addresses(text, html_options = {}, options = {})
121+
text.gsub(AUTO_EMAIL_RE) do
122+
text = $&
123+
124+
if auto_linked?($`, $')
125+
text.html_safe
126+
else
127+
display_text = (block_given?) ? yield(text) : text
128+
129+
unless options[:sanitize] == false
130+
text = sanitize(text)
131+
display_text = sanitize(display_text) unless text == display_text
132+
end
133+
mail_to text, display_text, html_options
134+
end
135+
end
136+
end
124137

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
138+
# Detects already linked context or position in the middle of a tag
139+
def auto_linked?(left, right)
140+
(left =~ AUTO_LINK_CRE[0] and right =~ AUTO_LINK_CRE[1]) or
141+
(left.rindex(AUTO_LINK_CRE[2]) and $' !~ AUTO_LINK_CRE[3])
142+
end
130143
end
131144
end
132145
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
146+
end
139147
end
140148
end
141149
end

0 commit comments

Comments
 (0)