module TruncateHtmlHelper

Public Instance Methods

truncate_html(html, options={}, &block) click to toggle source
# File truncate_html_helper.rb, line 4
def truncate_html(html, options={}, &block)
  if html
    length = options.fetch(:length, 30)
    omission = options.fetch(:omission, "…")

    omission &&= Nokogiri::HTML::DocumentFragment.parse(omission)

    remaining = length
    remaining -= omission.content.length if omission

    fragment = Nokogiri::HTML::DocumentFragment.parse(html)
    fragment.traverse do |node|
      if node.text? or node.cdata?
        remaining -= node.content.length
        if remaining < 0
          node.content = node.content[0...remaining]
        end
        if node.content.empty?
          node.remove
        end
      elsif node.element? and remaining <= 0 and not node.children.any?
        node.remove
      end
    end

    # If there's a block, use it instead of the omission
    if block_given? && remaining < 0
      omission = Nokogiri::HTML::DocumentFragment.parse(capture(&block))
    end

    # Add the omission only if we have truncated
    if omission && remaining < 0
      last_child = fragment.children.last
      # If the last element is block, level, tuck the omission inside
      if last_child.element? and last_child.description and last_child.description.block?
        last_child << omission
      else
        fragment << omission
      end
    end

    fragment.to_html
  end
end