Skip to content
Browse files

Major improvement on better_truncate

  • Loading branch information...
1 parent 497c11c commit d13e7a5a42c345261d10440ec427eab4bf8cbb47 Winton Welsh committed Sep 10, 2008
Showing with 47 additions and 4 deletions.
  1. +47 −4 lib/app_helpers/truncate.rb
View
51 lib/app_helpers/truncate.rb
@@ -1,9 +1,52 @@
+require "hpricot"
+
module AppHelpers
-
- def better_truncate(text, length = 80, truncate_string = "...")
+
+ # Like the Rails _truncate_ helper but doesn't break HTML tags or entities.
+ def better_truncate(text, max_length = 30, ellipsis = "...")
return if text.nil?
- l = length - truncate_string.chars.length
- text.chars.length > length ? text[/\A.{#{l}}\w*\;?/m][/.*[\w\;]/m] + truncate_string : text
+
+ doc = Hpricot(text.to_s)
+ ellipsis_length = Hpricot(ellipsis).inner_text.chars.length
+ content_length = doc.inner_text.chars.length
+ actual_length = max_length - ellipsis_length
+
+ content_length > max_length ? doc.truncate(actual_length).inner_html + ellipsis : text.to_s
+ end
+
+ module HpricotTruncator
+ module NodeWithChildren
+ def truncate(max_length)
+ return self if inner_text.chars.length <= max_length
+ truncated_node = self.dup
+ truncated_node.children = []
+ each_child do |node|
+ remaining_length = max_length - truncated_node.inner_text.chars.length
+ break if remaining_length == 0
+ truncated_node.children << node.truncate(remaining_length)
+ end
+ truncated_node
+ end
+ end
+
+ module TextNode
+ def truncate(max_length)
+ # We're using String#scan because Hpricot doesn't distinguish entities.
+ Hpricot::Text.new(content.scan(/&#?[^\W_]+;|./).first(max_length).join)
+ end
+ end
+
+ module IgnoredTag
+ def truncate(max_length)
+ self
+ end
+ end
end
+
+ Hpricot::Doc.send(:include, HpricotTruncator::NodeWithChildren)
+ Hpricot::Elem.send(:include, HpricotTruncator::NodeWithChildren)
+ Hpricot::Text.send(:include, HpricotTruncator::TextNode)
+ Hpricot::BogusETag.send(:include, HpricotTruncator::IgnoredTag)
+ Hpricot::Comment.send(:include, HpricotTruncator::IgnoredTag)
end

0 comments on commit d13e7a5

Please sign in to comment.
Something went wrong with that request. Please try again.