summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/handlebars/ast.js5
-rw-r--r--lib/handlebars/compiler.js4
-rw-r--r--lib/handlebars/printer.js4
-rw-r--r--spec/parser_spec.rb25
-rw-r--r--spec/qunit_spec.js58
-rw-r--r--spec/tokenizer_spec.rb16
-rw-r--r--src/handlebars.l4
-rw-r--r--src/handlebars.yy2
8 files changed, 114 insertions, 4 deletions
diff --git a/lib/handlebars/ast.js b/lib/handlebars/ast.js
index 86960ab..1002bd5 100644
--- a/lib/handlebars/ast.js
+++ b/lib/handlebars/ast.js
@@ -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;
diff --git a/lib/handlebars/compiler.js b/lib/handlebars/compiler.js
index d66b1db..42e5c2c 100644
--- a/lib/handlebars/compiler.js
+++ b/lib/handlebars/compiler.js
@@ -228,6 +228,10 @@ Handlebars.JavaScriptCompiler = function() {};
this.opcode('push', integer.integer);
},
+ BOOLEAN: function(boolean) {
+ this.opcode('push', boolean.boolean);
+ },
+
comment: function() {},
// HELPERS
diff --git a/lib/handlebars/printer.js b/lib/handlebars/printer.js
index 6388f01..ff3f038 100644
--- a/lib/handlebars/printer.js
+++ b/lib/handlebars/printer.js
@@ -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) {
diff --git a/spec/parser_spec.rb b/spec/parser_spec.rb
index 941887d..ead3315 100644
--- a/spec/parser_spec.rb
+++ b/spec/parser_spec.rb
@@ -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 "
diff --git a/spec/qunit_spec.js b/spec/qunit_spec.js
index 64fee91..65100e0 100644
--- a/spec/qunit_spec.js
+++ b/spec/qunit_spec.js
@@ -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});
diff --git a/spec/tokenizer_spec.rb b/spec/tokenizer_spec.rb
index d98ee3d..9b61fe2 100644
--- a/spec/tokenizer_spec.rb
+++ b/spec/tokenizer_spec.rb
@@ -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)
diff --git a/src/handlebars.l b/src/handlebars.l
index 895974a..0d3cdf0 100644
--- a/src/handlebars.l
+++ b/src/handlebars.l
@@ -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'; }
diff --git a/src/handlebars.yy b/src/handlebars.yy
index 02f8e21..d3d41df 100644
--- a/src/handlebars.yy
+++ b/src/handlebars.yy
@@ -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