Add BOOLEAN support

This commit is contained in:
tomhuda
2011-06-01 22:57:22 -07:00
parent 0f78345d0c
commit 1482f1ae72
8 changed files with 114 additions and 4 deletions
+5
View File
@@ -88,6 +88,11 @@ var Handlebars = require("handlebars");
this.integer = integer;
};
Handlebars.AST.BooleanNode = function(boolean) {
this.type = "BOOLEAN";
this.boolean = boolean;
};
Handlebars.AST.CommentNode = function(comment) {
this.type = "comment";
this.comment = comment;
+4
View File
@@ -228,6 +228,10 @@ Handlebars.JavaScriptCompiler = function() {};
this.opcode('push', integer.integer);
},
BOOLEAN: function(boolean) {
this.opcode('push', boolean.boolean);
},
comment: function() {},
// HELPERS
+4
View File
@@ -113,6 +113,10 @@ Handlebars.PrintVisitor.prototype.INTEGER = function(integer) {
return "INTEGER{" + integer.integer + "}";
}
Handlebars.PrintVisitor.prototype.BOOLEAN = function(boolean) {
return "BOOLEAN{" + boolean.boolean + "}";
}
Handlebars.PrintVisitor.prototype.ID = function(id) {
var path = id.parts.join("/");
if(id.parts.length > 1) {
+25
View File
@@ -96,6 +96,10 @@ describe "Parser" do
"INTEGER{#{string}}"
end
def boolean(string)
"BOOLEAN{#{string}}"
end
def hash(*pairs)
"HASH{" + pairs.map {|k,v| "#{k}=#{v}" }.join(", ") + "}"
end
@@ -138,6 +142,14 @@ describe "Parser" do
mustache id("foo"), [], hash(["bar", integer("1")])
end
ast_for("{{foo bar=true}}").should == program do
mustache id("foo"), [], hash(["bar", boolean("true")])
end
ast_for("{{foo bar=false}}").should == program do
mustache id("foo"), [], hash(["bar", boolean("false")])
end
ast_for("{{foo bar=baz bat=bam}}").should == program do
mustache id("foo"), [], hash(["bar", "ID:baz"], ["bat", "ID:bam"])
end
@@ -153,6 +165,14 @@ describe "Parser" do
ast_for("{{foo omg bar=baz bat=\"bam\" baz=1}}").should == program do
mustache id("foo"), [id("omg")], hash(["bar", id("baz")], ["bat", string("bam")], ["baz", integer("1")])
end
ast_for("{{foo omg bar=baz bat=\"bam\" baz=true}}").should == program do
mustache id("foo"), [id("omg")], hash(["bar", id("baz")], ["bat", string("bam")], ["baz", boolean("true")])
end
ast_for("{{foo omg bar=baz bat=\"bam\" baz=false}}").should == program do
mustache id("foo"), [id("omg")], hash(["bar", id("baz")], ["bat", string("bam")], ["baz", boolean("false")])
end
end
it "parses mustaches with string parameters" do
@@ -163,6 +183,11 @@ describe "Parser" do
ast_for("{{foo 1}}").should == program { mustache id("foo"), [integer("1")] }
end
it "parses mustaches with BOOLEAN parameters" do
ast_for("{{foo true}}").should == program { mustache id("foo"), [boolean("true")] }
ast_for("{{foo false}}").should == program { mustache id("foo"), [boolean("false")] }
end
it "parses contents followed by a mustache" do
ast_for("foo bar {{baz}}").should == program do
content "foo bar "
+55 -3
View File
@@ -434,10 +434,15 @@ test("GH-14: a partial preceding a selector", function() {
module("String literal parameters");
test("simple literals work", function() {
var string = 'Message: {{hello "world" 12}}';
var string = 'Message: {{hello "world" 12 true false}}';
var hash = {};
var helpers = {hello: function(param, times) { return "Hello " + param + " " + times + " times"; }}
shouldCompileTo(string, [hash, helpers], "Message: Hello world 12 times", "template with a simple String literal");
var helpers = {hello: function(param, times, bool1, bool2) {
if(typeof times !== 'number') { times = "NaN"; }
if(typeof bool1 !== 'boolean') { bool1 = "NaB"; }
if(typeof bool2 !== 'boolean') { bool2 = "NaB"; }
return "Hello " + param + " " + times + " times: " + bool1 + " " + bool2;
}}
shouldCompileTo(string, [hash, helpers], "Message: Hello world 12 times: true false", "template with a simple String literal");
});
test("using a quote in the middle of a parameter raises an error", function() {
@@ -695,6 +700,30 @@ test("helpers can take an optional hash", function() {
equals(result, "GOODBYE CRUEL WORLD 12 TIMES");
});
test("helpers can take an optional hash with booleans", function() {
var helpers = {
goodbye: function(options) {
if (options.hash.print === true) {
return "GOODBYE " + options.hash.cruel + " " + options.hash.world;
} else if (options.hash.print === false) {
return "NOT PRINTING";
} else {
return "THIS SHOULD NOT HAPPEN";
}
}
};
var context = {};
var template = Handlebars.compile('{{goodbye cruel="CRUEL" world="WORLD" print=true}}');
var result = template(context, {helpers: helpers});
equals(result, "GOODBYE CRUEL WORLD");
var template = Handlebars.compile('{{goodbye cruel="CRUEL" world="WORLD" print=false}}');
var result = template(context, {helpers: helpers});
equals(result, "NOT PRINTING");
});
test("block helpers can take an optional hash", function() {
var template = Handlebars.compile('{{#goodbye cruel="CRUEL" times=12}}world{{/goodbye}}');
@@ -708,6 +737,29 @@ test("block helpers can take an optional hash", function() {
equals(result, "GOODBYE CRUEL world 12 TIMES");
});
test("block helpers can take an optional hash with booleans", function() {
var helpers = {
goodbye: function(options) {
if (options.hash.print === true) {
return "GOODBYE " + options.hash.cruel + " " + options.fn(this);
} else if (options.hash.print === false) {
return "NOT PRINTING";
} else {
return "THIS SHOULD NOT HAPPEN";
}
}
};
var template = Handlebars.compile('{{#goodbye cruel="CRUEL" print=true}}world{{/goodbye}}');
var result = template({}, {helpers: helpers});
equals(result, "GOODBYE CRUEL world");
var template = Handlebars.compile('{{#goodbye cruel="CRUEL" print=false}}world{{/goodbye}}');
var result = template({}, {helpers: helpers});
equals(result, "NOT PRINTING");
});
test("arguments to helpers can be retrieved from options hash in string form", function() {
var template = Handlebars.compile('{{wycats is.a slave.driver}}', {stringParams: true});
+16
View File
@@ -177,6 +177,16 @@ describe "Tokenizer" do
result[2].should be_token("INTEGER", "1")
end
it "tokenizes booleans" do
result = tokenize(%|{{ foo true }}|)
result.should match_tokens(%w(OPEN ID BOOLEAN CLOSE))
result[2].should be_token("BOOLEAN", "true")
result = tokenize(%|{{ foo false }}|)
result.should match_tokens(%w(OPEN ID BOOLEAN CLOSE))
result[2].should be_token("BOOLEAN", "false")
end
it "tokenizes hash arguments" do
result = tokenize("{{ foo bar=baz }}")
result.should match_tokens %w(OPEN ID ID EQUALS ID CLOSE)
@@ -187,6 +197,12 @@ describe "Tokenizer" do
result = tokenize("{{ foo bar baz=1 }}")
result.should match_tokens %w(OPEN ID ID ID EQUALS INTEGER CLOSE)
result = tokenize("{{ foo bar baz=true }}")
result.should match_tokens %w(OPEN ID ID ID EQUALS BOOLEAN CLOSE)
result = tokenize("{{ foo bar baz=false }}")
result.should match_tokens %w(OPEN ID ID ID EQUALS BOOLEAN CLOSE)
result = tokenize("{{ foo bar\n baz=bat }}")
result.should match_tokens %w(OPEN ID ID ID EQUALS ID CLOSE)
+3 -1
View File
@@ -24,7 +24,9 @@
<mu>"}}}" { this.begin("INITIAL"); return 'CLOSE'; }
<mu>"}}" { this.begin("INITIAL"); return 'CLOSE'; }
<mu>'"'("\\"["]|[^"])*'"' { yytext = yytext.substr(1,yyleng-2).replace(/\\"/g,'"'); return 'STRING'; }
<mu>[0-9]+/[}\s] { return 'INTEGER' }
<mu>"true"/[}\s] { return 'BOOLEAN'; }
<mu>"false"/[}\s] { return 'BOOLEAN'; }
<mu>[0-9]+/[}\s] { return 'INTEGER'; }
<mu>[a-zA-Z0-9_$-]+/[=}\s/.] { return 'ID'; }
<mu>. { return 'INVALID'; }
+2
View File
@@ -69,6 +69,7 @@ param
: path { $$ = $1 }
| STRING { $$ = new yy.StringNode($1) }
| INTEGER { $$ = new yy.IntegerNode($1) }
| BOOLEAN { $$ = new yy.BooleanNode($1) }
;
hash
@@ -84,6 +85,7 @@ hashSegment
: ID EQUALS path { $$ = [$1, $3] }
| ID EQUALS STRING { $$ = [$1, new yy.StringNode($3)] }
| ID EQUALS INTEGER { $$ = [$1, new yy.IntegerNode($3)] }
| ID EQUALS BOOLEAN { $$ = [$1, new yy.BooleanNode($3)] }
;
path