mirror of
https://github.com/haml/haml.git
synced 2022-11-09 12:33:31 -05:00
Optimize common attributes
This commit is contained in:
parent
4d5fcbffe6
commit
9ce9b0db90
6 changed files with 117 additions and 2 deletions
|
@ -33,6 +33,13 @@ module Haml
|
|||
"_hamlout.attributes(#{Haml::Util.inspect_obj(attributes)}, #{object_ref},#{attributes_hashes.join(', ')})"
|
||||
end
|
||||
|
||||
# @param options [Haml::Options]
|
||||
def initialize(options)
|
||||
@is_html = [:html4, :html5].include?(options[:format])
|
||||
@attr_wrapper = options[:attr_wrapper]
|
||||
@escape_attrs = options[:escape_attrs]
|
||||
end
|
||||
|
||||
# Returns Temple expression to render attributes.
|
||||
#
|
||||
# @param attributes [Hash]
|
||||
|
@ -123,7 +130,47 @@ module Haml
|
|||
# @param values [Array<AttributeValue>]
|
||||
# @return [Array] Temple expression
|
||||
def compile_attribute(key, values)
|
||||
runtime_build(values)
|
||||
case key
|
||||
when 'id', 'class'
|
||||
runtime_build(values)
|
||||
else
|
||||
compile_common_attribute(key, values)
|
||||
end
|
||||
end
|
||||
|
||||
# Compiles attribute for keys except "id" and "class".
|
||||
#
|
||||
# @param key [String] Not "id" or "class"
|
||||
# @param values [Array<AttributeValue>]
|
||||
# @return [Array] Temple expression
|
||||
def compile_common_attribute(key, values)
|
||||
var = unique_name
|
||||
[:multi,
|
||||
[:code, "#{var} = (#{merged_value(key, values)})"],
|
||||
[:case, var,
|
||||
['Hash', runtime_build([AttributeValue.new(:dynamic, key, var)])],
|
||||
['true', true_value(key)],
|
||||
['false, nil', [:multi]],
|
||||
[:else, [:multi,
|
||||
[:static, " #{key}=#{@attr_wrapper}"],
|
||||
[:escape, @escape_attrs, [:dynamic, var]],
|
||||
[:static, @attr_wrapper]],
|
||||
]
|
||||
],
|
||||
]
|
||||
end
|
||||
|
||||
def true_value(key)
|
||||
if @is_html
|
||||
[:static, " #{key}"]
|
||||
else
|
||||
[:static, " #{key}=#{@attr_wrapper}#{key}#{@attr_wrapper}"]
|
||||
end
|
||||
end
|
||||
|
||||
def unique_name
|
||||
@unique_name ||= 0
|
||||
"_haml_attribute_compiler#{@unique_name += 1}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,7 +14,7 @@ module Haml
|
|||
@to_merge = []
|
||||
@temple = [:multi]
|
||||
@node = nil
|
||||
@attribute_compiler = AttributeCompiler.new
|
||||
@attribute_compiler = AttributeCompiler.new(options)
|
||||
end
|
||||
|
||||
def call(node)
|
||||
|
|
48
lib/haml/escapable.rb
Normal file
48
lib/haml/escapable.rb
Normal file
|
@ -0,0 +1,48 @@
|
|||
module Haml
|
||||
# Like Temple::Filters::Escapable, but with support for escaping by
|
||||
# Haml::Herlpers.html_escape and Haml::Herlpers.escape_once.
|
||||
class Escapable < Temple::Filter
|
||||
def initialize(*)
|
||||
super
|
||||
@escape_code = "::Haml::Helpers.html_escape((%s))"
|
||||
@escaper = eval("proc {|v| #{@escape_code % 'v'} }")
|
||||
@once_escape_code = "::Haml::Helpers.escape_once((%s))"
|
||||
@once_escaper = eval("proc {|v| #{@once_escape_code % 'v'} }")
|
||||
@escape = false
|
||||
end
|
||||
|
||||
def on_escape(flag, exp)
|
||||
old = @escape
|
||||
@escape = flag
|
||||
compile(exp)
|
||||
ensure
|
||||
@escape = old
|
||||
end
|
||||
|
||||
# The same as Haml::AttributeBuilder.build_attributes
|
||||
def on_static(value)
|
||||
[:static,
|
||||
if @escape == :once
|
||||
@once_escaper[value]
|
||||
elsif @escape
|
||||
@escaper[value]
|
||||
else
|
||||
value
|
||||
end
|
||||
]
|
||||
end
|
||||
|
||||
# The same as Haml::AttributeBuilder.build_attributes
|
||||
def on_dynamic(value)
|
||||
[:dynamic,
|
||||
if @escape == :once
|
||||
@once_escape_code % value
|
||||
elsif @escape
|
||||
@escape_code % value
|
||||
else
|
||||
"(#{value}).to_s"
|
||||
end
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,4 +1,5 @@
|
|||
require 'temple'
|
||||
require 'haml/escapable'
|
||||
require 'haml/generator'
|
||||
|
||||
module Haml
|
||||
|
@ -28,6 +29,8 @@ module Haml
|
|||
|
||||
use :Parser, -> { options[:parser_class] }
|
||||
use :Compiler, -> { options[:compiler_class] }
|
||||
use Escapable
|
||||
filter :ControlFlow
|
||||
filter :MultiFlattener
|
||||
filter :StaticMerger
|
||||
use Generator
|
||||
|
|
|
@ -13,6 +13,13 @@ module Haml
|
|||
args.first.count("\n")
|
||||
when :static
|
||||
0 # It has not real newline "\n" but escaped "\\n".
|
||||
when :case
|
||||
arg, *cases = args
|
||||
arg.count("\n") + cases.map do |cond, e|
|
||||
(cond == :else ? 0 : cond.count("\n")) + count_lines(e)
|
||||
end.reduce(:+)
|
||||
when :escape
|
||||
count_lines(args[1])
|
||||
else
|
||||
raise UnexpectedExpression.new("[HAML BUG] Unexpected Temple expression '#{type}' is given!")
|
||||
end
|
||||
|
|
|
@ -12,6 +12,16 @@ class TempleLineCounterTest < Haml::TestCase
|
|||
[:static, "foo\nbar\nbaz"],
|
||||
[:dynamic, "foo\nbar\nbaz"],
|
||||
],
|
||||
[:case,
|
||||
["'a\nb', false", [:static, "hello\n"]],
|
||||
[:else, [:code, "raise 'error\n'"]],
|
||||
],
|
||||
[:escape, true, [:dynamic, "foo\nbar"]],
|
||||
[:escape, :once, [:dynamic, "foo\nbar"]],
|
||||
[:escape, false, [:dynamic, "foo\nbar"]],
|
||||
[:escape, true, [:static, "foo\nbar"]],
|
||||
[:escape, :once, [:static, "foo\nbar"]],
|
||||
[:escape, false, [:dynamic, "foo\nbar"]],
|
||||
]
|
||||
|
||||
def test_count_lines
|
||||
|
|
Loading…
Reference in a new issue