diff --git a/lib/haml/precompiler.rb b/lib/haml/precompiler.rb index f871709e..9fd13eee 100644 --- a/lib/haml/precompiler.rb +++ b/lib/haml/precompiler.rb @@ -1,3 +1,5 @@ +require 'strscan' + module Haml module Precompiler # Designates an XHTML/XML element. @@ -609,18 +611,29 @@ END end def unescape_interpolation(str) - first = str.index(/(^|[^\\])\#\{/) + scan = StringScanner.new(str.dump) + str = '' - return str.dump if first.nil? - first += 1 unless first == 0 + while scan.scan(/(.*?)\\\#\{/) + str << scan.matched[0...-3] + str << eval("\"\\\#{#{balance_brackets(scan)}}\"") + end - last = str.rindex '}' + str + scan.rest + end - interpolation = str.slice!(first, last - first) - str.insert(first, "_haml_interpolation") + def balance_brackets(scanner) + str = '' + count = 1 - str = str.dump - str.gsub("_haml_interpolation", interpolation) + while scanner.scan(/(.*?)[\{\}]/) + str << scanner.matched + count += 1 if scanner.matched[-1] == ?{ + count -= 1 if scanner.matched[-1] == ?} + return str[0...-1] if count == 0 + end + + raise SyntaxError.new("Unbalanced brackets.") end # Counts the tabulation of a line. diff --git a/test/haml/engine_test.rb b/test/haml/engine_test.rb index 168acee8..6e28bb26 100644 --- a/test/haml/engine_test.rb +++ b/test/haml/engine_test.rb @@ -265,6 +265,12 @@ class EngineTest < Test::Unit::TestCase '"a\nb\n- fee do\nc" doesn\'t produce an exception!') end + def test_unbalanced_brackets + render('== #{1 + 5} foo #{6 + 7 bar #{8 + 9}') + rescue Haml::SyntaxError => e + assert_equal("Unbalanced brackets.", e.message) + end + def test_no_bluecloth Kernel.module_eval do def gem_original_require_with_bluecloth(file) diff --git a/test/haml/results/just_stuff.xhtml b/test/haml/results/just_stuff.xhtml index 9c2dda2a..2fd02ddb 100644 --- a/test/haml/results/just_stuff.xhtml +++ b/test/haml/results/just_stuff.xhtml @@ -11,6 +11,12 @@ Embedded? false! Embedded? true! Embedded? true! Embedded? twice! true! +Embedded? one af"t"er another! +

Embedded? false!

+

Embedded? true!

+

Embedded? true!

+

Embedded? twice! true!

+

Embedded? one af"t"er another!

wow!
stuff followed by whitespace block with whitespace diff --git a/test/haml/templates/just_stuff.haml b/test/haml/templates/just_stuff.haml index 28008b9e..1c1d8e01 100644 --- a/test/haml/templates/just_stuff.haml +++ b/test/haml/templates/just_stuff.haml @@ -12,6 +12,13 @@ - embedded = true == Embedded? #{embedded}! == Embedded? #{"twice! #{true}"}! +== Embedded? #{"one"} af"t"er #{"another"}! +%p== Embedded? false! +%p== Embedded? #{true}! +- embedded = true +%p== Embedded? #{embedded}! +%p== Embedded? #{"twice! #{true}"}! +%p== Embedded? #{"one"} af"t"er #{"another"}! .render= render :inline => "%em= 'wow!'", :type => :haml = "stuff followed by whitespace"