lib/temple/html/pretty.rb
module Temple module HTML # @api public class Pretty < Fast define_options :indent => ' ', :pretty => true, :indent_tags => %w(article aside audio base body datalist dd div dl dt fieldset figure footer form head h1 h2 h3 h4 h5 h6 header hgroup hr html li link meta nav ol p rp rt ruby section script style table tbody td tfoot th thead title tr ul video).freeze, :pre_tags => %w(code pre textarea).freeze def initialize(opts = {}) super @last = :noindent @indent = 0 @pretty = options[:pretty] @pre_tags = Regexp.new(options[:pre_tags].map {|t| "<#{t}" }.join('|')) end def call(exp) @pretty ? [:multi, preamble, compile(exp)] : super end def on_static(content) if @pretty content = content.gsub("\n", indent) if @pre_tags !~ content @last = content.sub!(/\r?\n\s*$/, ' ') ? nil : :noindent end [:static, content] end def on_dynamic(code) if @pretty @last = :noindent tmp = unique_name gsub_code = if ''.respond_to?(:html_safe?) "#{tmp} = #{tmp}.html_safe? ? #{tmp}.gsub(\"\\n\", #{indent.inspect}).html_safe : #{tmp}.gsub(\"\\n\", #{indent.inspect})" else "#{tmp} = #{tmp}.gsub(\"\\n\", #{indent.inspect})" end [:multi, [:code, "#{tmp} = (#{code}).to_s"], [:code, "if #{@pre_tags_name} !~ #{tmp}; #{gsub_code}; end"], [:dynamic, tmp]] else [:dynamic, code] end end def on_html_doctype(type) @last = nil super end def on_html_comment(content) return super unless @pretty result = [:multi, [:static, tag_indent(nil)], super] @last = nil result end def on_html_tag(name, attrs, content = nil) return super unless @pretty name = name.to_s closed = !content || (empty_exp?(content) && options[:autoclose].include?(name)) @pretty = false result = [:multi, [:static, "#{tag_indent(name)}<#{name}"], compile(attrs)] result << [:static, (closed && xhtml? ? ' /' : '') + '>'] @pretty = !options[:pre_tags].include?(name) if content @indent += 1 result << compile(content) @indent -= 1 end result << [:static, "#{content && !empty_exp?(content) ? tag_indent(name) : ''}</#{name}>"] unless closed @pretty = true result end protected def preamble @pre_tags_name = unique_name [:code, "#{@pre_tags_name} = /#{@pre_tags.source}/"] end # Return indentation if not in pre tag def indent "\n" + (options[:indent] || '') * @indent end # Return indentation before tag def tag_indent(name) result = @last != :noindent && (options[:indent_tags].include?(@last) || options[:indent_tags].include?(name)) ? indent : '' @last = name result end end end end