diff options
-rw-r--r-- | actionpack/lib/action_view/helpers/text_helper.rb | 16 | ||||
-rw-r--r-- | activesupport/CHANGELOG | 2 | ||||
-rw-r--r-- | activesupport/lib/active_support/core_ext/string/filters.rb | 33 | ||||
-rw-r--r-- | activesupport/test/core_ext/string_ext_test.rb | 29 |
4 files changed, 69 insertions, 11 deletions
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 41423d4e2e..860c1de6af 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/object/blank' +require 'active_support/core_ext/string/filters' require 'action_view/helpers/tag_helper' module ActionView @@ -42,7 +43,7 @@ module ActionView # ==== Examples # # truncate("Once upon a time in a world far far away") - # # => Once upon a time in a world... + # # => Once upon a time in a worl... # # truncate("Once upon a time in a world far far away", :separator => ' ') # # => Once upon a time in a world... @@ -50,9 +51,6 @@ module ActionView # truncate("Once upon a time in a world far far away", :length => 14) # # => Once upon a... # - # truncate("And they found that many people were sleeping better.", :length => 25, "(clipped)") - # # => And they found t(clipped) - # # truncate("And they found that many people were sleeping better.", :omission => "... (continued)", :length => 25) # # => And they f... (continued) # @@ -73,14 +71,10 @@ module ActionView options[:length] = args[0] || 30 options[:omission] = args[1] || "..." end - options.reverse_merge!(:length => 30, :omission => "...") - if text - l = options[:length] - options[:omission].mb_chars.length - chars = text.mb_chars - stop = options[:separator] ? (chars.rindex(options[:separator].mb_chars, l) || l) : l - (chars.length > options[:length] ? chars[0...stop] + options[:omission] : text).to_s - end + options.reverse_merge!(:length => 30) + + text.truncate(options.delete(:length), options) if text end # Highlights one or more +phrases+ everywhere in +text+ by inserting it into diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 0a25ad0406..d853788e00 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.0.0 [beta 4/release candidate] (unreleased)* +* Extracted String#truncate from TextHelper#truncate [DHH] + * Ruby 1.9: support UTF-8 case folding. #4595 [Norman Clarke] * Renames Array#rand -> Array#random_element. [Santiago Pastorino, Rizwan Reza] diff --git a/activesupport/lib/active_support/core_ext/string/filters.rb b/activesupport/lib/active_support/core_ext/string/filters.rb index 6fda7efef5..cdd86a836f 100644 --- a/activesupport/lib/active_support/core_ext/string/filters.rb +++ b/activesupport/lib/active_support/core_ext/string/filters.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/string/multibyte' + class String # Returns the string, first removing all whitespace on both ends of # the string, and then changing remaining consecutive whitespace @@ -17,4 +19,35 @@ class String gsub!(/\s+/, ' ') self end + + # Truncates a given +text+ after a given <tt>length</tt> if +text+ is longer than <tt>length</tt>. + # The last characters will be replaced with the <tt>:omission</tt> (defaults to "...") + # for a total length not exceeding <tt>:length</tt>. + # + # Pass a <tt>:separator</tt> to truncate +text+ at a natural break. + # + # ==== Examples + # + # "Once upon a time in a world far far away".truncate(30) + # # => Once upon a time in a worl... + # + # "Once upon a time in a world far far away".truncate(30, :separator => ' ') + # # => Once upon a time in a world... + # + # "Once upon a time in a world far far away".truncate(14) + # # => Once upon a... + # + # "And they found that many people were sleeping better.".truncate(25, :omission => "... (continued)") + # # => And they f... (continued) + def truncate(length, options = {}) + text = self.dup + options[:omission] ||= "..." + + length_with_room_for_omission = length - options[:omission].mb_chars.length + chars = text.mb_chars + stop = options[:separator] ? + (chars.rindex(options[:separator].mb_chars, length_with_room_for_omission) || length_with_room_for_omission) : length_with_room_for_omission + + (chars.length > length ? chars[0...stop] + options[:omission] : text).to_s + end end diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index 759b0ddcd6..d9702dd9ff 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -210,6 +210,35 @@ class StringInflectionsTest < Test::Unit::TestCase # And changes the original string: assert_equal original, expected end + + def test_truncate + assert_equal "Hello World!", "Hello World!".truncate(12) + assert_equal "Hello Wor...", "Hello World!!".truncate(12) + end + + def test_truncate_with_omission_and_seperator + assert_equal "Hello[...]", "Hello World!".truncate(10, :omission => "[...]") + assert_equal "Hello[...]", "Hello Big World!".truncate(13, :omission => "[...]", :separator => ' ') + assert_equal "Hello Big[...]", "Hello Big World!".truncate(14, :omission => "[...]", :separator => ' ') + assert_equal "Hello Big[...]", "Hello Big World!".truncate(15, :omission => "[...]", :separator => ' ') + end + + if RUBY_VERSION < '1.9.0' + def test_truncate_multibyte + with_kcode 'none' do + assert_equal "\354\225\210\353\205\225\355...", "\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224".truncate(10) + end + with_kcode 'u' do + assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...", + "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".truncate(10) + end + end + else + def test_truncate_multibyte + assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...".force_encoding('UTF-8'), + "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".force_encoding('UTF-8').truncate(10) + end + end end class StringBehaviourTest < Test::Unit::TestCase |