Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

fix pull request

  • Loading branch information...
commit e70aafd79849b1ca6b2113e9dac1ee94d6598f8f 1 parent 4d4635c
@mgutz mgutz authored
View
25 README.md
@@ -30,17 +30,12 @@ Partials may use any extension, which is better for syntax highlighting.
## Syntax
-To mark where layout should insert page,
-
- {{{body}}}
-To declare the layout for a page, use handlebars comment. `LAYOUT` is a relative path from template.
- {{!< LAYOUT}}
+To mark where layout should insert page,
+ {{{body}}}
-If a layout is not declared within a template, then `options.defaultLayout` is
-used if present.
To declare a block placeholder in layout.
@@ -52,6 +47,22 @@ To define block content in a page.
CONTENT HERE
{{/contentFor}}
+There are three ways to use a layout
+
+1. Declarative within a page. Use handlebars comment. `LAYOUT` is a relative path from template.
+
+ {{!< LAYOUT}}
+
+2. As an option to render
+
+ res.render('veggies', {
+ title: 'My favorite veggies',
+ veggies: veggies,
+ layout: 'layout/veggie'
+ });
+
+3. Lastly, use `defaultLayout` if specified in hbs configuration options.
+
## Example
View
15 example/app.js
@@ -17,6 +17,13 @@ var fruits = [
{name: 'pear'}
];
+
+var veggies = [
+ {name: 'asparagus'},
+ {name: 'carrot'},
+ {name: 'spinach'}
+];
+
app.get('/', function(req, res) {
res.render('index', {
title: 'express-hbs example'
@@ -30,5 +37,13 @@ app.get('/fruits', function(req, res) {
});
});
+app.get('/veggies', function(req, res) {
+ res.render('veggies', {
+ title: 'My favorite veggies',
+ veggies: veggies,
+ layout: 'layout/veggie'
+ });
+});
+
app.listen(3000);
console.log('Express server listening on port 3000');
View
2  example/views/fruits/index.hbs
@@ -1,5 +1,5 @@
<!-- relative path to layout -->
-{{!< ../layout/inner}}
+{{!< ../layout/fruits}}
{{#contentFor "pageStyles"}}
<style>
View
9 example/views/index.hbs
@@ -10,7 +10,7 @@
{{#contentFor 'pageScripts'}}
<script>
$(function() {
- $('p').click(function() {
+ $('.clicker').click(function() {
$(this).text('Hello express-hbs!');
});
});
@@ -20,4 +20,9 @@
<h1>{{title}}</h1>
<p class='clicker'>Click me!</p>
-<a href='/fruits'>Favorite fruits</a>
+<p>
+ <a href='/fruits'>Favorite fruits</a>
+</p>
+<p>
+ <a href='/veggies'>Vegetables</a>
+</p>
View
1  example/views/layout/default.hbs
@@ -5,6 +5,7 @@
{{{block "pageStyles"}}}
</head>
<body>
+ <h2>DEFAULT LAYOUT</h2>
<!-- Placeholder for page content. -->
{{{body}}}
View
2  example/views/layout/inner.hbs → example/views/layout/fruits.hbs
@@ -5,7 +5,7 @@
{{{block "pageStyles"}}}
</head>
<body>
- <h2>INNER LAYOUT</h2>
+ <h2>DECLARATIVE LAYOUT</h2>
<!-- Placeholder for page content. -->
{{{body}}}
View
18 example/views/layout/veggie.hbs
@@ -0,0 +1,18 @@
+<html>
+ <head>
+ <title>{{title}}</title>
+ <link type="text/css" rel="stylesheet" href="/css/style.css"/>
+ {{{block "pageStyles"}}}
+ </head>
+ <body>
+ <h2>PROGRAMMATIC LAYOUT</h2>
+ <!-- Placeholder for page content. -->
+ {{{body}}}
+
+ <!-- Partials are common snippets to be used 1 or more pages. -->
+ {{> scripts}}
+
+ <!-- A block is placeholder for pieces of content defined in a page. -->
+ {{{block "pageScripts"}}}
+ </body>
+</html>
View
15 example/views/veggies.hbs
@@ -0,0 +1,15 @@
+{{#contentFor "pageStyles"}}
+<style>
+ li {
+ color: #800;
+ }
+</style>
+{{/contentFor}}
+
+
+<h1>{{title}}</h1>
+<ul>
+ {{#each veggies}}
+ <li>{{this.name}}</li>
+ {{/each}}
+</ul>
View
59 lib/hbs.js
@@ -3,26 +3,38 @@ var path = require('path');
exports.handlebars = require('handlebars');
/**
- * handle async helpers
+ * Handle async helpers
*/
var async = require('./async');
-// cache for templates, express 3.x doesn't do this for us
+/**
+ * Cache for templates, express 3.x doesn't do this for us
+ */
var cache = {};
-// Blocks for layouts. Is this safe? What happens if the same block is used on multiple connections?
-// Isn't there a chance block and contentFor are not in sync. The template and layout are processed
-// asynchronously.
+/**
+ * Blocks for layouts. Is this safe? What happens if the same block is used on multiple connections?
+ * Isn't there a chance block and contentFor are not in sync. The template and layout are processed
+ * asynchronously.
+ */
var blocks = {};
+/**
+ * Absolute path to partials directory.
+ */
var partialsDir;
+/**
+ * Keep copy of options configuration.
+ */
var _options;
+/**
+ * Holds the default compiled layout if specified in options configuration.
+ */
var defaultLayoutTemplate;
-
/**
* Regex pattern for layout directive. {{!< layout }}
*/
@@ -89,7 +101,6 @@ function cacheLayout(layoutFile, useCache, cb) {
}
-
/**
* Cache partial templates found under <views>/partials.
*
@@ -243,17 +254,35 @@ var _express3 = function(filename, options, cb) {
parseLayout(str, filename, function(err, layoutTemplate) {
if (err) return cb(err);
- // If no layout, try using options config or default
- if (!layoutTemplate && options.layout)
- layoutTemplate = path.resolve(path.join(path.dirname(filename), options.layout));
- else if (!layoutTemplate && defaultLayoutTemplate)
- layoutTemplate = defaultLayoutTemplate;
+ function renderIt(layoutTemplate) {
+ if (layoutTemplate && options.cache) {
+ cache[filename].layoutTemplate = layoutTemplate;
+ }
+ return render(template, locals, layoutTemplate, cb);
+ }
+
+ // Determine which layout to use
+ // 1. Layout specified in template
+ if (layoutTemplate) {
+ renderIt(layoutTemplate);
+ }
+
+ // 2. Layout specified by options from render
+ else if (options.layout) {
+ var layoutFile = path.resolve(path.join(path.dirname(filename), options.layout));
+ cacheLayout(layoutFile, options.cache, function(err, layoutTemplate) {
+ if (err) return cb(err);
+ renderIt(layoutTemplate);
+ });
+ }
- if (layoutTemplate && options.cache) {
- cache[filename].layoutTemplate = layoutTemplate;
+ // 3. Default layout specified when middleware was configured.
+ else if (defaultLayoutTemplate) {
+ renderIt(defaultLayoutTemplate);
}
- return render(template, locals, layoutTemplate, cb);
+ // render without a template
+ else renderIt(null);
});
});
}
Please sign in to comment.
Something went wrong with that request. Please try again.