class Haml::AttributeCompiler

Public Class Methods

new(identity, options) click to toggle source
# File lib/haml/attribute_compiler.rb, line 16
def initialize(identity, options)
  @identity = identity
  @quote  = options[:attr_quote]
  @format = options[:format]
  @escape_attrs = options[:escape_attrs]
end

Public Instance Methods

compile(node) click to toggle source
# File lib/haml/attribute_compiler.rb, line 23
def compile(node)
  hashes = []
  if node.value[:object_ref] != :nil || !AttributeParser.available?
    return runtime_compile(node)
  end
  [node.value[:dynamic_attributes].new, node.value[:dynamic_attributes].old].compact.each do |attribute_str|
    hash = AttributeParser.parse(attribute_str)
    return runtime_compile(node) if hash.nil? || hash.any? { |_key, value| value.empty? }
    hashes << hash
  end
  static_compile(node.value[:attributes], hashes)
end

Private Instance Methods

attribute_builder(type, values) click to toggle source
# File lib/haml/attribute_compiler.rb, line 123
def attribute_builder(type, values)
  args = [@escape_attrs.inspect, *values.map { |v| literal_for(v) }]
  "::Haml::AttributeBuilder.build_#{type}(#{args.join(', ')})"
end
compile_boolean!(temple, key, values) click to toggle source
# File lib/haml/attribute_compiler.rb, line 98
def compile_boolean!(temple, key, values)
  exp = literal_for(values.last)

  if Temple::StaticAnalyzer.static?(exp)
    value = eval(exp)
    case value
    when true then temple << [:html, :attr, key, @format == :xhtml ? [:static, key] : [:multi]]
    when false, nil
    else temple << [:html, :attr, key, [:fescape, @escape_attrs, [:static, value.to_s]]]
    end
  else
    var = @identity.generate
    temple << [
      :case, "(#{var} = (#{exp}))",
      ['true', [:html, :attr, key, @format == :xhtml ? [:static, key] : [:multi]]],
      ['false, nil', [:multi]],
      [:else, [:multi, [:static, " #{key}=#{@quote}"], [:fescape, @escape_attrs, [:dynamic, var]], [:static, @quote]]],
    ]
  end
end
compile_class!(temple, key, values) click to toggle source
# File lib/haml/attribute_compiler.rb, line 78
def compile_class!(temple, key, values)
  build_code = attribute_builder(:class, values)
  if values.all? { |type, exp| type == :static || Temple::StaticAnalyzer.static?(exp) }
    temple << [:html, :attr, key, [:static, eval(build_code).to_s]]
  else
    temple << [:html, :attr, key, [:dynamic, build_code]]
  end
end
compile_common!(temple, key, values) click to toggle source
# File lib/haml/attribute_compiler.rb, line 119
def compile_common!(temple, key, values)
  temple << [:html, :attr, key, [:fescape, @escape_attrs, values.last]]
end
compile_data!(temple, key, values) click to toggle source
# File lib/haml/attribute_compiler.rb, line 87
def compile_data!(temple, key, values)
  args = [@escape_attrs.inspect, "#{@quote.inspect}.freeze", values.map { |v| literal_for(v) }]
  build_code = "::Haml::AttributeBuilder.build_#{key}(#{args.join(', ')})"

  if values.all? { |type, exp| type == :static || Temple::StaticAnalyzer.static?(exp) }
    temple << [:static, eval(build_code).to_s]
  else
    temple << [:dynamic, build_code]
  end
end
compile_id!(temple, key, values) click to toggle source
# File lib/haml/attribute_compiler.rb, line 69
def compile_id!(temple, key, values)
  build_code = attribute_builder(:id, values)
  if values.all? { |type, exp| type == :static || Temple::StaticAnalyzer.static?(exp) }
    temple << [:html, :attr, key, [:static, eval(build_code).to_s]]
  else
    temple << [:html, :attr, key, [:dynamic, build_code]]
  end
end
literal_for(value) click to toggle source
# File lib/haml/attribute_compiler.rb, line 128
def literal_for(value)
  type, exp = value
  type == :static ? "#{exp.inspect}.freeze" : exp
end
runtime_compile(node) click to toggle source
# File lib/haml/attribute_compiler.rb, line 38
def runtime_compile(node)
  attrs = []
  attrs.unshift(node.value[:attributes].inspect) if node.value[:attributes] != {}

  args = [@escape_attrs.inspect, "#{@quote.inspect}.freeze", @format.inspect, node.value[:object_ref]] + attrs
  [:html, :attrs, [:dynamic, "::Haml::AttributeBuilder.build(#{args.join(', ')}, #{node.value[:dynamic_attributes].to_literal})"]]
end
static_compile(static_hash, dynamic_hashes) click to toggle source
# File lib/haml/attribute_compiler.rb, line 46
def static_compile(static_hash, dynamic_hashes)
  temple = [:html, :attrs]
  keys = [*static_hash.keys, *dynamic_hashes.map(&:keys).flatten].uniq.sort
  keys.each do |key|
    values = [[:static, static_hash[key]], *dynamic_hashes.map { |h| [:dynamic, h[key]] }]
    values.select! { |_, exp| exp != nil }

    case key
    when 'id'
      compile_id!(temple, key, values)
    when 'class'
      compile_class!(temple, key, values)
    when 'data', 'aria'
      compile_data!(temple, key, values)
    when *BOOLEAN_ATTRIBUTES, /\Adata-/, /\Aaria-/
      compile_boolean!(temple, key, values)
    else
      compile_common!(temple, key, values)
    end
  end
  temple
end