From df01202fe83d175a832cb81c6f294ba6ebfb8ead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baz=C3=A1n?= Date: Sat, 18 Jun 2011 14:09:05 +0200 Subject: [PATCH] Change code structure. Easy testing. --- lib/rails_autolink.rb | 149 +-------------------------------- lib/rails_autolink/helpers.rb | 150 ++++++++++++++++++++++++++++++++++ test/test_rails_autolink.rb | 6 +- 3 files changed, 154 insertions(+), 151 deletions(-) create mode 100644 lib/rails_autolink/helpers.rb diff --git a/lib/rails_autolink.rb b/lib/rails_autolink.rb index c291814..244ebb0 100644 --- a/lib/rails_autolink.rb +++ b/lib/rails_autolink.rb @@ -4,154 +4,7 @@ module RailsAutolink class Railtie < ::Rails::Railtie 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 :link option - # will limit what should be linked. You can add HTML attributes to the links using - # :html. Possible values for :link are :all (default), - # :email_addresses, and :urls. 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 - # :sanitize option to false. - # - # ==== Examples - # auto_link("Go to http://www.rubyonrails.org and say hello to david@loudthinking.com") - # # => "Go to http://www.rubyonrails.org and - # # say hello to david@loudthinking.com" - # - # auto_link("Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com", :link => :urls) - # # => "Visit http://www.loudthinking.com/ - # # 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 david@loudthinking.com" - # - # 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 http://www.m.... - # Please e-mail me at me@email.com." - # - # - # You can still use auto_link 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 http://www.myblog.com. - # Please e-mail me at me@email.com." - # - # auto_link(post_body, :all, :target => "_blank") - # # => "Welcome to my new blog at http://www.myblog.com. - # Please e-mail me at me@email.com." - 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 = [/<[^>]+$/, /^[^>]*>/, //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 + require 'rails_autolink/helpers' end end end diff --git a/lib/rails_autolink/helpers.rb b/lib/rails_autolink/helpers.rb new file mode 100644 index 0000000..b880be7 --- /dev/null +++ b/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 :link option + # will limit what should be linked. You can add HTML attributes to the links using + # :html. Possible values for :link are :all (default), + # :email_addresses, and :urls. 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 + # :sanitize option to false. + # + # ==== Examples + # auto_link("Go to http://www.rubyonrails.org and say hello to david@loudthinking.com") + # # => "Go to http://www.rubyonrails.org and + # # say hello to david@loudthinking.com" + # + # auto_link("Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com", :link => :urls) + # # => "Visit http://www.loudthinking.com/ + # # 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 david@loudthinking.com" + # + # 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 http://www.m.... + # Please e-mail me at me@email.com." + # + # + # You can still use auto_link 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 http://www.myblog.com. + # Please e-mail me at me@email.com." + # + # auto_link(post_body, :all, :target => "_blank") + # # => "Welcome to my new blog at http://www.myblog.com. + # Please e-mail me at me@email.com." + 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 = [/<[^>]+$/, /^[^>]*>/, //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 \ No newline at end of file diff --git a/test/test_rails_autolink.rb b/test/test_rails_autolink.rb index 7b4c82a..2623048 100644 --- a/test/test_rails_autolink.rb +++ b/test/test_rails_autolink.rb @@ -1,11 +1,11 @@ # 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' @@ -13,7 +13,7 @@ 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'