npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

handlebars-template-loader

v1.0.0

Published

A Handlebars template loader for Webpack

Downloads

9,029

Readme

handlebars-template-loader

A Handlebars template loader for Webpack

Changelog

Table of Contents

Installation

npm install handlebars-template-loader

Since version 0.5.4, this loaders does not include Handlebars in its dependency list. Make sure to install Handlebars before running webpack. Read https://github.com/npm/npm/issues/6565 for details.

Usage

module.exports = {
    //...

    module: {
        loaders: [
            { test: /\.hbs/, loader: "handlebars-template-loader" }
        ]
    },

    node: {
        fs: "empty" // avoids error messages
    }
};

Loading templates

<!-- File: hello.hbs -->
<p>Hello&nbsp;{{name}}</p>
// File: app.js
var compiled = require('./hello.hbs');
return compiled({name: "world"});

Using helpers

// File: helpers.js

// Get Handlebars instance
var Handlebars = require('handlebars-template-loader/runtime');

Handlebars.registerHelper('list', function(items, options) {
  var out = "<ul>";

  for(var i=0, l=items.length; i<l; i++) {
    out = out + "<li>" + options.fn(items[i]) + "</li>";
  }

  return out + "</ul>";
});

Handlebars.registerHelper('link', function(text, url) {
  text = Handlebars.Utils.escapeExpression(text);
  url  = Handlebars.Utils.escapeExpression(url);

  var result = '<a href="' + url + '">' + text + '</a>';

  return new Handlebars.SafeString(result);
});
// File: main.js

// Include template helpers
require("./helpers.js");

Using partials

    // Get Handlebars instance
    var Handlebars = require('handlebars-template-loader/runtime');

    // Require partial
    var partial = require('path/to/my/_partial.hbs');

    // Register partial
    Handlebars.registerPartial('my_partial_name', partial);

Options

Prepending filename comment

When debugging a large single page app with the DevTools, it's often hard to find the template that contains a bug. With the following config a HTML comment is prepended to the template with the relative path in it (e.g. <!-- view/user/edit.html -->).

module.exports = {
    //...

    module: {
        loaders: [
            {
                test: /\.hbs$/,
                loader: "handlebars-template-loader",
                query: {
                    prependFilenameComment: __dirname,
                }
            }
        ]
    }
};

Images

In order to load images you must install either the file-loader or the url-loader package.

module.exports = {
    //...

    module: {
        loaders: [
            //...
            { test: /\.hbs/, loader: "handlebars-template-loader" },
            { test: /\.jpg/, loader: "file-loader" },
            { test: /\.png/, loader: "url-loader?mimetype=image/png" },
        ]
    }
};
<!-- Require image using file-loader -->
<img src="img/portrait.jpg">

<!-- Require image using url-loader -->
<img src="img/icon.png">

Images with an absolute path are not translated unless a root option is defined

<!-- Using root = undefined => no translation -->
<img src="/not_translated.jpg">

<!-- Using root = 'images' => require('images/image.jpg') -->
<img src="/image.jpg">

In order to deactivate image processing define the attributes option as an empty array.

module.exports = {
    //...

    module: {
        loaders: [
            {
                test: /\.hbs$/,
                loader: "handlebars-template-loader",
                query: {
                    attributes: []
                }
            }
        ]
    }
};

You could also add which attributes need to be processed in the form of pairs tag:attribute.

module.exports = {
    //...

    module: {
        loaders: [
            {
                test: /\.hbs$/,
                loader: "handlebars-template-loader",
                query: {
                    attributes: ['img:src', 'x-img:src']
                }
            }
        ]
    }
};

Dynamic attributes won't be afected by this behaviour by default.

<!-- Ignore "root" argument if attribute contains a template expression -->
<img src="/img/{{doge}}.png" class="doge-img">

In order to append the root directory you'll need to specify the parseDynamicRoutes argument.

module.exports = {
    //...

    module: {
        loaders: [
            {
                test: /\.html$/,
                loader: "handlebars-template-loader",
                query: {
                    root: "myapp",
                    parseDynamicRoutes: true
                }
            }
        ]
    }
};
<!-- Attribute now translates to "myapp/img/{{doge}}.png" -->
<img src="/img/cat-<%- currentCat.url %>.png" class="doge-img">

Runtime path

If you have a custom location for your Handlebars runtime module then you can set that in your query object via the runtimePath property. This is the path to the Handlebars runtime that every .hbs file will require and use. By default this loader looks up the absolute path to the handlebars/runtime in your node_modules folder. Changing this property is useful if you are doing somethign non-standard with your Handlebar templates, for example setting an alias for the handlebars/runtime path.

module.exports = {
    //...

    module: {
        loaders: [
            {
                test: /\.html$/,
                loader: "handlebars-template-loader",
                query: {
                    runtimePath: 'handlebars/runtime'
                }
            }
        ]
    }
};

Compilation options

Handlebars does support additional compilation options that you can specify in your query object literal.

module.exports = {
    //...

    module: {
        loaders: [
            {
                test: /\.html$/,
                loader: "handlebars-template-loader",
                query: {
                    root: "myapp",
                    strict: true,
                    noEscape: true
                }
            }
        ]
    }
};

Macros

require

The require macro expects a path to a handlebars template. The macro is then translated to a webpack require expression that evaluates the template using the same arguments.

<h4>Profile</h4>

Name: <strong>{{name}}</strong>
<br/>
Surname: <strong>{{surname}}</strong>
<div class="profile-details">
    @require('profile-details.hbs')
</div>

include

While the require macro expects a resource that returns a function, the include macro can be used for resources that return plain text. For example, we can include text loaded through the html-loader directly in our template.

<div class="wiki">
    <h3>Introduction</h3>
    @include('intro.htm')
    <h3>Authors</h3>
    @include('authors.htm')
</div>

repeat

The repeat macro will repeat the given string the amount of times as specified by the second argument (default to 1). It will only accept string literals.

<p>Lorem ipsum</p>
@repeat('<br/>', 3)
<p>Sit amet</p>
@repeat('\n')

Custom macros

We can include additional macros by defining them in the webpack configuration file. Remember that the value returned by a macro is inserted as plain javascript, so in order to insert a custom text we need to use nested quotes. For example, let's say that we want a macro that includes a copyright string in our template.

// File: webpack.config.js
module.exports = {
    // ...

    module: {
        loaders: {
            // ...
            { test: /\.hbs/, loader: "handlebars-template-loader" },
        }
    },

    macros: {
        copyright: function () {
            return "'<p>Copyright FakeCorp 2014 - 2015</p>'";
        }
    }
}

We then invoke our macro from within the template as usual.

<footer>
    @copyright()
</footer>

Disabling macros

You can disable macros if you are a bit unsure about their usage or just simply want faster processing. This is achieved by setting the parseMacros options to false.

module.exports = {
    // ...

    module: {
        loaders: {
            // ...
            {
                test: /\.hbs/,
                loader: "handlebars-template-loader",
                query: {
                    parseMacros: false
                }
            },
        }
    }
}

Arguments

Macros can accept an arbitrary number of arguments. Only boolean, strings and numeric types are supported.

// File: webpack.config.js
module.exports = {
    // ...

    module: {
        loaders: {
            // ...
            { test: /\.html$/, loader: "handlebars-template-loader" },
        }
    },

    macros: {
        header: function (size, content) {
            return "'<h" + size + ">" + content + "</h" + size + ">'";
        }
    }
}
@header(1, 'Welcome')
<p>Lorem ipsum</p>
@header(3, 'Contents')
<p>Sit amet</p>

Escaping

Macro expressions can be escaped with the \ character.

@repeat('<br/>', 3)
\@escaped()
@custom_macro()

Translates to

<br/><br/><br/>
@escaped()
custom string

License

Released under the MIT license.