Skip to content

Commit

Permalink
Ignore dynamic falsy attributes
Browse files Browse the repository at this point in the history
Fixes haml#2.
  • Loading branch information
k0kubun committed Apr 12, 2015
1 parent bc20a93 commit 8700951
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 14 deletions.
23 changes: 22 additions & 1 deletion lib/hamlit/compilers/old_attribute.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,27 @@ module OldAttribute
include Concerns::Balanceable
include Concerns::Ripperable

# For performance, only data can be nested.
# Only data can be nested for performance.
NESTABLE_ATTRIBUTES = %w[data].freeze
IGNORED_EXPRESSIONS = %w[false nil].freeze

# Only boolean attributes can be deleted for performance.
BOOLEAN_ATTRIBUTES = %w[
autofocus
checked
data
disabled
formnovalidate
multiple
readonly
].freeze

def compile_old_attribute(str)
raise RuntimeBuild unless Ripper.sexp(str)

attrs = parse_old_attributes(str)
assert_no_boolean_attributes!(attrs)

format_attributes(attrs).map do |key, value|
next true_attribute(key) if value == 'true'
assert_static_value!(value) if NESTABLE_ATTRIBUTES.include?(key)
Expand Down Expand Up @@ -56,6 +69,14 @@ def assert_static_value!(value)
end
end

# Give up static compilation when attributes have deletable
# attributes, such as 'checked'.
def assert_no_boolean_attributes!(attrs)
if BOOLEAN_ATTRIBUTES.any? { |key| attrs.keys.include?(key) }
raise RuntimeBuild
end
end

# Parse brace-balanced string and return the result as hash
def parse_old_attributes(str)
attributes = {}
Expand Down
71 changes: 58 additions & 13 deletions spec/hamlit/engine/old_attributes_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,6 @@
HTML
end

it 'renders false or nil attributes' do
assert_render(<<-'HAML', <<-HTML)
- hash = { checked: false }
%input{ hash }
%input{ checked: false }
%input{ checked: nil }
HAML
<input>
<input>
<input>
HTML
end

it 'accepts even illegal input for haml' do
assert_render(<<-'HAML', <<-HTML)
%span{ class: '}}}', id: '{}}' } }{
Expand Down Expand Up @@ -86,6 +73,64 @@
HTML
end

describe 'deletable attributes' do
it 'deletes attributes whose value is nil or false' do
assert_render(<<-'HAML', <<-HTML)
- hash = { checked: false }
%input{ hash }
%input{ checked: false }
%input{ checked: nil }
- checked = nil
%input{ checked: checked }
- checked = false
%input{ checked: checked }
HAML
<input>
<input>
<input>
<input>
<input>
HTML
end

it 'deletes some limited attributes with dynamic value' do
assert_render(<<-'HAML', <<-HTML)
- val = false
#foo.bar{ autofocus: val }
#foo.bar{ checked: val }
#foo.bar{ data: { disabled: val } }
#foo.bar{ disabled: val }
#foo.bar{ formnovalidate: val }
#foo.bar{ multiple: val }
#foo.bar{ readonly: val }
HAML
<div class='bar' id='foo'></div>
<div class='bar' id='foo'></div>
<div class='bar' id='foo'></div>
<div class='bar' id='foo'></div>
<div class='bar' id='foo'></div>
<div class='bar' id='foo'></div>
<div class='bar' id='foo'></div>
HTML
end

it 'does not delete some attributes, for optimization' do
assert_render(<<-'HAML', <<-HTML)
- val = false
%a{ href: val }
%a{ class: val }
- val = nil
%a{ href: val }
%a{ class: val }
HAML
<a href='false'></a>
<a class='false'></a>
<a href=''></a>
<a class=''></a>
HTML
end
end

describe 'html escape' do
it 'escapes attribute values on static attributes' do
assert_render(<<-'HAML', <<-HTML)
Expand Down

0 comments on commit 8700951

Please sign in to comment.