diff --git a/lib/handlebars/compiler/ast.js b/lib/handlebars/compiler/ast.js index b9e67d7f..286917db 100644 --- a/lib/handlebars/compiler/ast.js +++ b/lib/handlebars/compiler/ast.js @@ -131,13 +131,18 @@ var AST = { } }, - RawBlockNode: function(mustache, content, locInfo) { + RawBlockNode: function(mustache, content, close, locInfo) { LocationInfo.call(this, locInfo); + if (mustache.sexpr.id.original !== close) { + throw new Exception(mustache.sexpr.id.original + " doesn't match " + close, this); + } + + content = new AST.ContentNode(content, locInfo); + this.type = 'block'; this.mustache = mustache; - mustache.sexpr.isHelper = mustache.isHelper = true; - mustache.params.splice(0, 0, new AST.StringNode(content, locInfo)); + this.program = new AST.ProgramNode([content], locInfo); }, ContentNode: function(string, locInfo) { diff --git a/spec/helpers.js b/spec/helpers.js index b1d97229..ccde982b 100644 --- a/spec/helpers.js +++ b/spec/helpers.js @@ -12,8 +12,8 @@ describe('helpers', function() { it("helper for raw block gets raw content", function() { var string = "{{{{raw}}}} {{test}} {{{{/raw}}}}"; var hash = { test: "hello" }; - var helpers = { raw: function(content) { - return content; + var helpers = { raw: function(options) { + return options.fn(); } }; shouldCompileTo(string, [hash, helpers], " {{test}} ", "raw block helper gets raw content"); @@ -22,8 +22,8 @@ describe('helpers', function() { it("helper for raw block gets parameters", function() { var string = "{{{{raw 1 2 3}}}} {{test}} {{{{/raw}}}}"; var hash = { test: "hello" }; - var helpers = { raw: function(content, a, b, c) { - return content + a + b + c; + var helpers = { raw: function(a, b, c, options) { + return options.fn() + a + b + c; } }; shouldCompileTo(string, [hash, helpers], " {{test}} 123", "raw block helper gets raw content"); diff --git a/spec/parser.js b/spec/parser.js index 5b6dc8a4..097bb15b 100644 --- a/spec/parser.js +++ b/spec/parser.js @@ -157,6 +157,10 @@ describe('parser', function() { shouldThrow(function() { ast_for("{{#goodbyes}}{{/hellos}}"); }, Error, /goodbyes doesn't match hellos/); + + shouldThrow(function() { + ast_for("{{{{goodbyes}}}} {{{{/hellos}}}}"); + }, Error, /goodbyes doesn't match hellos/); }); it('knows how to report the correct line number in errors', function() { diff --git a/src/handlebars.l b/src/handlebars.l index 9b126652..cafdd72c 100644 --- a/src/handlebars.l +++ b/src/handlebars.l @@ -49,7 +49,11 @@ ID [^\s!"#%-,\.\/;->@\[-\^`\{-~]+/{LOOKAHEAD} return 'CONTENT'; } -"{{{{/"[^\s!"#%-,\.\/;->@\[-\^`\{-~]+/[=}\s\/.]"}}}}" { yytext = yytext.substr(5, yyleng-9); this.popState(); return 'END_RAW_BLOCK'; } +"{{{{/"[^\s!"#%-,\.\/;->@\[-\^`\{-~]+/[=}\s\/.]"}}}}" { + yytext = yytext.substr(5, yyleng-9); + this.popState(); + return 'END_RAW_BLOCK'; + } [^\x00]*?/("{{{{/") { return 'CONTENT'; } [\s\S]*?"--}}" strip(0,4); this.popState(); return 'COMMENT'; @@ -58,7 +62,11 @@ ID [^\s!"#%-,\.\/;->@\[-\^`\{-~]+/{LOOKAHEAD} ")" return 'CLOSE_SEXPR'; "{{{{" { return 'OPEN_RAW_BLOCK'; } -"}}}}" { this.popState(); this.begin('raw'); return 'CLOSE_RAW_BLOCK'; } +"}}}}" { + this.popState(); + this.begin('raw'); + return 'CLOSE_RAW_BLOCK'; + } "{{{{"[^\x00]*"}}}}" { yytext = yytext.substr(4, yyleng-8); this.popState(); diff --git a/src/handlebars.yy b/src/handlebars.yy index 464d1bab..51796ec6 100644 --- a/src/handlebars.yy +++ b/src/handlebars.yy @@ -35,7 +35,7 @@ statements ; statement - : openRawBlock CONTENT END_RAW_BLOCK -> new yy.RawBlockNode($1, $2, @$) + : openRawBlock CONTENT END_RAW_BLOCK -> new yy.RawBlockNode($1, $2, $3, @$) | openInverse program closeBlock -> new yy.BlockNode($1, $2.inverse, $2, $3, @$) | openBlock program closeBlock -> new yy.BlockNode($1, $2, $2.inverse, $3, @$) | mustache -> $1