Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow passing array of template paths for nunjucks engine #306

Merged
merged 1 commit into from
May 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,20 @@ fastify.get("/", (req, reply) => {

### Nunjucks

You can load templates from multiple paths when using the nunjucks engine:

```js
fastify.register(require("point-of-view"), {
engine: {
nunjucks: require("nunjucks"),
},
templates: [
"node_modules/shared-components",
"views",
],
});
```

To configure nunjucks environment after initialisation, you can pass callback function to options:

```js
Expand Down Expand Up @@ -393,7 +407,7 @@ fastify.get("/", (req, reply) => {
});
```

<!---
<!---
// This seems a bit random given that there was no mention of typescript before.
### Typing

Expand Down
32 changes: 25 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,20 @@ function fastifyView (fastify, opts, next) {
const propertyName = opts.propertyName || 'view'
const engine = opts.engine[type]
const globalOptions = opts.options || {}
const templatesDir = opts.root || resolve(opts.templates || './')
const templatesDir = resolveTemplateDir(opts)
const lru = HLRU(opts.maxCache || 100)
const includeViewExtension = opts.includeViewExtension || false
const viewExt = opts.viewExt || ''
const prod = typeof opts.production === 'boolean' ? opts.production : process.env.NODE_ENV === 'production'
const defaultCtx = opts.defaultContext || {}
const globalLayoutFileName = opts.layout

function templatesDirIsValid (_templatesDir) {
if (Array.isArray(_templatesDir) && type !== 'nunjucks') {
throw new Error('Only Nunjucks supports the "templates" option as an array')
}
}

function layoutIsValid (_layoutFileName) {
if (type !== 'dot' && type !== 'handlebars' && type !== 'ejs' && type !== 'eta') {
throw new Error('Only Dot, Handlebars, EJS, and Eta support the "layout" option')
Expand All @@ -44,13 +50,15 @@ function fastifyView (fastify, opts, next) {
}
}

if (globalLayoutFileName) {
try {
try {
templatesDirIsValid(templatesDir)

if (globalLayoutFileName) {
layoutIsValid(globalLayoutFileName)
} catch (error) {
next(error)
return
}
} catch (error) {
next(error)
return
}

const dotRender = type === 'dot' ? viewDot.call(fastify, preProcessDot.call(fastify, templatesDir, globalOptions)) : null
Expand Down Expand Up @@ -406,7 +414,7 @@ function fastifyView (fastify, opts, next) {
data = Object.assign({}, defaultCtx, this.locals, data)
// Append view extension.
page = getPage(page, 'njk')
nunjucksEnv.render(join(templatesDir, page), data, (err, html) => {
nunjucksEnv.render(page, data, (err, html) => {
const requestedPath = getRequestedPath(this)
if (err) return this.send(err)
if (useHtmlMinification(globalOptions, requestedPath)) {
Expand Down Expand Up @@ -677,6 +685,16 @@ function fastifyView (fastify, opts, next) {
return render
}

function resolveTemplateDir (_opts) {
if (_opts.root) {
return _opts.root
}

return Array.isArray(_opts.templates)
? _opts.templates.map((dir) => resolve(dir))
: resolve(_opts.templates || './')
}

function hasAccessToLayoutFile (fileName, ext) {
try {
accessSync(join(templatesDir, getPage(fileName, ext)))
Expand Down
10 changes: 10 additions & 0 deletions templates/nunjucks-layout/layout.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
3 changes: 3 additions & 0 deletions templates/nunjucks-template/index.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% extends "layout.njk" %}

{% block content %}<p>{{ text }}</p>{% endblock %}
44 changes: 41 additions & 3 deletions test/test-nunjucks.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ test('reply.view with nunjucks engine and custom templates folder', t => {
fastify.register(require('../index'), {
engine: {
nunjucks: nunjucks
}
},
templates: 'templates'
})

fastify.get('/', (req, reply) => {
reply.view('./templates/index.njk', data)
reply.view('index.njk', data)
})

fastify.listen(0, err => {
Expand All @@ -36,7 +37,44 @@ test('reply.view with nunjucks engine and custom templates folder', t => {
t.equal(response.statusCode, 200)
t.equal(response.headers['content-length'], '' + body.length)
t.equal(response.headers['content-type'], 'text/html; charset=utf-8')
t.equal(nunjucks.render('./templates/index.njk', data), body.toString())
t.equal(nunjucks.render('index.njk', data), body.toString())
fastify.close()
})
})
})

test('reply.view with nunjucks engine and custom templates array of folders', t => {
t.plan(6)
const fastify = Fastify()
const nunjucks = require('nunjucks')
const data = { text: 'text' }

fastify.register(require('../index'), {
engine: {
nunjucks: nunjucks
},
templates: [
'templates/nunjucks-layout',
'templates/nunjucks-template'
]
})

fastify.get('/', (req, reply) => {
reply.view('index.njk', data)
})

fastify.listen(0, err => {
t.error(err)

sget({
method: 'GET',
url: 'http://localhost:' + fastify.server.address().port
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.equal(response.headers['content-length'], '' + body.length)
t.equal(response.headers['content-type'], 'text/html; charset=utf-8')
t.equal(nunjucks.render('index.njk', data), body.toString())
fastify.close()
})
})
Expand Down
15 changes: 15 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,21 @@ test('register callback should throw if layout option provided with wrong engine
})
})

test('register callback should throw if templates option provided as array with wrong engine', t => {
t.plan(2)
const fastify = Fastify()

fastify.register(require('../index'), {
engine: {
pug: require('pug')
},
templates: ['layouts', 'pages']
}).ready(err => {
t.ok(err instanceof Error)
t.equal(err.message, 'Only Nunjucks supports the "templates" option as an array')
})
})

test('plugin is registered with "point-of-view" name', t => {
t.plan(2)
const fastify = Fastify()
Expand Down