summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.markdown187
-rw-r--r--Rakefile28
-rwxr-xr-xbin/handlebars2
-rw-r--r--lib/handlebars/base.js2
-rw-r--r--src/handlebars.l2
5 files changed, 127 insertions, 94 deletions
diff --git a/README.markdown b/README.markdown
index 703423d..97eb97d 100644
--- a/README.markdown
+++ b/README.markdown
@@ -1,3 +1,5 @@
+[![Build Status](https://secure.travis-ci.org/wycats/handlebars.js.png)](http://travis-ci.org/wycats/handlebars.js)
+
Handlebars.js
=============
@@ -16,21 +18,23 @@ In general, the syntax of Handlebars.js templates is a superset of Mustache temp
Once you have a template, use the Handlebars.compile method to compile the template into a function. The generated function takes a context argument, which will be used to render the template.
- var source = "<p>Hello, my name is {{name}}. I am from {{hometown}}. I have " +
- "{{kids.length}} kids:</p>" +
- "<ul>{{#kids}}<li>{{name}} is {{age}}</li>{{/kids}}</ul>";
- var template = Handlebars.compile(source);
+```js
+var source = "<p>Hello, my name is {{name}}. I am from {{hometown}}. I have " +
+ "{{kids.length}} kids:</p>" +
+ "<ul>{{#kids}}<li>{{name}} is {{age}}</li>{{/kids}}</ul>";
+var template = Handlebars.compile(source);
- var data = { "name": "Alan", "hometown": "Somewhere, TX",
- "kids": [{"name": "Jimmy", "age": "12"}, {"name": "Sally", "age": "4"}]};
- var result = template(data);
+var data = { "name": "Alan", "hometown": "Somewhere, TX",
+ "kids": [{"name": "Jimmy", "age": "12"}, {"name": "Sally", "age": "4"}]};
+var result = template(data);
- // Would render:
- // <p>Hello, my name is Alan. I am from Somewhere, TX. I have 2 kids:</p>
- // <ul>
- // <li>Jimmy is 12</li>
- // <li>Sally is 4</li>
- // </ul>
+// Would render:
+// <p>Hello, my name is Alan. I am from Somewhere, TX. I have 2 kids:</p>
+// <ul>
+// <li>Jimmy is 12</li>
+// <li>Sally is 4</li>
+// </ul>
+```
Registering Helpers
@@ -40,22 +44,23 @@ You can register helpers that Handlebars will use when evaluating your
template. Here's an example, which assumes that your objects have a URL
embedded in them, as well as the text for a link:
- Handlebars.registerHelper('link_to', function(context) {
- return "<a href='" + context.url + "'>" + context.body + "</a>";
- });
-
- var context = { posts: [{url: "/hello-world", body: "Hello World!"}] };
- var source = "<ul>{{#posts}}<li>{{{link_to this}}}</li>{{/posts}}</ul>"
+```js
+Handlebars.registerHelper('link_to', function(context) {
+ return "<a href='" + context.url + "'>" + context.body + "</a>";
+});
- var template = Handlebars.compile(source);
- template(context);
+var context = { posts: [{url: "/hello-world", body: "Hello World!"}] };
+var source = "<ul>{{#posts}}<li>{{{link_to this}}}</li>{{/posts}}</ul>"
- // Would render:
- //
- // <ul>
- // <li><a href='/hello-world'>Hello World!</a></li>
- // </ul>
+var template = Handlebars.compile(source);
+template(context);
+// Would render:
+//
+// <ul>
+// <li><a href='/hello-world'>Hello World!</a></li>
+// </ul>
+```
Escaping
--------
@@ -78,40 +83,50 @@ Handlebars.js supports an extended expression syntax that we call paths. Paths a
To display data from descendent contexts, use the `.` character. So, for example, if your data were structured like:
- var data = {"person": { "name": "Alan" }, company: {"name": "Rad, Inc." } };
+```js
+var data = {"person": { "name": "Alan" }, company: {"name": "Rad, Inc." } };
+```
you could display the person's name from the top-level context with the following expression:
- {{person.name}}
+```
+{{person.name}}
+```
You can backtrack using `../`. For example, if you've already traversed into the person object you could still display the company's name with an expression like `{{../company.name}}`, so:
- {{#person}}{{name}} - {{../company.name}}{{/person}}
+```
+{{#person}}{{name}} - {{../company.name}}{{/person}}
+```
would render:
- Alan - Rad, Inc.
+```
+Alan - Rad, Inc.
+```
### Strings
When calling a helper, you can pass paths or Strings as parameters. For
instance:
- Handlebars.registerHelper('link_to', function(title, context) {
- return "<a href='/posts" + context.id + "'>" + title + "</a>"
- });
+```js
+Handlebars.registerHelper('link_to', function(title, context) {
+ return "<a href='/posts" + context.id + "'>" + title + "</a>"
+});
- var context = { posts: [{url: "/hello-world", body: "Hello World!"}] };
- var source = '<ul>{{#posts}}<li>{{{link_to "Post" this}}}</li>{{/posts}}</ul>'
+var context = { posts: [{url: "/hello-world", body: "Hello World!"}] };
+var source = '<ul>{{#posts}}<li>{{{link_to "Post" this}}}</li>{{/posts}}</ul>'
- var template = Handlebars.compile(source);
- template(context);
+var template = Handlebars.compile(source);
+template(context);
- // Would render:
- //
- // <ul>
- // <li><a href='/hello-world'>Post!</a></li>
- // </ul>
+// Would render:
+//
+// <ul>
+// <li><a href='/hello-world'>Post!</a></li>
+// </ul>
+```
When you pass a String as a parameter to a helper, the literal String
gets passed to the helper function.
@@ -121,23 +136,25 @@ gets passed to the helper function.
Handlebars.js also adds the ability to define block helpers. Block helpers are functions that can be called from anywhere in the template. Here's an example:
- var source = "<ul>{{#people}}<li>{{{#link}}}{{name}}{{/link}}</li>{{/people}}</ul>";
- Handlebars.registerHelper('link', function(context, fn) {
- return '<a href="/people/' + this.__get__("id") + '">' + fn(this) + '</a>';
- });
- var template = Handlebars.compile(source);
-
- var data = { "people": [
- { "name": "Alan", "id": 1 },
- { "name": "Yehuda", "id": 2 }
- ]};
- template(data);
-
- // Should render:
- // <ul>
- // <li><a href="/people/1">Alan</a></li>
- // <li><a href="/people/2">Yehuda</a></li>
- // </ul>
+```js
+var source = "<ul>{{#people}}<li>{{{#link}}}{{name}}{{/link}}</li>{{/people}}</ul>";
+Handlebars.registerHelper('link', function(context, fn) {
+ return '<a href="/people/' + this.__get__("id") + '">' + fn(this) + '</a>';
+});
+var template = Handlebars.compile(source);
+
+var data = { "people": [
+ { "name": "Alan", "id": 1 },
+ { "name": "Yehuda", "id": 2 }
+ ]};
+template(data);
+
+// Should render:
+// <ul>
+// <li><a href="/people/1">Alan</a></li>
+// <li><a href="/people/2">Yehuda</a></li>
+// </ul>
+```
Whenever the block helper is called it is given two parameters, the argument that is passed to the helper, or the current context if no argument is passed and the compiled contents of the block. Inside of the block helper the value of `this` is the current context, wrapped to include a method named `__get__` that helps translate paths into values within the helpers.
@@ -148,37 +165,42 @@ Handlebars when it encounters a partial (`{{> partialName}}`). Partials
can either be String templates or compiled template functions. Here's an
example:
- var source = "<ul>{{#people}}<li>{{> link}}</li>{{/people}}</ul>";
-
- Handlebars.registerPartial('link', '<a href="/people/{{id}}">{{name}}</a>')
- var template = Handlebars.compile(source);
+```js
+var source = "<ul>{{#people}}<li>{{> link}}</li>{{/people}}</ul>";
- var data = { "people": [
- { "name": "Alan", "id": 1 },
- { "name": "Yehuda", "id": 2 }
- ]};
+Handlebars.registerPartial('link', '<a href="/people/{{id}}">{{name}}</a>')
+var template = Handlebars.compile(source);
- template(data);
+var data = { "people": [
+ { "name": "Alan", "id": 1 },
+ { "name": "Yehuda", "id": 2 }
+ ]};
- // Should render:
- // <ul>
- // <li><a href="/people/1">Alan</a></li>
- // <li><a href="/people/2">Yehuda</a></li>
- // </ul>
+template(data);
+// Should render:
+// <ul>
+// <li><a href="/people/1">Alan</a></li>
+// <li><a href="/people/2">Yehuda</a></li>
+// </ul>
+```
### Comments
You can add comments to your templates with the following syntax:
- {{! This is a comment }}
+```js
+{{! This is a comment }}
+```
You can also use real html comments if you want them to end up in the output.
- <div>
- {{! This comment will not end up in the output }}
- <!-- This comment will show up in the output -->
- </div>
+```html
+<div>
+ {{! This comment will not end up in the output }}
+ <!-- This comment will show up in the output -->
+</div>
+```
Precompiling Templates
@@ -248,11 +270,15 @@ changed.
Instead of:
- template(context, helpers, partials, [data])
+```js
+template(context, helpers, partials, [data])
+```
Use:
- template(context, {helpers: helpers, partials: partials, data: data})
+```js
+template(context, {helpers: helpers, partials: partials, data: data})
+```
Known Issues
------------
@@ -265,6 +291,7 @@ like to try out Handlebars.js in their browser.
* Don Park wrote an Express.js view engine adapter for Handlebars.js called [hbs](http://github.com/donpark/hbs).
* [sammy.js](http://github.com/quirkey/sammy) by Aaron Quint, a.k.a. quirkey, supports Handlebars.js as one of its template plugins.
* [SproutCore](http://www.sproutcore.com) uses Handlebars.js as its main templating engine, extending it with automatic data binding support.
+* Les Hill (@leshill) wrote a Rails Asset Pipeline gem named [handlebars_assets](http://github.com/leshill/handlebars_assets).
Helping Out
-----------
diff --git a/Rakefile b/Rakefile
index 904b468..c276485 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,20 +1,26 @@
require "rubygems"
require "bundler/setup"
+def compile_parser
+ system "jison src/handlebars.yy src/handlebars.l"
+ if $?.success?
+ File.open("lib/handlebars/compiler/parser.js", "w") do |file|
+ file.puts File.read("handlebars.js") + ";"
+ end
+
+ sh "rm handlebars.js"
+ else
+ puts "Failed to run Jison."
+ end
+end
+
file "lib/handlebars/compiler/parser.js" => ["src/handlebars.yy","src/handlebars.l"] do
if ENV['PATH'].split(':').any? {|folder| File.exists?(folder+'/jison')}
- system "jison src/handlebars.yy src/handlebars.l"
- if $?.success?
- File.open("lib/handlebars/compiler/parser.js", "w") do |file|
- file.puts File.read("handlebars.js") + ";"
- end
-
- sh "rm handlebars.js"
- else
- puts "Failed to run Jison."
- end
+ compile_parser
else
- puts "Jison is not installed. Try running `npm install jison`."
+ puts "Jison is not installed. Trying `npm install jison`."
+ sh "npm install jison -g"
+ compile_parser
end
end
diff --git a/bin/handlebars b/bin/handlebars
index 5e9dba8..2c03b0b 100755
--- a/bin/handlebars
+++ b/bin/handlebars
@@ -121,7 +121,7 @@ argv._.forEach(function(template) {
// Output the content
if (!argv.simple) {
- output.push('})()');
+ output.push('})();');
}
output = output.join('');
diff --git a/lib/handlebars/base.js b/lib/handlebars/base.js
index acf2dd6..60c2fcf 100644
--- a/lib/handlebars/base.js
+++ b/lib/handlebars/base.js
@@ -1,7 +1,7 @@
// BEGIN(BROWSER)
var Handlebars = {};
-Handlebars.VERSION = "1.0.beta.2";
+Handlebars.VERSION = "1.0.beta.4";
Handlebars.helpers = {};
Handlebars.partials = {};
diff --git a/src/handlebars.l b/src/handlebars.l
index 57ebb90..71c023e 100644
--- a/src/handlebars.l
+++ b/src/handlebars.l
@@ -27,7 +27,7 @@
<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>[a-zA-Z0-9_$-]+/[=}\s\/.] { return 'ID'; }
<mu>\[.*\] { yytext = yytext.substr(1, yyleng-2); return 'ID'; }
<mu>. { return 'INVALID'; }