npm package: @bark/koa-handlebars
Description: Render hbs files in your koa apps with autoloaded helpers and partials
Author: Louis Captianchik
Latest version: 1.0.1

# koa-handlebars

Render HBS files in your Koa apps with autoloaded helpers and partials

## Install

```
npm i @bark/koa-handlebars handlebars fs-jetpack
```

koa-handlebars is BYOFS (Bring-your-own-file-system). If you have a different fs implementation that is api-compatible with fs-jetpack, you can use that instead and provide it to the `jetpack` option when creating your renderer

## Usage

### Koa Middleware

The primary use case for this module is to act as a Koa middleware. This means that you will need to `app.use` it somewhere in your middleware stack. This will add a `ctx.render` function that can be used to render templates in one
of your app's controllers.

```javascript
const Koa = require('koa')
const hbs = require('@bark/koa-handlebars')
const path = require('path')

const app = new Koa()

// ... Other Middleware ...

app.use(hbs(path.join(__dirname, 'views'))) // <-- Mount the middleware

// ... More Middleware ...

router.get('web.projects.list', '/projects', async ctx => {
    const currentUser = await getCurrentUser()
    const projects = await getProjectsSomehow(currentUser)

    await ctx.render('projects/list-projects', { // <-- Call 'ctx.render' with your template name and data
        user: currentUser,
        projects,
    })
})
```

### Standalone

You might sometimes need to access the fully configured renderer outside of your request/response flow (e.g. async job queue handlers). Koa-handlebars exposes a method for creating a `ctx`-independent renderer with the same set of options as the middleware version.

```javascript
const path = require('path')
const { cwd } = require('process')
const { createRenderer } = require('@bark/koa-handlebars')

const renderer = createRenderer(path.join(cwd(), 'views')))

const output = await renderer.render('mailers/users/password-reset', {
    name: 'Schmoopy',
    token: '123',
    action_url: 'https://example.com/reset-password?token=123'
})
```

## API

This module exposes two functions, both of which have the same parameters. One function creates a koa middleware that attaches a `render` method to `ctx` (see above usage). The other creates a `Renderer` object with a `render` method. Both `render` methods take the same parameters

### createRenderer(rootPath: string, options: RendererOptions) -> Renderer
### koaHandlebars(rootPath: string, options: RendererOptions) -> Koa.Middleware

#### rootPath

The base path that the render method will append template names to in order to find a template file. Unless the helper and partial paths are customised, koa-handlebars will expect the folder found at this path to also contain folders named `helpers` and `partials`

#### RendererOptions

An object that can be used to customise the behaviour of the koa-handlebars renderer

##### RendererOptions.useCache: boolean

**Default: `process.env.NODE_ENV === 'production'`**

When set to `true`, the renderer will store the parsed template file in an internal cache. This *does not* store the result
of using a template; rather, the file is loaded from disk, parsed by Handlebars and then stored in the cache before being used. Subsequent calls to render the same template will use the cached template instead of having to hit the filesystem and re-parse the template file. 

This behaviour may be undesirable if you are iterating on your templates, or if you have a large number of templates that might take up a lot of memory when cached.

##### RendererOptions.extension: string

**Default: ".hbs"**

The extension that koa-handlebars will append to the name of a template in order to find the template file. Using the default settings, a call to `renderer.render('users/profile')` would render `<root>/users/profile.hbs`.

##### RendererOptions.partials: string

**Default: "partials"**

The name of the folder holding your partials, relative to the root path. Using the default settings, the following handlebars expression will render the template found at `<root>/partials/user-footer.hbs`

```hbs
<!-- Some content -->

{{> user-footer }}

<!-- Some other content -->
```

##### RendererOptions.helpers: string

**Default: "helpers"**

The name of the folder holding your helper functions, relative to the root path. koa-handlebars will `require` every file in this folder to look for helpers. See below for more information about how to write a helper file in a way that is compatible with koa-handlebars

##### RenderOptions.extend: Fn(instance: Handlebars) -> Handlebars

**Default: `(inst) => inst`**

A simple hook that allows you to directly access and modify the underlying Handlebars instance. This function is called at the end of the configuration process after partials and helpers have been registered. The `extend` function must return _a_ handlebars instance (or another api-compatible object), but this does not imply that it has to be _the_ handlebars instance passed to the `extend` function.

##### RenderOptions.jetpack: FsJetpack

**Default: `require('fs-jetpack')`**

The filesystem instance that koa-handlebars will use for all filesystem operations. This should either be an instance of `fs-jetpack`, or some other api-compatible object. If you are providing your own implementation, you do not need to install the `fs-jetpack` dependency.

### ctx.render(template: string, data: Object, options: HandlebarsOptions) -> Promise<void>
### renderer.render(template: string, data: Object, options: HandlebarsOptions) -> Promise<string>

#### template

This is the path to the template file, relative to the `root` option provided to the constructor, and without the file extension. If the template does not exist, `ctx.render` will set the response status to `404` with no response body; `renderer.render` will simply return `null`

#### data

This object holds data that will be made available to the Handlebars template. This is passed directly to the Handlebars instance without modification.

#### options

This object holds options for the underlying Handlebars instance. This is passed directly to the Handlebars instance without modification; check the Handlebars documentation for more information.


## Helpers

Helpers are javascript functions that can perform some sync processing and return data to be interpolated into a template. By default, koa-handlebars will look at every file in the `<root>/helpers` directory for functions to load. Helpers can be exported in one of two ways: one helper per file, or helper bundles.

If you have one helper per file, the name of the file will be registered as the name of your helper function, and your file should look something like this:

```javascript
// <root>/helpers/current_year.js

const Handlebars = require('handlebars')
module.exports = function showCurrentYear() {
	const date = new Date()
	return new Handlebars.SafeString(String(date.getFullYear()))
}
```

If you have multiple helpers per file, every exported name will be registered as a helper function, where the helper function name matches the exported name. You file should look something like this:

```javascript
// <root>/helpers/utilities.js

const Handlebars = require('handlebars')

exports.current_year = function showCurrentYear() {
	const date = new Date()
	return new Handlebars.SafeString(String(date.getFullYear()))
}

exports.ifenv = function(name, compare, options) {
    if (options == null) {
        options = compare
        compare = null
    }

    const value = process.env[name.toUpperCase()]
    if (value === compare) {
        return options.fn(this)
    } else {
        return options.inverse(this)
    }
}
```

Both of the above ways of registering helpers will allow the following code to work:

```hbs
<div class="footer">
    Copyright 1970 - {{# current_year }}
</div>
```

The second example will also allow the following to work:

```hbs
{{#ifenv "node_env" "production"}}
<script type="application/javascript" src="https://example.com/cdn/my-crm-widget.js"></script>
{{else}}
<script type="application/javascript" src="https://example.com/cdn/my-debug-tools.js"></script>
{{/ifenv}}
```