Skip to content

Commit

Permalink
Merge branch 'master' of github.com:tenderlove/rails_autolink
Browse files Browse the repository at this point in the history
* 'master' of github.com:tenderlove/rails_autolink:
  bumping to v1.0.2
  Change code structure. Easy testing.
  Use gsub method on String instead of SafeBuffer. Fix for incompatibility with Rails 3.1.0.rc2.
  oops!
  • Loading branch information
tenderlove committed Oct 6, 2011
2 parents 9d17e2c + 25f7dae commit f07793c
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 144 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.rdoc
@@ -1,3 +1,7 @@
=== 1.0.2 / 2011-06-18

* Compatibility with rails 3.1.0.rc4

=== 1.0.0 / 2011-05-02

* 1 major enhancement
Expand Down
1 change: 1 addition & 0 deletions Manifest.txt
Expand Up @@ -5,4 +5,5 @@ Manifest.txt
README.rdoc
Rakefile
lib/rails_autolink.rb
lib/rails_autolink/helpers.rb
test/test_rails_autolink.rb
2 changes: 2 additions & 0 deletions Rakefile
Expand Up @@ -10,6 +10,8 @@ Hoe.plugin :git # `gem install hoe-git`

Hoe.spec 'rails_autolink' do
developer('Aaron Patterson', 'aaron@tenderlovemaking.com')
developer('Juanjo Bazan', 'jjbazan@gmail.com')
developer('Akira Matsuda', 'ronnie@dio.jp')
self.readme_file = 'README.rdoc'
self.history_file = 'CHANGELOG.rdoc'
self.extra_rdoc_files = FileList['*.rdoc']
Expand Down
144 changes: 3 additions & 141 deletions lib/rails_autolink.rb
@@ -1,148 +1,10 @@
module RailsAutolink
VERSION = '1.0.1'
VERSION = '1.0.2'

class Railtie < ::Rails::Railtie
initializer 'nested_form' do |app|
initializer 'rails_autolink' do |app|
ActiveSupport.on_load(:action_view) do
require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/array/extract_options'
require 'active_support/core_ext/hash/reverse_merge'
require 'active_support/core_ext/hash/keys'

module ::ActionView
module Helpers # :nodoc:
module TextHelper
# Turns all URLs and e-mail addresses into clickable links. The <tt>:link</tt> option
# will limit what should be linked. You can add HTML attributes to the links using
# <tt>:html</tt>. Possible values for <tt>:link</tt> are <tt>:all</tt> (default),
# <tt>:email_addresses</tt>, and <tt>:urls</tt>. If a block is given, each URL and
# e-mail address is yielded and the result is used as the link text. By default the
# text given is sanitized, you can override this behaviour setting the
# <tt>:sanitize</tt> option to false.
#
# ==== Examples
# auto_link("Go to http://www.rubyonrails.org and say hello to david@loudthinking.com")
# # => "Go to <a href=\"http://www.rubyonrails.org\">http://www.rubyonrails.org</a> and
# # say hello to <a href=\"mailto:david@loudthinking.com\">david@loudthinking.com</a>"
#
# auto_link("Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com", :link => :urls)
# # => "Visit <a href=\"http://www.loudthinking.com/\">http://www.loudthinking.com/</a>
# # or e-mail david@loudthinking.com"
#
# auto_link("Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com", :link => :email_addresses)
# # => "Visit http://www.loudthinking.com/ or e-mail <a href=\"mailto:david@loudthinking.com\">david@loudthinking.com</a>"
#
# post_body = "Welcome to my new blog at http://www.myblog.com/. Please e-mail me at me@email.com."
# auto_link(post_body, :html => { :target => '_blank' }) do |text|
# truncate(text, :length => 15)
# end
# # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\" target=\"_blank\">http://www.m...</a>.
# Please e-mail me at <a href=\"mailto:me@email.com\">me@email.com</a>."
#
#
# You can still use <tt>auto_link</tt> with the old API that accepts the
# +link+ as its optional second parameter and the +html_options+ hash
# as its optional third parameter:
# post_body = "Welcome to my new blog at http://www.myblog.com/. Please e-mail me at me@email.com."
# auto_link(post_body, :urls)
# # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\">http://www.myblog.com</a>.
# Please e-mail me at me@email.com."
#
# auto_link(post_body, :all, :target => "_blank")
# # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\" target=\"_blank\">http://www.myblog.com</a>.
# Please e-mail me at <a href=\"mailto:me@email.com\">me@email.com</a>."
def auto_link(text, *args, &block)#link = :all, html = {}, &block)
return ''.html_safe if text.blank?

options = args.size == 2 ? {} : args.extract_options! # this is necessary because the old auto_link API has a Hash as its last parameter
unless args.empty?
options[:link] = args[0] || :all
options[:html] = args[1] || {}
end
options.reverse_merge!(:link => :all, :html => {})
text = sanitize(text) unless options[:sanitize] == false
case options[:link].to_sym
when :all then auto_link_email_addresses(auto_link_urls(text, options[:html], options, &block), options[:html], &block)
when :email_addresses then auto_link_email_addresses(text, options[:html], &block)
when :urls then auto_link_urls(text, options[:html], options, &block)
end
end

private

AUTO_LINK_RE = %r{
(?: ([0-9A-Za-z+.:-]+:)// | www\. )
[^\s<]+
}x

# regexps for determining context, used high-volume
AUTO_LINK_CRE = [/<[^>]+$/, /^[^>]*>/, /<a\b.*?>/i, /<\/a>/i]

AUTO_EMAIL_RE = /[\w.!#\$%+-]+@[\w-]+(?:\.[\w-]+)+/

BRACKETS = { ']' => '[', ')' => '(', '}' => '{' }

# 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 = {}, options = {})
link_attributes = html_options.stringify_keys
text.gsub(AUTO_LINK_RE) do
scheme, href = $1, $&
punctuation = []

if auto_linked?($`, $')
# do not change string; URL is already linked
href
else
# don't include trailing punctuation character as part of the URL
while href.sub!(/[^\w\/-]$/, '')
punctuation.push $&
if opening = BRACKETS[punctuation.last] and href.scan(opening).size > href.scan(punctuation.last).size
href << punctuation.pop
break
end
end

link_text = block_given?? yield(href) : href
href = 'http://' + href unless scheme

unless options[:sanitize] == false
link_text = sanitize(link_text)
href = sanitize(href)
end
content_tag(:a, link_text, link_attributes.merge('href' => href), !!options[:sanitize]) + punctuation.reverse.join('')
end
end
end

# 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 = {}, options = {})
text.gsub(AUTO_EMAIL_RE) do
text = $&

if auto_linked?($`, $')
text.html_safe
else
display_text = (block_given?) ? yield(text) : text

unless options[:sanitize] == false
text = sanitize(text)
display_text = sanitize(display_text) unless text == display_text
end
mail_to text, display_text, html_options
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
require 'rails_autolink/helpers'
end
end
end
Expand Down
150 changes: 150 additions & 0 deletions lib/rails_autolink/helpers.rb
@@ -0,0 +1,150 @@
module RailsAutolink
require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/array/extract_options'
require 'active_support/core_ext/hash/reverse_merge'
require 'active_support/core_ext/hash/keys'

module ::ActionView
module Helpers # :nodoc:
module TextHelper
# Turns all URLs and e-mail addresses into clickable links. The <tt>:link</tt> option
# will limit what should be linked. You can add HTML attributes to the links using
# <tt>:html</tt>. Possible values for <tt>:link</tt> are <tt>:all</tt> (default),
# <tt>:email_addresses</tt>, and <tt>:urls</tt>. If a block is given, each URL and
# e-mail address is yielded and the result is used as the link text. By default the
# text given is sanitized, you can override this behaviour setting the
# <tt>:sanitize</tt> option to false.
#
# ==== Examples
# auto_link("Go to http://www.rubyonrails.org and say hello to david@loudthinking.com")
# # => "Go to <a href=\"http://www.rubyonrails.org\">http://www.rubyonrails.org</a> and
# # say hello to <a href=\"mailto:david@loudthinking.com\">david@loudthinking.com</a>"
#
# auto_link("Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com", :link => :urls)
# # => "Visit <a href=\"http://www.loudthinking.com/\">http://www.loudthinking.com/</a>
# # or e-mail david@loudthinking.com"
#
# auto_link("Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com", :link => :email_addresses)
# # => "Visit http://www.loudthinking.com/ or e-mail <a href=\"mailto:david@loudthinking.com\">david@loudthinking.com</a>"
#
# post_body = "Welcome to my new blog at http://www.myblog.com/. Please e-mail me at me@email.com."
# auto_link(post_body, :html => { :target => '_blank' }) do |text|
# truncate(text, :length => 15)
# end
# # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\" target=\"_blank\">http://www.m...</a>.
# Please e-mail me at <a href=\"mailto:me@email.com\">me@email.com</a>."
#
#
# You can still use <tt>auto_link</tt> with the old API that accepts the
# +link+ as its optional second parameter and the +html_options+ hash
# as its optional third parameter:
# post_body = "Welcome to my new blog at http://www.myblog.com/. Please e-mail me at me@email.com."
# auto_link(post_body, :urls)
# # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\">http://www.myblog.com</a>.
# Please e-mail me at me@email.com."
#
# auto_link(post_body, :all, :target => "_blank")
# # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\" target=\"_blank\">http://www.myblog.com</a>.
# Please e-mail me at <a href=\"mailto:me@email.com\">me@email.com</a>."
def auto_link(text, *args, &block)#link = :all, html = {}, &block)
return ''.html_safe if text.blank?

options = args.size == 2 ? {} : args.extract_options! # this is necessary because the old auto_link API has a Hash as its last parameter
unless args.empty?
options[:link] = args[0] || :all
options[:html] = args[1] || {}
end
options.reverse_merge!(:link => :all, :html => {})
sanitize = (options[:sanitize] != false)
text = conditional_sanitize(text, sanitize).to_str
case options[:link].to_sym
when :all then conditional_html_safe(auto_link_email_addresses(auto_link_urls(text, options[:html], options, &block), options[:html], &block), sanitize)
when :email_addresses then conditional_html_safe(auto_link_email_addresses(text, options[:html], &block), sanitize)
when :urls then conditional_html_safe(auto_link_urls(text, options[:html], options, &block), sanitize)
end
end

private

AUTO_LINK_RE = %r{
(?: ([0-9A-Za-z+.:-]+:)// | www\. )
[^\s<]+
}x

# regexps for determining context, used high-volume
AUTO_LINK_CRE = [/<[^>]+$/, /^[^>]*>/, /<a\b.*?>/i, /<\/a>/i]

AUTO_EMAIL_RE = /[\w.!#\$%+-]+@[\w-]+(?:\.[\w-]+)+/

BRACKETS = { ']' => '[', ')' => '(', '}' => '{' }

# 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 = {}, options = {})
link_attributes = html_options.stringify_keys
text.gsub(AUTO_LINK_RE) do
scheme, href = $1, $&
punctuation = []

if auto_linked?($`, $')
# do not change string; URL is already linked
href
else
# don't include trailing punctuation character as part of the URL
while href.sub!(/[^\w\/-]$/, '')
punctuation.push $&
if opening = BRACKETS[punctuation.last] and href.scan(opening).size > href.scan(punctuation.last).size
href << punctuation.pop
break
end
end

link_text = block_given?? yield(href) : href
href = 'http://' + href unless scheme

unless options[:sanitize] == false
link_text = sanitize(link_text)
href = sanitize(href)
end
content_tag(:a, link_text, link_attributes.merge('href' => href), !!options[:sanitize]) + punctuation.reverse.join('')
end
end
end

# 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 = {}, options = {})
text.gsub(AUTO_EMAIL_RE) do
text = $&

if auto_linked?($`, $')
text.html_safe
else
display_text = (block_given?) ? yield(text) : text

unless options[:sanitize] == false
text = sanitize(text)
display_text = sanitize(display_text) unless text == display_text
end
mail_to text, display_text, html_options
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

def conditional_sanitize(target, condition)
condition ? sanitize(target) : target
end

def conditional_html_safe(target, condition)
condition ? target.html_safe : target
end
end
end
end
end
6 changes: 3 additions & 3 deletions test/test_rails_autolink.rb
@@ -1,19 +1,19 @@
# encoding: utf-8

require "minitest/autorun"
require "rails_autolink"
require "rails"
require "rails_autolink/helpers"
require 'erb'
require 'cgi'
require 'active_support/core_ext/class/attribute_accessors'
require 'active_support'
require 'action_pack'
require 'action_view/helpers/capture_helper'
require 'action_view/helpers/sanitize_helper'
require 'action_view/helpers/url_helper'
require 'action_view/helpers/tag_helper'
require 'active_support/core_ext/module/attribute_accessors'
require 'active_support/core_ext/string/encoding'
require 'action_dispatch/testing/assertions/dom'
require 'action_dispatch/testing/assertions'
require 'action_view/helpers/text_helper'
require 'action_view/helpers/output_safety_helper'

Expand Down

0 comments on commit f07793c

Please sign in to comment.