1
0
Fork 0
mirror of https://github.com/haml/haml.git synced 2022-11-09 12:33:31 -05:00

Consider about runtime attribute nesting

But accepting all attribute nesting will cause performance regression.
So I decided to accept runtime nesting for only 'data'.

Fixes #1.
This commit is contained in:
Takashi Kokubun 2015-03-31 02:54:50 +09:00
parent d333f586df
commit 600b03d484
3 changed files with 33 additions and 1 deletions

View file

@ -22,6 +22,11 @@ module Hamlit
def build(attributes)
result = ''
flatten_attributes(attributes).each do |key, value|
if value == true
result += " #{key}"
next
end
escaped = Temple::Utils.escape_html(value)
result += " #{key}=#{@quote}#{escaped}#{@quote}"
end

View file

@ -6,22 +6,32 @@ require 'hamlit/concerns/ripperable'
# This module compiles only old-style attribute, which is
# surrounded by brackets.
module Hamlit
# This error is raised when hamlit copmiler decide to
# copmile the attributes on runtime.
class RuntimeBuild < StandardError; end
module Compilers
module OldAttribute
include Concerns::AttributeBuilder
include Concerns::Balanceable
include Concerns::Ripperable
# For performance, only data can be nested.
NESTABLE_ATTRIBUTES = %w[data].freeze
IGNORED_EXPRESSIONS = %w[false nil].freeze
def compile_old_attribute(str)
return runtime_build(str) unless Ripper.sexp(str)
raise RuntimeBuild unless Ripper.sexp(str)
attrs = parse_old_attributes(str)
format_attributes(attrs).map do |key, value|
next true_attribute(key) if value == 'true'
assert_static_value!(value) if NESTABLE_ATTRIBUTES.include?(key)
[:html, :attr, key, [:dynamic, value]]
end
rescue RuntimeBuild
return runtime_build(str)
end
private
@ -38,6 +48,14 @@ module Hamlit
end
end
# Give up static copmile when variables are detected.
def assert_static_value!(value)
tokens = Ripper.lex(value)
tokens.each do |(row, col), type, str|
raise RuntimeBuild if type == :on_ident
end
end
# Parse brace-balanced string and return the result as hash
def parse_old_attributes(str)
attributes = {}

View file

@ -48,6 +48,15 @@ describe Hamlit::Engine do
HTML
end
it 'renders nested hash whose value is variable' do
assert_render(<<-'HAML', <<-HTML)
- hash = { disable: true }
%span{ data: hash } bar
HAML
<span data-disable>bar</span>
HTML
end
it 'renders false or nil attributes' do
assert_render(<<-'HAML', <<-HTML)
- hash = { checked: false }