diff options
-rw-r--r-- | lib/handlebars/compiler/helpers.js | 15 | ||||
-rw-r--r-- | spec/basic.js | 19 | ||||
-rw-r--r-- | src/handlebars.l | 2 | ||||
-rw-r--r-- | src/handlebars.yy | 8 |
4 files changed, 33 insertions, 11 deletions
diff --git a/lib/handlebars/compiler/helpers.js b/lib/handlebars/compiler/helpers.js index beaf988..4a502d8 100644 --- a/lib/handlebars/compiler/helpers.js +++ b/lib/handlebars/compiler/helpers.js @@ -12,6 +12,14 @@ export function SourceLocation(source, locInfo) { }; } +export function id(token) { + if (/^\[.*\]$/.test(token)) { + return token.substr(1, token.length - 2); + } else { + return token; + } +} + export function stripFlags(open, close) { return { open: open.charAt(2) === '~', @@ -34,10 +42,13 @@ export function preparePath(data, parts, locInfo) { depthString = ''; for(var i=0,l=parts.length; i<l; i++) { - var part = parts[i].part; + var part = parts[i].part, + // If we have [] syntax then we do not treat path references as operators, + // i.e. foo.[this] resolves to approximately context.foo['this'] + isLiteral = parts[i].original !== part; original += (parts[i].separator || '') + part; - if (part === '..' || part === '.' || part === 'this') { + if (!isLiteral && (part === '..' || part === '.' || part === 'this')) { if (dig.length > 0) { throw new Exception('Invalid path: ' + original, {loc: locInfo}); } else if (part === '..') { diff --git a/spec/basic.js b/spec/basic.js index e634d41..37aa8cf 100644 --- a/spec/basic.js +++ b/spec/basic.js @@ -227,10 +227,12 @@ describe("basic context", function() { }); it("this keyword nested inside path", function() { - var string = "{{#hellos}}{{text/this/foo}}{{/hellos}}"; shouldThrow(function() { - CompilerContext.compile(string); - }, Error); + CompilerContext.compile('{{#hellos}}{{text/this/foo}}{{/hellos}}'); + }, Error, 'Invalid path: text/this - 1:13'); + + shouldCompileTo('{{[this]}}', {'this': 'bar'}, 'bar'); + shouldCompileTo('{{text/[this]}}', {text: {'this': 'bar'}}, 'bar'); }); it("this keyword in helpers", function() { @@ -251,7 +253,16 @@ describe("basic context", function() { var string = "{{#hellos}}{{foo text/this/foo}}{{/hellos}}"; shouldThrow(function() { CompilerContext.compile(string); - }, Error); + }, Error, 'Invalid path: text/this - 1:17'); + + shouldCompileTo( + '{{foo [this]}}', + {foo: function(value) { return value; }, 'this': 'bar'}, + 'bar'); + shouldCompileTo( + '{{foo text/[this]}}', + {foo: function(value) { return value; }, text: {'this': 'bar'}}, + 'bar'); }); it('pass string literals', function() { diff --git a/src/handlebars.l b/src/handlebars.l index 55d8efc..ff21283 100644 --- a/src/handlebars.l +++ b/src/handlebars.l @@ -110,7 +110,7 @@ ID [^\s!"#%-,\.\/;->@\[-\^`\{-~]+/{LOOKAHEAD} <mu>{ID} return 'ID'; -<mu>'['[^\]]*']' yytext = strip(1,2); return 'ID'; +<mu>'['[^\]]*']' return 'ID'; <mu>. return 'INVALID'; <INITIAL,mu><<EOF>> return 'EOF'; diff --git a/src/handlebars.yy b/src/handlebars.yy index 01ef7fb..d67a7da 100644 --- a/src/handlebars.yy +++ b/src/handlebars.yy @@ -94,11 +94,11 @@ hash ; hashSegment - : ID EQUALS param -> new yy.HashPair($1, $3, yy.locInfo(@$)) + : ID EQUALS param -> new yy.HashPair(yy.id($1), $3, yy.locInfo(@$)) ; blockParams - : OPEN_BLOCK_PARAMS ID+ CLOSE_BLOCK_PARAMS -> $2 + : OPEN_BLOCK_PARAMS ID+ CLOSE_BLOCK_PARAMS -> yy.id($2) ; helperName @@ -125,6 +125,6 @@ path ; pathSegments - : pathSegments SEP ID { $1.push({part: $3, separator: $2}); $$ = $1; } - | ID -> [{part: $1}] + : pathSegments SEP ID { $1.push({part: yy.id($3), original: $3, separator: $2}); $$ = $1; } + | ID -> [{part: yy.id($1), original: $1}] ; |