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]); }
;