class Railroader::HamlTemplateProcessor

Processes HAML templates.

Constants

COFFEE_FILTER
HAML_FORMAT_METHOD
HAML_HELPERS
JAVASCRIPT_FILTER

Public Instance Methods

build_output_from_push_text(exp, default = :output) click to toggle source

HAML likes to put interpolated values into _hamlout.push_text but we want to handle those individually

# File lib/railroader/processors/haml_template_processor.rb, line 140
def build_output_from_push_text exp, default = :output
  if string_interp? exp
    exp.map! do |e|
      if sexp? e
        if node_type? e, :evstr and e[1]
          e = e.value
        end

        get_pushed_value e, default
      else
        e
      end
    end
  end
end
get_pushed_value(exp, default = :output) click to toggle source

Gets outputs from values interpolated into _hamlout.push_text

# File lib/railroader/processors/haml_template_processor.rb, line 157
def get_pushed_value exp, default = :output
  return exp unless sexp? exp

  case exp.node_type
  when :format
    exp.node_type = :output
    @current_template.add_output exp
    exp
  when :format_escaped
    exp.node_type = :escaped_output
    @current_template.add_output exp
    exp
  when :str, :ignore, :output, :escaped_output
    exp
  when :block, :rlist, :dstr
    exp.map! { |e| get_pushed_value e }
  when :if
    clauses = [get_pushed_value(exp.then_clause), get_pushed_value(exp.else_clause)].compact

    if clauses.length > 1
      s(:or, *clauses)
    else
      clauses.first
    end
  else
    if call? exp and exp.target == HAML_HELPERS and exp.method == :html_escape
      add_escaped_output exp.first_arg
    elsif @javascript and call? exp and (exp.method == :j or exp.method == :escape_javascript)
      add_escaped_output exp.first_arg
    else
      add_output exp, default
    end
  end
end
is_buffer_target?(exp) click to toggle source

Checks if the buffer is the target in a method call Sexp. TODO: Test this

# File lib/railroader/processors/haml_template_processor.rb, line 131
def is_buffer_target? exp
  exp.node_type == :call and
  node_type? exp.target, :lvar and
  exp.target.value == :_hamlout and
  exp.method == :buffer
end
process_block(exp) click to toggle source

If inside an output stream, only return the final expression

# File lib/railroader/processors/haml_template_processor.rb, line 106
def process_block exp
  exp = exp.dup
  exp.shift
  if @inside_concat
    @inside_concat = false
    exp[0..-2].each do |e|
      process e
    end
    @inside_concat = true
    process exp[-1]
  else
    exp.map! do |e|
      res = process e
      if res.empty?
        nil
      else
        res
      end
    end
    Sexp.new(:rlist).concat(exp).compact
  end
end
process_call(exp) click to toggle source

Processes call, looking for template output

# File lib/railroader/processors/haml_template_processor.rb, line 11
def process_call exp
  target = exp.target
  if sexp? target
    target = process target
  end

  method = exp.method

  if (call? target and target.method == :_hamlout)
    res = case method
          when :adjust_tabs, :rstrip!, :attributes # Check attributes, maybe?
            ignore
          when :options, :buffer
            exp
          when :open_tag
            process_call_args exp
          else
            arg = exp.first_arg

            if arg
              @inside_concat = true
              exp.first_arg = process(arg)
              out = normalize_output(exp.first_arg)
              @inside_concat = false
            else
              raise "Empty _hamlout.#{method}()?"
            end

            if string? out
              ignore
            else
              r = case method.to_s
                  when "push_text"
                    build_output_from_push_text(out)
                  when HAML_FORMAT_METHOD
                    if $4 == "true"
                      if string_interp? out
                        build_output_from_push_text(out, :escaped_output)
                      else
                        Sexp.new :format_escaped, out
                      end
                    else
                      if string_interp? out
                        build_output_from_push_text(out)
                      else
                        Sexp.new :format, out
                      end
                    end

                  else
                    raise "Unrecognized action on _hamlout: #{method}"
                  end

              @javascript = false
              r
            end
          end

    res.line(exp.line)
    res

    # _hamlout.buffer <<
    # This seems to be used rarely, but directly appends args to output buffer.
    # Has something to do with values of blocks?
  elsif sexp? target and method == :<< and is_buffer_target? target
    @inside_concat = true
    exp.first_arg = process(exp.first_arg)
    out = normalize_output(exp.first_arg)
    @inside_concat = false

    if out.node_type == :str # ignore plain strings
      ignore
    else
      add_output out
    end
  elsif target == nil and method == :render
    # Process call to render()
    exp.arglist = process exp.arglist
    make_render_in_view exp
  elsif target == nil and method == :find_and_preserve and exp.first_arg
    process exp.first_arg
  elsif method == :render_with_options
    if target == JAVASCRIPT_FILTER or target == COFFEE_FILTER
      @javascript = true
    end

    process exp.first_arg
  else
    exp.target = target
    exp.arglist = process exp.arglist
    exp
  end
end