This was holding me up for a while. I asked around online and did some code searches on Google but wasn’t able to find a good rails solution to truncating a string of HTML coming out of Textile without cutting off tags and making a general mess of things. Links in particular were problematic.
In the end I came up with a solution that I think was pretty easy to implement in my application controller and that I could call from any view.
Details below,
Enjoy!
#in application_helper.rb # Does NOT behave identical to current Rails truncate method # you must pass options as a hash not just values # Sample usage: <%= html_truncate(category.description, :length => # 120, :omission => "(continued...)" ) -%>... def html_truncate(html, truncate_length, options={}) text, result = [], [] # get all text (including punctuation) and tags and stick them in a hash html.scan(/<\/?[^>]*>|[A-Za-z0-9.,\/\!\+\(\)\-"'?]+/).each { |t| text << t } text.each do |str| if truncate_length > 0 if str =~ /<\/?[^>]*>/ previous_tag = str result << str else result << str truncate_length -= str.length end else # now stick the next tag with a > that matches the previous # open tag on the end of the result if previous_tag && str =~ /<\/([#{previous_tag}]*)>/ result << str end end end return result.join(" ") + options[:omission].to_s end end
I’m open to improvement on this. Perhaps extending “acts_as_textiled” or something. Maybe I could find a neater way to put the two arrays together.
As of the time of this writing, I just finished this and will be putting it into a production environment so that I can evaluate if it’s quick enough to work in production. Since I went with regex, I’m hoping so.
You can see it in action on Seaview Global
4 Comments