diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 893faa70..62ce7a22 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -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
diff --git a/app/views/wiki/list.rhtml b/app/views/wiki/list.rhtml
index fb42a0bd..12dc2571 100644
--- a/app/views/wiki/list.rhtml
+++ b/app/views/wiki/list.rhtml
@@ -13,7 +13,7 @@
<%- @pages_in_category.each do |page| -%>
-
- <%= link_to_existing_page page, truncate(page.plain_name, 35) %>
+ <%= link_to_existing_page page, truncate(page.plain_name, :length => 35) %>
<%- end -%>
@@ -37,7 +37,7 @@
<%- @page_names_that_are_wanted.each do |wanted_page_name| -%>
-
- <%= 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 @@
<%- @pages_that_are_orphaned.each do |orphan_page| -%>
-
- <%= 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) %>
<%- end -%>
diff --git a/lib/stringsupport.rb b/lib/stringsupport.rb
index 658283dd..29d763ef 100644
--- a/lib/stringsupport.rb
+++ b/lib/stringsupport.rb
@@ -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)
diff --git a/test/functional/wiki_controller_test.rb b/test/functional/wiki_controller_test.rb
index 7b54a359..bdb47ef8 100644
--- a/test/functional/wiki_controller_test.rb
+++ b/test/functional/wiki_controller_test.rb
@@ -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 & 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 & 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