Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/shannonmoeller/handlebars-layouts

Handlebars helpers which implement layout blocks similar to Jinja, Nunjucks (Swig), Pug (Jade), and Twig.
https://github.com/shannonmoeller/handlebars-layouts

blocks embed handlebars layout layouts nodejs partials templating

Last synced: about 2 months ago
JSON representation

Handlebars helpers which implement layout blocks similar to Jinja, Nunjucks (Swig), Pug (Jade), and Twig.

Awesome Lists containing this project

README

        

# `handlebars-layouts`

[![NPM version][npm-img]][npm-url] [![Downloads][downloads-img]][npm-url] [![Build Status][travis-img]][travis-url] [![Coverage Status][coveralls-img]][coveralls-url] [![Tip][amazon-img]][amazon-url]

Handlebars helpers which implement layout blocks similar to Jade, Jinja, Nunjucks, Swig, and Twig.

## Install

With [Node.js](http://nodejs.org):

$ npm install handlebars-layouts

With [Bower](http://bower.io):

$ bower install shannonmoeller/handlebars-layouts

## API

Helpers are generated by passing in your instance of Handlebars. This allows you to selectively register the helpers on various instances of Handlebars.

### `layouts(handlebars) : Object`

- `handlebars` `Handlebars` - An instance of Handlebars.

Generates an object containing the layout helpers suitible for passing into `registerHelper`.

```js
var handlebars = require('handlebars'),
layouts = require('handlebars-layouts');

handlebars.registerHelper(layouts(handlebars));
```

### `layouts.register(handlebars) : Object`

- `handlebars` `Handlebars` - An instance of Handlebars.

Both generates an object containing the layout helpers and registers them with Handlebars automatically.

```js
var handlebars = require('handlebars'),
layouts = require('handlebars-layouts');

layouts.register(handlebars);
```

## Helpers

### `{{#extend [partial] [context] [key=value ...]}}`

- `partial` `String` - Name of partial to render.
- `context` `Object` _(Optional)_ - A custom context for the partial.
- `attributes` `Object` _(Optional)_ - Arbitrary values that will be added to the partial data context.

Loads a layout partial of a given name and defines block content.

```handlebars
{{#extend "layout" foo="bar"}}
{{#content "title" mode="prepend"}}Example - {{/content}}
{{/extend}}
```

The `{{#extend}}` helper allows you to reason about your layouts as you would class extension where the above is equivalent to the following psuedo code:

```js
class Page extends Layout {
constructor() {
this.foo = 'bar';
}

title() {
return 'Example - ' + super();
}
}
```

### `{{#embed [partial] [context] [key=value ...]}}`

- `partial` `String` - Name of partial to render.
- `context` `Object` _(Optional)_ - A custom context for the partial.
- `attributes` `Object` _(Optional)_ - Arbitrary values that will be added to the partial data context.

Allows you to load a partial which itself extends from a layout. Blocks defined in embedded partials will not conflict with those in the primary layout.

```handlebars
{{#extend "layout"}}

{{#content "body"}}
{{#embed "gallery"}}
{{#content "body"}}


{{/content}}
{{/embed}}

{{#embed "modal" foo="bar" name=user.fullName}}
{{#content "title" mode="prepend"}}Image 1 - {{/content}}
{{#content "body"}}{{/content}}
{{/embed}}
{{/content}}

{{/extend}}
```

The `{{#embed}}` helper allows you to reason about your partials as you would class instantiation where the above is equivalent to the following psuedo code:

```js
class Page extends Layout {
body() {
var gallery = new Gallery();

gallery.replaceBody('\n');

var modal = new Modal({
foo: 'bar',
name: this.user.fullName
});

modal.prependTitle('Image 1 - ');
modal.replaceBody('');

return gallery.toString() + modal.toString();
}
}
```

### `{{#block [name]}}`

- `name` `String` - Block identifier.

Defines a named block, with optional default content. Blocks may have content appended, prepended, or replaced entirely when extending or embedding. You may append and prepend to the same block multiple times.

```handlebars
{{#block "header"}}

Hello World


{{/block}}

{{#block "main"}}

Lorem ipsum...


{{/block}}

{{#block "footer"}}

© 1970


{{/block}}
```

### `{{#content [name] mode="(append|prepend|replace)"}}`

- `name` `String` - Identifier of the block to modify.
- `mode` `String` _(Optional)_ - Means of providing block content. Default: `replace`.

Sets block content, optionally appending or prepending using the `mode` attribute.

Layout:

```handlebars

...

{{#block "header"}}

Hello World


{{/block}}

{{#block "main"}}

Lorem ipsum.


{{/block}}

{{#block "footer"}}

© 1999


{{/block}}

```

Page:

```handlebars
{{#extend "layout"}}

{{#content "header"}}

Goodnight Moon


{{/content}}

{{#content "main" mode="append"}}

Dolor sit amet.


{{/content}}

{{#content "footer" mode="prepend"}}

MIT License


{{/content}}

{{/extend}}
```

Output:

```handlebars

...

Goodnight Moon

Lorem ipsum.


Dolor sit amet.

MIT License


© 1999


```

### Conditional Blocks

There are times where you need to wrap a block with an element or use a different class depending on whether content has been provided for a block. For this purpose, the `content` helper may be called as a [subexpression](http://handlebarsjs.com/expressions.html#subexpressions) to check whether content has been provided for a block.

For example, you may wish to have an optional column in a grid layout:

```handlebars
{{!-- layout.hbs --}}



{{{block "left"}}}

{{#if (content "right")}}

{{{block "right"}}}

{{/if}}

```

For a page that only needs a left column, you may omit defining content for the `right` block:

```handlebars
{{!-- page.html --}}
{{#extend "layout"}}

{{#content "left"}}

Left


{{/content}}

{{/extend}}
```

Resulting in:

```html



Left




```

For a page with two columns, simply define content for both blocks:

```handlebars
{{!-- page.html --}}
{{#extend "layout"}}

{{#content "left"}}

Left


{{/content}}

{{#content "right"}}

Right


{{/content}}

{{/extend}}
```

Resulting in:

```html



Left




Right




```

## Example

### layout.hbs

```handlebars

{{#block "head"}}
{{title}}


{{/block}}



{{#block "header"}}

{{title}}


{{/block}}


{{#block "body"}}

Hello World


{{/block}}


{{#block "footer"}}
© 2013
{{/block}}

{{#block "foot"}}

{{/block}}

```

### page.html

```handlebars
{{#extend "layout"}}
{{#content "head" mode="append"}}

{{/content}}

{{#content "body"}}

Welcome Home


    {{#items}}
  • {{.}}

  • {{/items}}

{{/content}}

{{#content "foot" mode="prepend"}}

{{/content}}
{{/extend}}
```

### Putting Them Together

```js
var handlebars = require('handlebars');
var layouts = require('handlebars-layouts');

// Register helpers
handlebars.registerHelper(layouts(handlebars));

// Register partials
handlebars.registerPartial('layout', fs.readFileSync('layout.hbs', 'utf8'));

// Compile template
var template = handlebars.compile(fs.readFileSync('page.html', 'utf8'));

// Render template
var output = template({
title: 'Layout Test',
items: [
'apple',
'orange',
'banana'
]
});

console.log(output);
```

### Output (prettified for readability)

```handlebars

Layout Test




Layout Test



Welcome Home



  • apple

  • orange

  • banana



© 2013


```

## Contribute

Standards for this project, including tests, code coverage, and semantics are enforced with a build tool. Pull requests must include passing tests with 100% code coverage and no linting errors.

## Test

$ npm test

----

MIT © [Shannon Moeller](http://shannonmoeller.com)

[amazon-img]: https://img.shields.io/badge/tip-jar-yellow.svg?style=flat-square
[amazon-url]: https://www.amazon.com/gp/registry/wishlist/1VQM9ID04YPC5?sort=universal-price
[coveralls-img]: http://img.shields.io/coveralls/shannonmoeller/handlebars-layouts/master.svg?style=flat-square
[coveralls-url]: https://coveralls.io/r/shannonmoeller/handlebars-layouts
[downloads-img]: http://img.shields.io/npm/dm/handlebars-layouts.svg?style=flat-square
[npm-img]: http://img.shields.io/npm/v/handlebars-layouts.svg?style=flat-square
[npm-url]: https://npmjs.org/package/handlebars-layouts
[travis-img]: http://img.shields.io/travis/shannonmoeller/handlebars-layouts/master.svg?style=flat-square
[travis-url]: https://travis-ci.org/shannonmoeller/handlebars-layouts