UNPKG

koa-views

Version:

Template rendering middleware for koa

99 lines (79 loc) 2.59 kB
'use strict' const debug = require('debug')('koa-views') const consolidate = require('@ladjs/consolidate') const send = require('koa-send') const getPaths = require('get-paths') const pretty = require('pretty') const resolve = require('resolve-path') module.exports = viewsMiddleware const bigIntReplacer = () => { const seen = new WeakSet() return (key, value) => { if (typeof value === 'bigint') return value.toString() if (typeof value === 'object' && value !== null) { if (seen.has(value)) { return } seen.add(value) } return value } } function viewsMiddleware( path, { autoRender = true, engineSource = consolidate, extension = 'html', options = {}, map } = {} ) { return function views(ctx, next) { let extendsContext = false function render(relPath, locals = {}) { if (extendsContext) { if (this.ctx && this.ctx.req === this.req) ctx = this.ctx else ctx = this } return getPaths(path, relPath, extension).then(paths => { const suffix = paths.ext const state = Object.assign({}, options, ctx.state || {}, locals) // deep copy partials state.partials = Object.assign(Object.create(null), options.partials || {}) if (debug.enabled) debug('render `%s` with %s', paths.rel, JSON.stringify(state, bigIntReplacer())) ctx.type = 'text/html' if (isHtml(suffix) && !map) { return send(ctx, paths.rel, { root: path }) } else { const engineName = map && map[suffix] ? map[suffix] : suffix const render = engineSource[engineName] if (!engineName || !render) return Promise.reject( new Error(`Engine not found for the ".${suffix}" file extension`) ) return render(resolve(path, paths.rel), state).then(html => { // since pug has deprecated `pretty` option // we'll use the `pretty` package in the meanwhile if (locals.pretty) { debug('using `pretty` package to beautify HTML') html = pretty(html) } if (autoRender) { ctx.body = html return html } return Promise.resolve(html) }) } }) } // Use to extends app.context if (!ctx) { extendsContext = true return render } if (ctx.render) return next() ctx.response.render = ctx.render = render return next() } } function isHtml(ext) { return ext === 'html' }