Skip to content

Commit 3a176e4

Browse files
authored
Merge pull request #1 from dadi/feature/add-helper-functions-to-locals
add helpers from config to locals passed to template
2 parents 5baf694 + e49c799 commit 3a176e4

File tree

10 files changed

+160
-15
lines changed

10 files changed

+160
-15
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
coverage
22
node_modules/
3-
scripts/*.svg
3+
scripts/*.svg
4+
.DS_Store

README.md

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
## Pug.js engine interface
44

55
[![npm (scoped)](https://img.shields.io/npm/v/@dadi/web-pugjs.svg?maxAge=10800&style=flat-square)](https://www.npmjs.com/package/@dadi/web-pugjs)
6-
[![coverage](https://img.shields.io/badge/coverage-85%25-yellow.svg?style=flat?style=flat-square)](https://github.com/dadi/web-pugjs)
6+
[![coverage](https://img.shields.io/badge/coverage-78%25-yellow.svg?style=flat?style=flat-square)](https://github.com/dadi/web-pugjs)
77
[![Build Status](https://travis-ci.org/dadi/web-pugjs.svg?branch=master)](https://travis-ci.org/dadi/web-pugjs)
88
[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](http://standardjs.com/)
99
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square)](https://github.com/semantic-release/semantic-release)
@@ -54,3 +54,54 @@ include /partials/common/header.pug
5454
//- Relative path
5555
include common/header.pug
5656
```
57+
58+
### Helper functions
59+
60+
Add a DADI Web configuration setting for `helpers`, pointing to a directory containing helper files. Each `.js` helper file will be added as a property to template locals for use within templates.
61+
62+
#### Configuration
63+
64+
```
65+
engines: {
66+
pug: {
67+
paths: {
68+
helpers: 'test/workspace/helpers'
69+
}
70+
}
71+
}
72+
```
73+
74+
#### Directory structure
75+
76+
```
77+
helpers/
78+
|_ trim.js
79+
pages/
80+
|_ partials/
81+
|_ |_ common/
82+
|_ |_ |_ header.pug
83+
|_ |_ contact-info.pug
84+
|_ home.pug
85+
```
86+
87+
#### Locals
88+
89+
The function is added to the template locals, along with data objects:
90+
91+
```
92+
{
93+
products: [
94+
{ name: 'The Old Man and the Sea' }
95+
],
96+
trim: [Function]
97+
}
98+
```
99+
100+
#### Usage
101+
102+
Use the function in templates like so:
103+
104+
```
105+
h1= trim(product.name)
106+
```
107+

index.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
const ENGINE = {
2+
config: {
3+
paths: {
4+
doc: 'Paths required by Pug.js',
5+
format: Object,
6+
default: {}
7+
}
8+
},
29
extensions: ['.pug'],
310
handle: 'pug'
411
}
512

613
module.exports = () => {
714
const debug = require('debug')('web:templates:pug')
815
const pug = require('pug')
16+
const requireDir = require('require-dir')
917

1018
const EnginePug = function (options) {
1119
debug('Starting Pug.js engine...')
@@ -44,6 +52,13 @@ module.exports = () => {
4452
*/
4553
EnginePug.prototype.initialise = function () {
4654
debug('Pug initialised')
55+
56+
if (this.config.engines &&
57+
this.config.engines.pug &&
58+
this.config.engines.pug.paths && this.config.engines.pug.paths.helpers
59+
) {
60+
this.helperFunctions = requireDir(this.config.engines.pug.paths.helpers, { recurse: true, camelcase: true })
61+
}
4762
}
4863

4964
/**
@@ -69,6 +84,10 @@ module.exports = () => {
6984
* @return {Promise} A Promise that resolves with the render result.
7085
*/
7186
EnginePug.prototype.render = function (name, data, locals, options) {
87+
if (this.helperFunctions) {
88+
Object.assign(locals, this.helperFunctions)
89+
}
90+
7291
return Promise.resolve(this.templates[name](locals))
7392
}
7493

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
"web",
1818
"pug",
1919
"pug.js",
20-
"jade"
20+
"jade",
21+
"dadi-web-engine"
2122
],
2223
"author": "Eduardo Boucas <mail@eduardoboucas.com>",
2324
"bugs": {
@@ -26,7 +27,8 @@
2627
"homepage": "https://github.com/dadi/web-pugjs#readme",
2728
"dependencies": {
2829
"debug": "^2.6.6",
29-
"pug": "^2.0.0-rc.1"
30+
"pug": "^2.0.0-rc.1",
31+
"require-dir": "^0.3.2"
3032
},
3133
"devDependencies": {
3234
"colors": "^1.1.2",

test/helpers/config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const objectPath = require('object-path')
44

55
const CONFIG_PROPERTIES = {
66
engines: {
7-
dust: {
7+
pug: {
88
paths: {
99
filters: 'test/workspace/filters',
1010
helpers: 'test/workspace/helpers'

test/helpers/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ const ADDITIONAL_TEMPLATES = {
1414
}
1515

1616
const PAGES = {
17-
products: fs.readFileSync(path.join(PATHS.workspace, 'pages/products.pug'), 'utf8')
17+
products: fs.readFileSync(path.join(PATHS.workspace, 'pages/products.pug'), 'utf8'),
18+
'products-with-helpers': fs.readFileSync(path.join(PATHS.workspace, 'pages/products-with-helpers.pug'), 'utf8')
1819
}
1920

2021
module.exports.additionalTemplates = ADDITIONAL_TEMPLATES

test/pug.js

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ describe('Pug.js interface', function () {
5252
const Engine = factory()
5353
const instance = new Engine({
5454
additionalTemplates: Object.keys(helpers.additionalTemplates).map(name => helpers.additionalTemplates[name]),
55-
config: config,
55+
config: config.config,
5656
pagesPath: path.join(helpers.paths.workspace, 'pages')
5757
})
5858

@@ -65,11 +65,25 @@ describe('Pug.js interface', function () {
6565
})
6666
})
6767

68+
it('should load helpers', done => {
69+
const Engine = factory()
70+
const instance = new Engine({
71+
additionalTemplates: Object.keys(helpers.additionalTemplates).map(name => helpers.additionalTemplates[name]),
72+
config: config.config,
73+
pagesPath: path.join(helpers.paths.workspace, 'pages')
74+
})
75+
76+
Promise.resolve(instance.initialise()).then(() => {
77+
(typeof instance.helperFunctions.trim).should.eql('function')
78+
done()
79+
})
80+
})
81+
6882
it('should render pages with locals', done => {
6983
const Engine = factory()
7084
const instance = new Engine({
7185
additionalTemplates: Object.keys(helpers.additionalTemplates).map(name => helpers.additionalTemplates[name]),
72-
config: config,
86+
config: config.config,
7387
pagesPath: path.join(helpers.paths.workspace, 'pages')
7488
})
7589

@@ -110,4 +124,49 @@ describe('Pug.js interface', function () {
110124
done()
111125
})
112126
})
127+
128+
it('should render pages with helpers', done => {
129+
const Engine = factory()
130+
const instance = new Engine({
131+
additionalTemplates: Object.keys(helpers.additionalTemplates).map(name => helpers.additionalTemplates[name]),
132+
config: config.config,
133+
pagesPath: path.join(helpers.paths.workspace, 'pages')
134+
})
135+
136+
const locals = {
137+
products: [
138+
{
139+
name: ' Super Thing 3000 ',
140+
price: 5000
141+
},
142+
{
143+
name: ' Mega Thang XL',
144+
price: 8000
145+
}
146+
]
147+
}
148+
149+
const expected = `
150+
<header>My online store</header>
151+
152+
<h1>Products:</h1>
153+
154+
<ul>
155+
<li>Super Thing 3000 - £5000</li>
156+
<li>Mega Thang XL - £8000</li>
157+
</ul>
158+
159+
<footer>Made by DADI</footer>
160+
`
161+
162+
Promise.resolve(instance.initialise()).then(() => {
163+
return instance.register('products-with-helpers', helpers.pages['products-with-helpers'])
164+
}).then(() => {
165+
return instance.render('products-with-helpers', helpers.pages['products-with-helpers'], locals)
166+
}).then(output => {
167+
htmlLooksLike(output, expected)
168+
169+
done()
170+
})
171+
})
113172
})

test/workspace/helpers/trim.js

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
const dust = require('dustjs-linkedin')
2-
31
/*
4-
* Returns the supplied 'data' parameter trimmed of whitespace on both left and right sides
5-
* Usage: {@Trim data="{body}"/}
2+
* Returns the supplied 'input' parameter trimmed of whitespace on both left and right sides
63
*/
7-
dust.helpers.Trim = function (chunk, context, bodies, params) {
8-
var data = context.resolve(params.data)
9-
return chunk.write(data.trim())
4+
module.exports = input => {
5+
return input.trim()
106
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"page": {
3+
"name": "products",
4+
"description": "The products page",
5+
"language": "en"
6+
}
7+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
include /partials/header.pug
2+
3+
h1 Products:
4+
5+
ul
6+
each val, index in products
7+
li= trim(val.name) + ' - £' + val.price
8+
9+
include /partials/footer.pug

0 commit comments

Comments
 (0)