diff options
author | Carlos Antonio da Silva <carlosantoniodasilva@gmail.com> | 2012-09-08 05:02:18 -0700 |
---|---|---|
committer | Carlos Antonio da Silva <carlosantoniodasilva@gmail.com> | 2012-09-08 05:02:18 -0700 |
commit | bf27f6b2f711cc839b023174884c5c3fe3c6dd8d (patch) | |
tree | b61540a349528a5f908ce87a29f95b512ce9aaf0 | |
parent | 63730271127f4b1540fcd469d42b46018bd13ab4 (diff) | |
parent | 963c50eca87373bed403358c076b377ad62454ef (diff) | |
download | rails-bf27f6b2f711cc839b023174884c5c3fe3c6dd8d.tar.gz rails-bf27f6b2f711cc839b023174884c5c3fe3c6dd8d.tar.bz2 rails-bf27f6b2f711cc839b023174884c5c3fe3c6dd8d.zip |
Merge pull request #7189 from GCorbel/excerpt_with_separation
Add a separator option for the excerpt function.
-rw-r--r-- | actionpack/CHANGELOG.md | 2 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/text_helper.rb | 60 | ||||
-rw-r--r-- | actionpack/test/template/text_helper_test.rb | 13 |
3 files changed, 64 insertions, 11 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 1232370439..4cf653722f 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,5 +1,7 @@ ## Rails 4.0.0 (unreleased) ## +* Add `separation` option for `ActionView::Helpers::TextHelper.excerpt`. *Guirec Corbel* + * Added controller-level etag additions that will be part of the action etag computation *Jeremy Kemper/DHH* class InvoicesController < ApplicationController diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 0f599d5f41..069969a710 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -126,8 +126,9 @@ module ActionView # Extracts an excerpt from +text+ that matches the first instance of +phrase+. # The <tt>:radius</tt> option expands the excerpt on each side of the first occurrence of +phrase+ by the number of characters # defined in <tt>:radius</tt> (which defaults to 100). If the excerpt radius overflows the beginning or end of the +text+, - # then the <tt>:omission</tt> option (which defaults to "...") will be prepended/appended accordingly. The resulting string - # will be stripped in any case. If the +phrase+ isn't found, nil is returned. + # then the <tt>:omission</tt> option (which defaults to "...") will be prepended/appended accordingly. The + # <tt>:separator</tt> enable to choose the delimation. The resulting string will be stripped in any case. If the +phrase+ + # isn't found, nil is returned. # # excerpt('This is an example', 'an', :radius => 5) # # => ...s is an exam... @@ -143,21 +144,37 @@ module ActionView # # excerpt('This is also an example', 'an', :radius => 8, :omission => '<chop> ') # # => <chop> is also an example + # + # excerpt('This is a very beautiful morning', 'very', :separator => ' ', :radius => 1) + # # => ...a very beautiful... def excerpt(text, phrase, options = {}) return unless text && phrase - radius = options.fetch(:radius, 100) - omission = options.fetch(:omission, "...") + radius = options.fetch(:radius, 100) + omission = options.fetch(:omission, "...") + separator = options.fetch(:separator, "") + + phrase = Regexp.escape(phrase) + regex = /#{phrase}/i + + return unless matches = text.match(regex) + phrase = matches[0] + + text.split(separator).each do |value| + if value.match(regex) + regex = phrase = value + break + end + end - phrase = Regexp.escape(phrase) - return unless found_pos = text =~ /(#{phrase})/i + first_part, second_part = text.split(regex, 2) - start_pos = [ found_pos - radius, 0 ].max - end_pos = [ [ found_pos + phrase.length + radius - 1, 0].max, text.length ].min + options = options.merge(:part_position => :first) + prefix, first_part = cut_part(first_part, options) - prefix = start_pos > 0 ? omission : "" - postfix = end_pos < text.length - 1 ? omission : "" + options = options.merge(:part_position => :second) + postfix, second_part = cut_part(second_part, options) - prefix + text[start_pos..end_pos].strip + postfix + prefix + (first_part + separator + phrase + separator + second_part).strip + postfix end # Attempts to pluralize the +singular+ word unless +count+ is 1. If @@ -402,6 +419,27 @@ module ActionView t.gsub!(/([^\n]\n)(?=[^\n])/, '\1<br />') || t end end + + def cut_part(part, options) + radius = options.fetch(:radius, 100) + omission = options.fetch(:omission, "...") + separator = options.fetch(:separator, "") + part_position = options.fetch(:part_position) + + return "", "" unless part + + part = part.split(separator) + part.delete("") + affix = part.size > radius ? omission : "" + part = if part_position == :first + drop_index = [part.length - radius, 0].max + part.drop(drop_index).join(separator) + else + part.first(radius).join(separator) + end + + return affix, part + end end end end diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb index c0f694b2bf..4525efe73c 100644 --- a/actionpack/test/template/text_helper_test.rb +++ b/actionpack/test/template/text_helper_test.rb @@ -303,6 +303,19 @@ class TextHelperTest < ActionView::TestCase assert_equal options, passed_options end + def test_excerpt_with_separator + options = { :separator => ' ', :radius => 1 } + assert_equal('...a very beautiful...', excerpt('This is a very beautiful morning', 'very', options)) + assert_equal('This is...', excerpt('This is a very beautiful morning', 'this', options)) + assert_equal('...beautiful morning', excerpt('This is a very beautiful morning', 'morning', options)) + + options = { :separator => "\n", :radius => 0 } + assert_equal("...very long...", excerpt("my very\nvery\nvery long\nstring", 'long', options)) + + options = { :separator => "\n", :radius => 1 } + assert_equal("...very\nvery long\nstring", excerpt("my very\nvery\nvery long\nstring", 'long', options)) + end + def test_word_wrap assert_equal("my very very\nvery long\nstring", word_wrap("my very very very long string", :line_width => 15)) end |