From 5f2a5ea9eae5892bb038a2d9a85315c2beb0c35c Mon Sep 17 00:00:00 2001
From: Ian Ownbey <iownbey@notesake.com>
Date: Sun, 10 Feb 2008 19:45:36 -0500
Subject: [PATCH] Allow formatting of nested brackets
---
lib/haml/precompiler.rb | 15 +++++++++++++--
test/haml/engine_test.rb | 7 +++++++
2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/lib/haml/precompiler.rb b/lib/haml/precompiler.rb
index 74408dd..200995a 100644
--- a/lib/haml/precompiler.rb
+++ b/lib/haml/precompiler.rb
@@ -479,8 +479,19 @@ END
def render_tag(line)
raise SyntaxError.new("Invalid tag: \"#{line}\"") unless match = line.scan(TAG_REGEX)[0]
tag_name, attributes, attributes_hash, object_ref, action, value = match
- value = value.to_s.strip
- attributes_hash = attributes_hash[1...-1] if attributes_hash
+
+ if attributes_hash && garble = attributes_hash.scan(/\{(.*(\}.*\{).*)\}/)[0]
+ scanner = StringScanner.new(attributes_hash[1, attributes_hash.length])
+ attributes_hash = balance_brackets(scanner)
+ # Strip off the attributes
+ rest = garble[0][attributes_hash.length + 2...garble[0].length]
+ object_ref, action, start_value = rest.scan(/(\[.*\])?([=\/\~]?)?(.*)?/)[0] unless rest.nil?
+ value = start_value.to_s + "}" + value.to_s
+ value.strip
+ else
+ value = value.to_s.strip
+ attributes_hash = attributes_hash[1...-1] if attributes_hash
+ end
raise SyntaxError.new("Illegal element: classes and ids must have values.") if attributes =~ /[\.#](\.|#|\z)/
diff --git a/test/haml/engine_test.rb b/test/haml/engine_test.rb
index a178ecc..75a031c 100644
--- a/test/haml/engine_test.rb
+++ b/test/haml/engine_test.rb
@@ -133,6 +133,13 @@ class EngineTest < Test::Unit::TestCase
assert_equal("<p escaped='quo4te'>\n</p>\n", render("%p{ :escaped => \"quo\#{2 + 2}te\"}"))
end
+ def test_correct_parsing_with_brackets
+ assert_equal("<p class='foo'>{tada} foo</p>\n", render("%p{:class => 'foo'} {tada} foo"))
+ assert_equal("<p class='foo'>deep {nested { things }}</p>\n", render("%p{:class => 'foo'} deep {nested { things }}"))
+ assert_equal("<p class='bar foo'>{a { d</p>\n", render("%p{{:class => 'foo'}, :class => 'bar'} {a { d"))
+ assert_equal("<p>a }</p>\n", render("%p a }"))
+ end
+
def test_empty_attrs
assert_equal("<p attr=''>empty</p>\n", render("%p{ :attr => '' } empty"))
assert_equal("<p attr=''>empty</p>\n", render("%p{ :attr => x } empty", :locals => {:x => ''}))
--
1.5.3.6