Skip to content

Commit

Permalink
Add support for \\{ escapes
Browse files Browse the repository at this point in the history
Fixes #456
  • Loading branch information
kpdecker committed Mar 31, 2013
1 parent bcc15ea commit 9e4b59e
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 31 deletions.
64 changes: 33 additions & 31 deletions dist/handlebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -554,84 +554,86 @@ lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_STA

var YYSTATE=YY_START
switch($avoiding_name_collisions) {
case 0:
case 0: yy_.yytext = "\\"; return 14;
break;
case 1:
if(yy_.yytext.slice(-1) !== "\\") this.begin("mu");
if(yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1), this.begin("emu");
if(yy_.yytext) return 14;

break;
case 1: return 14;
case 2: return 14;
break;
case 2:
case 3:
if(yy_.yytext.slice(-1) !== "\\") this.popState();
if(yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1);
return 14;

break;
case 3: yy_.yytext = yy_.yytext.substr(0, yy_.yyleng-4); this.popState(); return 15;
break;
case 4: this.begin("par"); return 24;
case 4: yy_.yytext = yy_.yytext.substr(0, yy_.yyleng-4); this.popState(); return 15;
break;
case 5: return 16;
case 5: this.begin("par"); return 24;
break;
case 6: return 20;
case 6: return 16;
break;
case 7: return 19;
case 7: return 20;
break;
case 8: return 19;
break;
case 9: return 23;
case 9: return 19;
break;
case 10: return 23;
break;
case 11: this.popState(); this.begin('com');
case 11: return 23;
break;
case 12: yy_.yytext = yy_.yytext.substr(3,yy_.yyleng-5); this.popState(); return 15;
case 12: this.popState(); this.begin('com');
break;
case 13: return 22;
case 13: yy_.yytext = yy_.yytext.substr(3,yy_.yyleng-5); this.popState(); return 15;
break;
case 14: return 36;
case 14: return 22;
break;
case 15: return 35;
case 15: return 36;
break;
case 16: return 35;
break;
case 17: return 39;
case 17: return 35;
break;
case 18: /*ignore whitespace*/
case 18: return 39;
break;
case 19: this.popState(); return 18;
case 19: /*ignore whitespace*/
break;
case 20: this.popState(); return 18;
break;
case 21: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"'); return 30;
case 21: this.popState(); return 18;
break;
case 22: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\'/g,"'"); return 30;
case 22: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"'); return 30;
break;
case 23: yy_.yytext = yy_.yytext.substr(1); return 28;
case 23: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\'/g,"'"); return 30;
break;
case 24: return 32;
case 24: yy_.yytext = yy_.yytext.substr(1); return 28;
break;
case 25: return 32;
break;
case 26: return 31;
case 26: return 32;
break;
case 27: return 31;
break;
case 27: return 35;
case 28: return 35;
break;
case 28: yy_.yytext = yy_.yytext.substr(1, yy_.yyleng-2); return 35;
case 29: yy_.yytext = yy_.yytext.substr(1, yy_.yyleng-2); return 35;
break;
case 29: return 'INVALID';
case 30: return 'INVALID';
break;
case 30: /*ignore whitespace*/
case 31: /*ignore whitespace*/
break;
case 31: this.popState(); return 37;
case 32: this.popState(); return 37;
break;
case 32: return 5;
case 33: return 5;
break;
}
};
lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|$)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\{\{>)/,/^(?:\{\{#)/,/^(?:\{\{\/)/,/^(?:\{\{\^)/,/^(?:\{\{\s*else\b)/,/^(?:\{\{\{)/,/^(?:\{\{&)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{)/,/^(?:=)/,/^(?:\.(?=[} ]))/,/^(?:\.\.)/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}\}\})/,/^(?:\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@[a-zA-Z]+)/,/^(?:true(?=[}\s]))/,/^(?:false(?=[}\s]))/,/^(?:-?[0-9]+(?=[}\s]))/,/^(?:[a-zA-Z0-9_$-]+(?=[=}\s\/.]))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:\s+)/,/^(?:[a-zA-Z0-9_$-/]+)/,/^(?:$)/];
lexer.conditions = {"mu":{"rules":[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,32],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"com":{"rules":[3],"inclusive":false},"par":{"rules":[30,31],"inclusive":false},"INITIAL":{"rules":[0,1,32],"inclusive":true}};
lexer.rules = [/^(?:\\\\(?=(\{\{)))/,/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|$)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\{\{>)/,/^(?:\{\{#)/,/^(?:\{\{\/)/,/^(?:\{\{\^)/,/^(?:\{\{\s*else\b)/,/^(?:\{\{\{)/,/^(?:\{\{&)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{)/,/^(?:=)/,/^(?:\.(?=[} ]))/,/^(?:\.\.)/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}\}\})/,/^(?:\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@[a-zA-Z]+)/,/^(?:true(?=[}\s]))/,/^(?:false(?=[}\s]))/,/^(?:-?[0-9]+(?=[}\s]))/,/^(?:[a-zA-Z0-9_$-]+(?=[=}\s\/.]))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:\s+)/,/^(?:[a-zA-Z0-9_$-/]+)/,/^(?:$)/];
lexer.conditions = {"mu":{"rules":[5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,33],"inclusive":false},"emu":{"rules":[3],"inclusive":false},"com":{"rules":[4],"inclusive":false},"par":{"rules":[31,32],"inclusive":false},"INITIAL":{"rules":[0,1,2,33],"inclusive":true}};
return lexer;})()
parser.lexer = lexer;
function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser;
Expand Down
6 changes: 6 additions & 0 deletions spec/qunit_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ test("most basic", function() {
shouldCompileTo("{{foo}}", { foo: "foo" }, "foo");
});

test("escaping", function() {
shouldCompileTo("\\{{foo}}", { foo: "food" }, "{{foo}}");
shouldCompileTo("\\\\{{foo}}", { foo: "food" }, "\\food");
shouldCompileTo("\\\\ {{foo}}", { foo: "food" }, "\\\\ food");
});

test("compiling with a basic context", function() {
shouldCompileTo("Goodbye\n{{cruel}}\n{{world}}!", {cruel: "cruel", world: "world"}, "Goodbye\ncruel\nworld!",
"It works if all the required keys are provided");
Expand Down
1 change: 1 addition & 0 deletions src/handlebars.l
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

%%

"\\\\"/("{{") { yytext = "\\"; return 'CONTENT'; }
[^\x00]*?/("{{") {
if(yytext.slice(-1) !== "\\") this.begin("mu");
if(yytext.slice(-1) === "\\") yytext = yytext.substr(0,yyleng-1), this.begin("emu");
Expand Down

0 comments on commit 9e4b59e

Please sign in to comment.