From 9d353bd3dd24b1e975ddf14a77179d4ab016706c Mon Sep 17 00:00:00 2001 From: Daniel Marcotte Date: Wed, 6 Nov 2013 08:20:49 -0800 Subject: [PATCH] Fix "\\{{" immediately following "\{{" Escaped-escape mustaches ("\\{{") immediately following escaped mustaches ("\{{") were being handled incorrectly. Fix the lookahead to make sure yytext still contains the appropriate slashes when we pop out of so they can be handled consistently by the initial state. --- spec/tokenizer.js | 22 ++++++++++++++++------ src/handlebars.l | 6 +++--- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/spec/tokenizer.js b/spec/tokenizer.js index de981e42..69bc7b27 100644 --- a/spec/tokenizer.js +++ b/spec/tokenizer.js @@ -88,15 +88,15 @@ describe('Tokenizer', function() { it('supports escaping multiple escape characters', function() { var result = tokenize("{{foo}} \\\\{{bar}} \\\\{{baz}}"); - result.should.match_tokens(['OPEN', 'ID', 'CLOSE', 'CONTENT', 'OPEN', 'ID', 'CLOSE', 'CONTENT', 'OPEN', 'ID', 'CLOSE']); + result.should.match_tokens(['OPEN', 'ID', 'CLOSE', 'CONTENT', 'OPEN', 'ID', 'CLOSE', 'CONTENT', 'OPEN', 'ID', 'CLOSE']); - result[3].should.be_token("CONTENT", " \\"); - result[5].should.be_token("ID", "bar"); - result[7].should.be_token("CONTENT", " \\"); - result[9].should.be_token("ID", "baz"); + result[3].should.be_token("CONTENT", " \\"); + result[5].should.be_token("ID", "bar"); + result[7].should.be_token("CONTENT", " \\"); + result[9].should.be_token("ID", "baz"); }); - it('supports mixed escaped delimiters and escaped escape characters', function() { + it('supports escaped mustaches after escaped escape characters', function() { var result = tokenize("{{foo}} \\\\{{bar}} \\{{baz}}"); result.should.match_tokens(['OPEN', 'ID', 'CLOSE', 'CONTENT', 'OPEN', 'ID', 'CLOSE', 'CONTENT', 'CONTENT', 'CONTENT']); @@ -107,6 +107,16 @@ describe('Tokenizer', function() { result[8].should.be_token("CONTENT", "{{baz}}"); }); + it('supports escaped escape characters after escaped mustaches', function() { + var result = tokenize("{{foo}} \\{{bar}} \\\\{{baz}}"); + result.should.match_tokens(['OPEN', 'ID', 'CLOSE', 'CONTENT', 'CONTENT', 'CONTENT', 'OPEN', 'ID', 'CLOSE']); + + result[4].should.be_token("CONTENT", "{{bar}} "); + result[5].should.be_token("CONTENT", "\\"); + result[6].should.be_token("OPEN", "{{"); + result[7].should.be_token("ID", "baz"); + }); + it('supports escaped escape character on a triple stash', function() { var result = tokenize("{{foo}} \\\\{{{bar}}} {{baz}}"); result.should.match_tokens(['OPEN', 'ID', 'CLOSE', 'CONTENT', 'OPEN_UNESCAPED', 'ID', 'CLOSE_UNESCAPED', 'CONTENT', 'OPEN', 'ID', 'CLOSE']); diff --git a/src/handlebars.l b/src/handlebars.l index ddb7fe9c..42054708 100644 --- a/src/handlebars.l +++ b/src/handlebars.l @@ -43,9 +43,9 @@ ID [^\s!"#%-,\.\/;->@\[-\^`\{-~]+/{LOOKAHEAD} [^\x00]+ return 'CONTENT'; -[^\x00]{2,}?/("{{"|<>) { - if(yytext.slice(-1) !== "\\") this.popState(); - if(yytext.slice(-1) === "\\") strip(0,1); +// marks CONTENT up to the next mustache or escaped mustache +[^\x00]{2,}?/("{{"|"\\{{"|"\\\\{{"|<>) { + this.popState(); return 'CONTENT'; }