3.1.4 • Published 7 years ago

handlebars-layouts v3.1.4

Weekly downloads
62,078
License
MIT
Repository
github
Last release
7 years ago

handlebars-layouts

NPM version Downloads Build Status Coverage Status Tip

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

Install

With Node.js:

$ npm install handlebars-layouts

With Bower:

$ 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.

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.

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.

{{#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:

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.

{{#extend "layout"}}

    {{#content "body"}}
        {{#embed "gallery"}}
            {{#content "body"}}
                <img src="1.png" alt="" />
                <img src="2.png" alt="" />
            {{/content}}
        {{/embed}}

        {{#embed "modal" foo="bar" name=user.fullName}}
            {{#content "title" mode="prepend"}}Image 1 - {{/content}}
            {{#content "body"}}<img src="1.png" alt="" />{{/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:

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

        gallery.replaceBody('<img src="1.png" alt="" />\n<img src="2.png" alt="" />');

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

        modal.prependTitle('Image 1 - ');
        modal.replaceBody('<img src="1.png" alt="" />');

        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.

{{#block "header"}}
    <h1>Hello World</h1>
{{/block}}

{{#block "main"}}
    <p>Lorem ipsum...</p>
{{/block}}

{{#block "footer"}}
    <p>&copy; 1970</p>
{{/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:

<html>
    ...
    <body>
        {{#block "header"}}
            <h1>Hello World</h1>
        {{/block}}

        {{#block "main"}}
            <p>Lorem ipsum.</p>
        {{/block}}

        {{#block "footer"}}
            <p>&copy; 1999</p>
        {{/block}}
    </body>
</html>

Page:

{{#extend "layout"}}

    {{#content "header"}}
        <h1>Goodnight Moon</h1>
    {{/content}}

    {{#content "main" mode="append"}}
        <p>Dolor sit amet.</p>
    {{/content}}

    {{#content "footer" mode="prepend"}}
        <p>MIT License</p>
    {{/content}}

{{/extend}}

Output:

<html>
    ...
    <body>
        <h1>Goodnight Moon</h1>

        <p>Lorem ipsum.</p>
        <p>Dolor sit amet.</p>

        <p>MIT License</p>
        <p>&copy; 1999</p>
    </body>
</html>

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 to check whether content has been provided for a block.

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

{{!-- layout.hbs --}}
<div class="grid">
    <div class="grid-col {{#if (content "right")}}grid-col_2of3{{else}}grid-col_full{{/if}}">
        {{{block "left"}}}
    </div>
    {{#if (content "right")}}
        <div class="grid-col grid-col_1of3">
            {{{block "right"}}}
        </div>
    {{/if}}
</div>

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

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

    {{#content "left"}}
        <p>Left</p>
    {{/content}}

{{/extend}}

Resulting in:

<div class="grid">
    <div class="grid-col grid-col_full">
        <p>Left</p>
    </div>
</div>

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

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

    {{#content "left"}}
        <p>Left</p>
    {{/content}}

    {{#content "right"}}
        <p>Right</p>
    {{/content}}

{{/extend}}

Resulting in:

<div class="grid">
    <div class="grid-col grid-col_2of3">
        <p>Left</p>
    </div>
    <div class="grid-col grid-col_1of3">
        <p>Right</p>
    </div>
</div>

Example

layout.hbs

<!doctype html>
<html lang="en-us">
<head>
    {{#block "head"}}
        <title>{{title}}</title>

        <link rel="stylesheet" href="assets/css/screen.css" />
    {{/block}}
</head>
<body>
    <div class="site">
        <div class="site-hd" role="banner">
            {{#block "header"}}
                <h1>{{title}}</h1>
            {{/block}}
        </div>

        <div class="site-bd" role="main">
            {{#block "body"}}
                <h2>Hello World</h2>
            {{/block}}
        </div>

        <div class="site-ft" role="contentinfo">
            {{#block "footer"}}
                <small>&copy; 2013</small>
            {{/block}}
        </div>
    </div>

    {{#block "foot"}}
        <script src="assets/js/controllers/home.js"></script>
    {{/block}}
</body>
</html>

page.html

{{#extend "layout"}}
    {{#content "head" mode="append"}}
        <link rel="stylesheet" href="assets/css/home.css" />
    {{/content}}

    {{#content "body"}}
        <h2>Welcome Home</h2>

        <ul>
            {{#items}}
                <li>{{.}}</li>
            {{/items}}
        </ul>
    {{/content}}

    {{#content "foot" mode="prepend"}}
        <script src="assets/js/analytics.js"></script>
    {{/content}}
{{/extend}}

Putting Them Together

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)

<!doctype html>
<html lang="en-us">
<head>
    <title>Layout Test</title>

    <link rel="stylesheet" href="assets/css/screen.css" />
    <link rel="stylesheet" href="assets/css/home.css" />
</head>
<body>
    <div class="site">
        <div class="site-hd" role="banner">
            <h1>Layout Test</h1>
        </div>

        <div class="site-bd" role="main">
            <h2>Welcome Home</h2>
            <ul>
                <li>apple</li>
                <li>orange</li>
                <li>banana</li>
            </ul>
        </div>

        <div class="site-ft" role="contentinfo">
            <small>&copy; 2013</small>
        </div>
    </div>

    <script src="assets/js/analytics.js"></script>
    <script src="assets/js/controllers/home.js"></script>
</body>
</html>

Contribute

Tasks

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

© 2015 Shannon Moeller me@shannonmoeller.com

Licensed under MIT

broken-record@everything-registry/sub-chunk-1822@andreyvolokitin/parcel-transformer-handlebars@campj/bannerstrabeaxcxspritesheet-templatesyaplweblerwebexhbswhimyu-spritesheet-templatestoga-puratutu-backendtutu-frameworkthink-template-handlebarssite-boilerplate-helperssummitstarter-metalsmithstr8r-coresails-hook-hbsshamrock_utilssifespritesheet-templatesspritesheet-templates-3xspritesheet-templates-steamerspritesheet-templates-x3@hidoo/express-engine-handlebars@hidoo/gulp-task-build-html-handlebars@anikin/parcel-transformer-handlebars@infinitebrahmanuniverse/nolb-hand@inventory/parcel-plugin-handlebarsdojo-templater@economist/doc-pack@evokegroup/str8r-core@evokegroup/str8r-core-multilang@layflags/parcel-plugin-handlebars@jsoma/parcel-plugin-handlebars@modularbp/gulp-hbs@miyagi/core@marcotss/parcel-transformer-handlebars-json@native_finance/parcel-plugin-handlebars@isomx/jsdoc-baseline@jmilanes/hotbars@jmilanes/parcel-transformer-handlebars-revamped@zetavogel/parcel-transformer-handlebarsexactoabecmsffc-nodefekit-extension-hfflatsheetnan-summitfis3-parser-handlebars@sugarcrm/jsdoc-baseline@ringods/starterkit-zoho-sites@restorecommerce/handlebars-helperized@sitna/jsdoc-template@unic/estatico-handlebarsdufing@valtech-us-baltimore-frontend/yaplmangonyangular-cli-node-js-mongo-db-customers-servicefx-spritesheet-templatesfunctions-creatorfull-auth-middlewarefoodocgp-boilerplate-environmentnovicell-buildexpress-yourselfbeerkithandlebars-plus-loaderhapi-auto-loadergulp-cg-toolkit@partiellkorrekt/parcel-transformer-handlebarslxc-spritesheet-templateslxc-spritesheet-templates-mobiledw-hbs-sassdrizzle-builderarchitektgenabogart-handlebarsparcel-plugin-handlebarsparcel-plugin-handlebars-benzparcel-plugin-handlebars-jsonparcel-plugin-handlebars2grunt-handlebars-layouthex-views-handlebarsheadmangwcsshbscartapacio.core.templateaxperienceax-web-builderhtml-templaterinstinct_clgulp-handlebars-robotinialitebuilderradic-handlebarsjsonresume-theme-acejsdoc-baselinecozy-notificationskanon
3.1.4

7 years ago

3.1.3

8 years ago

3.1.2

9 years ago

3.1.1

9 years ago

3.1.0

9 years ago

3.0.0

9 years ago

2.0.2

9 years ago

2.0.1

9 years ago

2.0.0

9 years ago

1.1.0

9 years ago

1.0.0

9 years ago

0.3.3

10 years ago

0.3.2

10 years ago

0.3.1

10 years ago

0.2.0

10 years ago

0.1.3

11 years ago

0.1.1

11 years ago

0.1.0

11 years ago