diff --git a/lib/handlebars/compiler/ast.js b/lib/handlebars/compiler/ast.js index 567e29747..3e9d87dba 100644 --- a/lib/handlebars/compiler/ast.js +++ b/lib/handlebars/compiler/ast.js @@ -37,6 +37,13 @@ Handlebars.AST.PartialNode = function(partialName, context) { this.context = context; }; +Handlebars.AST.RawBlockNode = function(mustache, content) { + this.type = "block"; + this.mustache = mustache; + this.mustache.isHelper = true; + this.mustache.params.splice(0, 0, { type: "STRING", "string": content } ); +}; + Handlebars.AST.BlockNode = function(mustache, program, inverse, close) { if(mustache.id.original !== close.original) { throw new Handlebars.Exception(mustache.id.original + " doesn't match " + close.original); diff --git a/spec/blocks.js b/spec/blocks.js index 1880eb584..ef1ef30a4 100644 --- a/spec/blocks.js +++ b/spec/blocks.js @@ -20,7 +20,7 @@ describe('blocks', function() { equal(result, "0. goodbye! 1. Goodbye! 2. GOODBYE! cruel world!", "The @index variable is used"); }); - + it("empty block", function() { var string = "{{#goodbyes}}{{/goodbyes}}cruel {{world}}!"; var hash = {goodbyes: [{text: "goodbye"}, {text: "Goodbye"}, {text: "GOODBYE"}], world: "world"}; diff --git a/spec/helpers.js b/spec/helpers.js index 9fb32e6c6..1ef56ef10 100644 --- a/spec/helpers.js +++ b/spec/helpers.js @@ -9,6 +9,26 @@ describe('helpers', function() { shouldCompileTo(string, [hash, helpers], "Goodbye"); }); + 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; + } }; + shouldCompileTo(string, [hash, helpers], " {{test}} ", + "raw block helper gets raw content"); + }); + + 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; + } }; + shouldCompileTo(string, [hash, helpers], " {{test}} 123", + "raw block helper gets raw content"); + }); + it("helper block with complex lookup expression", function() { var string = "{{#goodbyes}}{{../name}}{{/goodbyes}}"; var hash = {name: "Alan"}; diff --git a/src/handlebars.l b/src/handlebars.l index aa76eabd3..1e86183a7 100644 --- a/src/handlebars.l +++ b/src/handlebars.l @@ -1,5 +1,5 @@ -%x mu emu com +%x mu emu com raw %% @@ -18,8 +18,14 @@ return 'CONTENT'; } +"{{{{/"[^\s!"#%-,\.\/;->@\[-\^`\{-~]+/[=}\s\/.]"}}}}" { yytext = yytext.substr(5, yyleng-9); this.popState(); return 'END_RAW_BLOCK'; } +[^\x00]*?/("{{{{/") { return 'CONTENT'; } + [\s\S]*?"--}}" { yytext = yytext.substr(0, yyleng-4); this.popState(); return 'COMMENT'; } +"{{{{" { return 'OPEN_RAW_BLOCK'; } +"}}}}" { this.popState(); this.begin('raw'); return 'CLOSE_RAW_BLOCK'; } +"{{{{"[^\x00]*"}}}}" { yytext = yytext.substr(4, yyleng-8); this.popState(); return 'RAW_BLOCK'; } "{{>" { return 'OPEN_PARTIAL'; } "{{#" { return 'OPEN_BLOCK'; } "{{/" { return 'OPEN_ENDBLOCK'; } diff --git a/src/handlebars.yy b/src/handlebars.yy index 56b3b7040..a97f87f82 100644 --- a/src/handlebars.yy +++ b/src/handlebars.yy @@ -21,7 +21,8 @@ statements ; statement - : openInverse program closeBlock { $$ = new yy.BlockNode($1, $2.inverse, $2, $3); } + : openRawBlock CONTENT END_RAW_BLOCK { $$ = new yy.RawBlockNode($1, $2); } + | openInverse program closeBlock { $$ = new yy.BlockNode($1, $2.inverse, $2, $3); } | openBlock program closeBlock { $$ = new yy.BlockNode($1, $2, $2.inverse, $3); } | mustache { $$ = $1; } | partial { $$ = $1; } @@ -29,6 +30,10 @@ statement | COMMENT { $$ = new yy.CommentNode($1); } ; +openRawBlock + : OPEN_RAW_BLOCK inMustache CLOSE_RAW_BLOCK { $$ = new yy.MustacheNode($2[0], $2[1]); } + ; + openBlock : OPEN_BLOCK inMustache CLOSE { $$ = new yy.MustacheNode($2[0], $2[1]); } ;