aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib
diff options
context:
space:
mode:
authorGuirec Corbel <guirec.corbel@gmail.com>2012-07-28 17:34:36 -0400
committerGCorbel <guirec.corbel@gmail.com>2012-09-08 07:24:17 -0400
commit963c50eca87373bed403358c076b377ad62454ef (patch)
tree7a1d91408fdc3435b8a164250d6bfb4b4e5031c0 /actionpack/lib
parentf415475621c79cbc2d93e1ecf10805a4100a5d43 (diff)
downloadrails-963c50eca87373bed403358c076b377ad62454ef.tar.gz
rails-963c50eca87373bed403358c076b377ad62454ef.tar.bz2
rails-963c50eca87373bed403358c076b377ad62454ef.zip
Add a separation option for the excerpt function
The separation option enable to keep entire words, lines or anything. To split by line, like github, we can set the separation option as \n. To split by word, like google, we can set the separation option as " ". The radius option represent the number of lines or words we want to have in the result. The default behaviour is the same. If we don't set the separation option, it split the text any where.
Diffstat (limited to 'actionpack/lib')
-rw-r--r--actionpack/lib/action_view/helpers/text_helper.rb60
1 files changed, 49 insertions, 11 deletions
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