Make truncate() Unicode-aware

master
Jacques Distler 2009-12-14 17:41:28 -06:00
parent 2c5e5a0015
commit d3e79ea84a
4 changed files with 41 additions and 9 deletions

View File

@ -1,5 +1,6 @@
# The methods added to this helper will be available to all templates in the application.
module ApplicationHelper
require 'stringsupport'
# Accepts a container (hash, array, enumerable, your type) and returns a string of option tags. Given a container
# where the elements respond to first and last (such as a two-element array), the "lasts" serve as option values and
@ -111,15 +112,17 @@ module ApplicationHelper
PageRenderer.new(page.revisions.last).display_content
end
def truncate(text, length = 30, truncate_string = '...')
return text if text.length <= length
len = length - truncate_string.length
def truncate(text, *args)
options = args.extract_options!
options.reverse_merge!(:length => 30, :omission => "...")
return text if text.num_chars <= options[:length]
len = options[:length] - options[:omission].as_utf8.num_chars
t = ''
text.split.collect do |word|
if t.length + word.length <= len
if t.num_chars + word.num_chars <= len
t << word + ' '
else
return t.chop + truncate_string
return t.chop + options[:omission]
end
end
end

View File

@ -13,7 +13,7 @@
<ul>
<%- @pages_in_category.each do |page| -%>
<li>
<%= link_to_existing_page page, truncate(page.plain_name, 35) %>
<%= link_to_existing_page page, truncate(page.plain_name, :length => 35) %>
</li>
<%- end -%>
</ul>
@ -37,7 +37,7 @@
<ul style="margin-bottom: 10px">
<%- @page_names_that_are_wanted.each do |wanted_page_name| -%>
<li>
<%= link_to_page(wanted_page_name, @web, truncate(WikiWords.separate(wanted_page_name), 35)) %>
<%= link_to_page(wanted_page_name, @web, truncate(WikiWords.separate(wanted_page_name), :length => 35)) %>
wanted by
<%= @web.select.pages_that_reference(wanted_page_name).collect { |referring_page|
link_to_existing_page referring_page
@ -57,7 +57,7 @@
<ul style="margin-bottom: 35px">
<%- @pages_that_are_orphaned.each do |orphan_page| -%>
<li>
<%= link_to_existing_page orphan_page, truncate(orphan_page.plain_name, 35) %>
<%= link_to_existing_page orphan_page, truncate(orphan_page.plain_name, :length => 35) %>
</li>
<%- end -%>
</ul>

View File

@ -2,8 +2,30 @@
class String
# Return the number of unicode characters in a string
#
# :call-seq:
# string.num_chars -> integer
#
# Because Rails 2.3.5's String#mb_chars.length is broken,
# we provide this method.
#--
if "".respond_to?(:force_encoding)
def num_chars
length
end
else
def num_chars
unpack('U*').length
end
end
#++
# A method to allow byte-oriented operations in both Ruby 1.8 and Ruby 1.9
#
# :call-seq:
# string.to_utf_8 -> string (with the encoding set to "ASCII-8BIT")
#
# Under 1.8, this is a NOOP. Under 1.9, it sets the encoding to "ASCII-8BIT"
#--
if "".respond_to?(:force_encoding)
@ -19,6 +41,9 @@ end
#++
# A method to allow string-oriented operations in both Ruby 1.8 and Ruby 1.9
#
# :call-seq:
# string.to_utf_8 -> string (with the encoding set to "UTF-8")
#
# Under 1.8, this is a NOOP. Under 1.9, it sets the encoding to "UTF-8"
#--
if "".respond_to?(:force_encoding)

View File

@ -40,8 +40,12 @@ class WikiControllerTest < ActionController::TestCase
def test_truncate_page_name
wanted_page_name = 'This is a very, very, very, very, VERY long page name'
evil_page_name = 'This page has plenty of fun &amp; games'
assert_equal 'This is a very, very, very,...', @controller.truncate(WikiWords.separate(wanted_page_name), 35)
unicode_page_name = "This p\xF0\x9D\x94\xB8\xF0\x9D\x94\xBE\xF0\x9D\x94\xBC has plenty of fun &amp; games"
assert_equal 'This is a very, very, very,...', @controller.truncate(WikiWords.separate(wanted_page_name), :length => 35)
assert_equal 'This page has plenty of fun...', @controller.truncate(WikiWords.separate(evil_page_name))
truncated = "".respond_to?(:force_encoding) ? "This p\u{1D538}\u{1D53E}\u{1D53C} has plenty of fun\u2633\u2633" :
"This p\xF0\x9D\x94\xB8\xF0\x9D\x94\xBE\xF0\x9D\x94\xBC has plenty of fun\xE2\x98\xB3\xE2\x98\xB3"
assert_equal truncated, @controller.truncate(WikiWords.separate(unicode_page_name), :omission =>"\xE2\x98\xB3\xE2\x98\xB3")
end
def test_authenticate