From f8b245896dce9b0a8613870f39ff465a2a91a6ad Mon Sep 17 00:00:00 2001 From: wycats Date: Thu, 25 Nov 2010 16:12:50 -0800 Subject: [PATCH] Make the ID node capable of handling paths TODO: handle invalid paths in the tokenizer or parser TODO: invalidate "{{ foo/ bar }}" --- lib/handlebars/handlebars_lexer.js | 7 ++++++- lib/handlebars/printer.js | 7 ++++++- spec/tokenizer_spec.rb | 6 ++++++ src/handlebars.yy | 19 ++++++++++++------- test.js | 2 +- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/lib/handlebars/handlebars_lexer.js b/lib/handlebars/handlebars_lexer.js index b7454a44..af2da754 100644 --- a/lib/handlebars/handlebars_lexer.js +++ b/lib/handlebars/handlebars_lexer.js @@ -33,6 +33,11 @@ Handlebars.HandlebarsLexer.prototype.lex = function() { if(lookahead === "") return; if(this.state == "MUSTACHE") { + if(this.peek() === "/") { + this.getchar(); + return "SEP"; + } + // chomp optional whitespace while(this.peek() === " ") { this.ignorechar(); } @@ -64,7 +69,7 @@ Handlebars.HandlebarsLexer.prototype.lex = function() { // All other cases are IDs or errors } else { // grab alphanumeric characters - while(this.peek().match(/[0-9A-Za-z]/)) { this.getchar() } + while(this.peek().match(/[0-9A-Za-z\.]/)) { this.getchar() } // if any characters were grabbed => ID if(this.yytext.length) { return "ID" } diff --git a/lib/handlebars/printer.js b/lib/handlebars/printer.js index b388a3a4..dc03042d 100644 --- a/lib/handlebars/printer.js +++ b/lib/handlebars/printer.js @@ -79,7 +79,12 @@ Handlebars.PrintVisitor.prototype.STRING = function(string) { }; Handlebars.PrintVisitor.prototype.ID = function(id) { - return "ID:" + id.id; + var path = id.id.join("/"); + if(id.id.length > 1) { + return "PATH:" + path; + } else { + return "ID:" + path; + } }; Handlebars.PrintVisitor.prototype.content = function(content) { diff --git a/spec/tokenizer_spec.rb b/spec/tokenizer_spec.rb index 54063dba..c9047dac 100644 --- a/spec/tokenizer_spec.rb +++ b/spec/tokenizer_spec.rb @@ -36,6 +36,12 @@ describe "Tokenizer" do result[1].should be_token("ID", "foo") end + it "tokenizes a path as 'OPEN ID CLOSE'" do + result = tokenize("{{../foo/bar}}") + result.should match_tokens(%w(OPEN ID SEP ID SEP ID CLOSE)) + result[1].should be_token("ID", "..") + end + it "tokenizes a simple mustahe with spaces as 'OPEN ID CLOSE'" do result = tokenize("{{ foo }}") result.should match_tokens(%w(OPEN ID CLOSE)) diff --git a/src/handlebars.yy b/src/handlebars.yy index e1ef1a77..2e46f8b1 100644 --- a/src/handlebars.yy +++ b/src/handlebars.yy @@ -29,7 +29,7 @@ openBlock ; closeBlock - : OPEN_ENDBLOCK id CLOSE { } + : OPEN_ENDBLOCK path CLOSE { } ; mustache @@ -37,7 +37,7 @@ mustache ; partial - : OPEN_PARTIAL id CLOSE { $$ = new yy.PartialNode($2) } + : OPEN_PARTIAL path CLOSE { $$ = new yy.PartialNode($2) } ; simpleInverse @@ -45,8 +45,8 @@ simpleInverse ; inMustache - : id params { $$ = [$1].concat($2) } - | id { $$ = [$1] } + : path params { $$ = [$1].concat($2) } + | path { $$ = [$1] } ; params @@ -55,11 +55,16 @@ params ; param - : id { $$ = $1 } + : path { $$ = $1 } | STRING { $$ = new yy.StringNode($1) } ; -id - : ID { $$ = new yy.IdNode($1) } +path + : pathSegments { $$ = new yy.IdNode($1) } + ; + +pathSegments + : pathSegments SEP ID { $1.push($3); $$ = $1; } + | ID { $$ = [$1] } ; diff --git a/test.js b/test.js index b512dc2e..7a155c06 100644 --- a/test.js +++ b/test.js @@ -2,7 +2,7 @@ require.paths.push(__dirname + "/lib"); var Handlebars = require("handlebars").Handlebars; -var string = "foo {{ bar baz \"baz\" }}baz{{! foo bar baz }}{{#foo}} bar {{^}} baz {{/foo}}{{> partial }}{{# bar }}part1 {{^}} part2{{> foo }}{{/bar}}zomg" +var string = "foo {{ bar ../baz/bat/bam \"baz\" }}baz{{! foo bar baz }}{{#foo}} bar {{^}} baz {{/foo}}{{> partial }}{{# bar }}part1 {{^}} part2{{> foo }}{{/bar}}zomg" var ast = Handlebars.parse(string); require("sys").print(Handlebars.print(ast));