Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add support for \\{ escapes

Fixes #456
  • Loading branch information...
commit 9e4b59e815b1f557c31fe5abc36b9be8aa0cf34a 1 parent bcc15ea
@kpdecker kpdecker authored
Showing with 40 additions and 31 deletions.
  1. +33 −31 dist/handlebars.js
  2. +6 −0 spec/qunit_spec.js
  3. +1 −0  src/handlebars.l
View
64 dist/handlebars.js
@@ -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;
View
6 spec/qunit_spec.js
@@ -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");
View
1  src/handlebars.l
@@ -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");
Please sign in to comment.
Something went wrong with that request. Please try again.