Giter Club home page Giter Club logo

koa-handlebars's Introduction

koa-handlebars

A koa middleware for using handlebars templates

NOTE: the master branch (ie: v1.x on npm) works with [email protected]. See the v2 branch (ie: v2.x on npm) for [email protected] support.

Usage

This middleware adds 2 methods to the koa context object. The primary one is render(view, locals), which automatically sets the content-type as text/html and writes the generated view as the response. There is also renderView(view, locals), which yields the raw string. This allows you to modify the response further.

app.js

var koa = require("koa");
var handlebars = require("koa-handlebars");

var app = koa();

app.use(handlebars({
  defaultLayout: "main"
}));

app.use(function *() {
  yield this.render("index", {
    title: "Test Page",
    name: "World"
  });
});

app.listen(3000);

layouts/main.hbs

<!DOCTYPE html>
<html>
  <head>
    <title>{{title}}</title>
  </head>
  <body>
    {{{@body}}}
  </body>
</html>

views/index.hbs

Hello, {{name}}!

Resulting page

<!DOCTYPE html>
<html>
  <head>
    <title>Test Page</title>
  </head>
  <body>
    Hello, World!
  </body>
</html>

Views

The entry point for rendering is known as a view. The view usually contains the content specific to a single page. It has access to all loaded partials, helpers and is injected into the {{{@body}}} of the corresponding layout. (if there is one)

The simplest usage is to have a flat views/ directory that contains .hbs files. (although other patterns are possible, see the "Advanced Usage" section for more details)

In "development mode", views are not cached.

Layouts

Layouts are the content that is shared between many views. Like views, it has access to all loaded partials and helpers. The {{{@body}}} local is set as the content of the corresponding view.

The simplest usage is to have a flat layouts/ directory that contains .hbs files. (although other patterns are possible, see the "Advanced Usage" section for more details)

In "development mode", layouts are not cached.

Partials

Partials are sub-templates that you can use to render smaller bits within layouts/views.

There are 2 main types of partials. First, global partials are registered during init. (see options.partials) These will not be dynamically updated, not even during "development mode". (thus, you will need to restart your server when these globals change)

Secondly, partials residing in the directory specified by options.partialsDir will be dynamically loaded on each render call. When caching is enabled, that overhead is reduced substantially, and further optimization will be done in the future.

Helpers

Helpers are functions that any of your templates can call upon.

Currently, helpers can only be defined globally and must be declared during initialization. (see options.helpers) This requires a server restart after any changes, but this will be improved upon in the future.

Development

To enable "development mode" in your server, simply set cache: false in your middleware configuration.

In addition, this library uses visionmedia/debug, so you can enable debug output via DEBUG=koa-handlebars in the terminal.

Special Variables

When rendering templates, koa-handlebars will add 3 special private variables to your templates:

  • @body: in layouts, this is the contents of the rendererd view
  • @view: the name of the view that is being rendered
  • @layout: the name of the layout that is being rendered
  • @koa: the koa ctx of the current request

You can add more variables of your own via the data option or more dynamically with the beforeRender function. (see configuration options section for more details)

Generally speaking, avoid injecting data directly into locals from middleware, instead focus on adding things to options.data or using the koa context to grab data from there. (eg: {{@koa.request.length}})

Configuration Options

root

The base directory to use when resolving paths.

Default: process.cwd()

cache

Enables or disables the view cache. This is basically the flag for "development mode".

Default:: true

app.use(handlebars({
  cache: app.env !== "development"
}));

data

Adds additional private data (alongside @view, @layout and @koa) to the handlebars render options.

extension

The extension(s) that your template files can use. Any files not using the given extensions will be ignored.

Default: "hbs"

If you have multiple extensions, you simply use an array.

For example: [ "hbs", "handlebars", "tpl" ]

viewsDir

The location of your view templates (relative to root)

Default: "views"

viewPath(id)

Translates the given id into a path to resolve the template file. (the file extension is not required) If the returned path is relative, it will be assumed as relative to viewsDir.

By default, this simply returns the given id.

This function is run with the renderer as it's context (ie: this) so you can access this.options for advanced usage.

defaultLayout

If you are using layouts, then this can be used to bypass requiring each call to render() to specify a layout manually. Otherwise, leaving it empty will not render a layout at all unless otherwise specified.

layoutsDir

The location of your layout templates (relative to root)

Default: "layouts"

layoutPath(id)

Translates the given id into a path to resolve the template file. (the file extension is not required) If the returned path is relative, it will be assumed as relative to layoutsDir.

By default, this simply returns the given id.

This function is run with the renderer as it's context (ie: this) so you can access this.options for advanced usage.

partialsDir

The location of your non-global partial templates (relative to root)

Default: "partials"

partialId(file)

This function is a little backwards compared to layouts and views, but it takes a path for a partial template file. (relative to partialsDir) and converts it into a handlebars-friendly identifier.

For example: "navigation.hbs" => "navigation"

By default, it will strip the extension and camel-case the remaining string.

For example: "nav/main.hbs" => "navMain"

helpers

Allows you to define global helpers during initialization, this should be a shallow object where each key is a helper name and the value is a function.

partials

Allows you to define global partials during initialization, this should be a shallow object where each key is a partial name and the value is a function.

handlebars

Allows you to pass a custom handlebars instance, which you may want to do in some edge cases. For example, if you plan on using Handlebars.SafeString in your block helpers, you'll need a handle on the same instance of handlebars that the middleware is using. For example:

// app.js
var handlebars = require('handlebars');
var hbsKoa = require('koa-handlebars');

var app = koa();
app.use(hbsKoa({
  handlebars: handlebars
}));

// helpers.js

// Same instance, because node modules are cached
var Handlebars = require('handlebars');

module.exports.myHelper = function(input, options) {
  return new Handlebars.SafeString('<div class="some-html">' + input + '</div>');
};

koa-handlebars's People

Contributors

dominicbarnes avatar howlingeverett avatar rowno avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

koa-handlebars's Issues

partials do not work (iojs 1.8.1, windows 7.1)

The following log says, that partials are found and compiled, but at render log says that partials not found:
There is nothing about registration in readme.

Wed, 06 May 2015 10:12:38 GMT koa-handlebars creating koa-handlebars instance with options { cache: false,
root: 'd:/MyLife/Programming/TimeIsAllRepo/TimeIsAll/dev/src/timeisall',
viewsDir: 'views',
layoutsDir: 'views',
partialsDir: 'views/partials',
defaultLayout: 'layout' }
Wed, 06 May 2015 10:12:38 GMT koa-handlebars using d:/MyLife/Programming/TimeIsAllRepo/TimeIsAll/dev/src/timeisall as the root
Wed, 06 May 2015 10:12:42 GMT koa-handlebars rendering index template
Wed, 06 May 2015 10:12:42 GMT koa-handlebars reading file views\layout.hbs
Wed, 06 May 2015 10:12:42 GMT koa-handlebars compiling template views\layout.hbs
Wed, 06 May 2015 10:12:42 GMT koa-handlebars reading file views\index.hbs
Wed, 06 May 2015 10:12:42 GMT koa-handlebars compiling template views\index.hbs
Wed, 06 May 2015 10:12:42 GMT koa-handlebars searching for partials in d:\MyLife\Programming\TimeIsAllRepo\TimeIsAll\dev\src\timeisall\views\partials
Wed, 06 May 2015 10:12:42 GMT koa-handlebars 4 partials found
Wed, 06 May 2015 10:12:42 GMT koa-handlebars reading file views\partials\auth_widget.hbs
Wed, 06 May 2015 10:12:42 GMT koa-handlebars reading file views\partials\home_skeleton.hbs
Wed, 06 May 2015 10:12:42 GMT koa-handlebars compiling template views\partials\auth_widget.hbs
Wed, 06 May 2015 10:12:42 GMT koa-handlebars compiling template views\partials\home_skeleton.hbs
Wed, 06 May 2015 10:12:42 GMT koa-handlebars rendering with layout layout
Wed, 06 May 2015 10:12:42 GMT koa-handlebars unable to render view index Error: The partial home_skeleton could not be found
at Object.invokePartial (d:\MyLife\Programming\TimeIsAllRepo\TimeIsAll\dev\src\timeisall\node_modules\koa-handlebars\node_modules\handlebars\dist\cjs\handlebars\runtime.js:216:11)
at Object.invokePartialWrapper as invokePartial
at Object.eval (eval at createFunctionContext (d:\MyLife\Programming\TimeIsAllRepo\TimeIsAll\dev\src\timeisall\node_modules\koa-handlebars\node_modules\handlebars\dist\cjs\handlebars\compiler\javascript-compiler.js:221:23), :4:23)
at Object.ret (d:\MyLife\Programming\TimeIsAllRepo\TimeIsAll\dev\src\timeisall\node_modules\koa-handlebars\node_modules\handlebars\dist\cjs\handlebars\runtime.js:159:30)
at Object.ret as fn
at Object.Renderer.compileTemplate.meta.render (d:\MyLife\Programming\TimeIsAllRepo\TimeIsAll\dev\src\timeisall\node_modules\koa-handlebars\lib\renderer.js:85:17)
at Renderer.render (d:\MyLife\Programming\TimeIsAllRepo\TimeIsAll\dev\src\timeisall\node_modules\koa-handlebars\lib\renderer.js:313:38)
at GeneratorFunctionPrototype.next (native)
at onFulfilled (d:\MyLife\Programming\TimeIsAllRepo\TimeIsAll\dev\src\timeisall\node_modules\koa\node_modules\co\index.js:64:19)

Probably similar problem (unanswered yet).
http://stackoverflow.com/questions/29309198/koa-handlebars-unable-to-render-view-the-partial-could-not-be-found

Handlebars compile options aren't passed through.

The JSDoc for this.render suggests that we can pass additional options for Handlebars as the third argument after template name and locals.

However, Handlebars requires that these options be passed to the handlebars.compile function as a second argument. Instead they're being passed into the resulting render function where they're being silently ignored.

This means something like this.render('my-template', {foo: 'bar'}, {preventIndent: true}) won't work as expected.

Partials file names are not allowed the character "-"

InternalServerError: unable to render view: home-public because The partial nav-public could not be found

Apparantly it craches when the name of a partial file has the character - in it. An example:

nav-public.hbs <--- crashes
navpublic.hbs <--- does not crash(includes changing {{> nav-public }} to {{> navpublic }} in the view)

// project/views/home-public.hbs
{{> nav-public }}
// project/partials/nav-public.hbs
This is a partial

Request: Koa context in options.data

As outlined here, http://handlebarsjs.com/execution.html, Handlebars has the ability to pass additional data to helpers through the data hash in the options parameter.

We're currently evaluating a switch from koa-hbs to koa-handlebars and would like to request a similar ability in koa-handlebars. We put together a pull request for koa-hbs to enable just that (koajs/koa-hbs@93096b4) We went this route instead of allowing for a 'data' parameter in this.render because this is inteded to be used for koa, and in that situation, the koa context is always relevant.

Feature: support for Koa 2.0

Koa 2.0 is moving away from generator functions completely, which came as a bit of a surprise. The ultimate end-goal appears to be building the middleware around ES7 async/await. That works in the alpha.2 already when you run with babel, but in the interim it seems like tj is expecting package authors to switch from generator middleware functions to Promises.

A lot of middleware can be hacked into compatibility simply by calling co.wrap around the initialiser, but koa-handlebars is a bit more complex since it's augmenting the context with functions that other route handlers use.

I'm happy to help out with this once I get my head around the new API, since koa-handlebars is the only piece of middleware in my current project that isn't working with the koa 2.0 alpha yet.

refactor the tests?

  • I think it is necessary to test in koa context. such as:
var request = require('supertest');
var koa = require('koa');
var app = koa();

app.use(...)
request(app.listen())...

Simple example for including your own helper

I keep seeing the following in tutorials etc.:

Handlebars.registerHelper('myHelper', function (date) { // get minutes between date and now
    return 'something...';
});

Would be nice if you could proves an example of how to get this to work with koa-handlebars.

the viewsDir maybe an array

when I set the viewsDir like this:
app.use(handlebars({
cache: app.env !== "development",
extension:['html','hbs'],
viewsDir:['./client/web','./client/wx']
}));
It does not work,could the viewsDir be an array?

Request: Allow arrays of paths

I'd like to request the ability to pass an array of paths to the renderer options for layoutsPath, viewsPath and partialsPath.

eg.

{
  partialsPath: [
    '/public/templates/partials',
    '/views/partials'
  ]
}

Custom handlebars option in the initialisation object

One of the nicer features of express-handlebars is the ability to pass your own instance of Handlebars to the middleware initialiser, a bit like this:

var handlebars = require('handlebars');
var hbKoa = require('koa-handlebars');
app.use(hbKoa({
  handlebars: handlebars,
  // ... other config options
});

There are a couple of advantages to this. First, it decouples the koa middleware from a specific Handlebars version, e.g. I could use 4.0 without waiting for the package maintainer to update the middleware to include it.

Secondly, unless you have access to the same instance of Handlebars as is being used to render templates then you cannot use Handlebars.SafeString in custom helpers, since it uses simple equality to determine that the handlebars instance is the same and therefore a safe render context. This severely limits the capability of a lot of block helpers.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.