-
Notifications
You must be signed in to change notification settings - Fork 56
/
Copy pathindex.js
127 lines (108 loc) · 3.06 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*!
* @koa/ejs
*
* Copyright(c) 2017 dead_horse <[email protected]>
* Copyright(c) 2021-2022 3imed-jaberi <[email protected]>
* MIT Licensed
*/
'use strict'
/**
* Module dependencies.
*/
const ejs = require('ejs')
const path = require('path')
const debug = require('debug')('@koa/ejs')
/**
* Temp assigned for override later
*/
const parentResolveInclude = ejs.resolveInclude
/**
* default render options
* @type {Object}
*/
const defaultSettings = {
cache: true,
layout: 'layout',
viewExt: 'html',
locals: {},
compileDebug: false,
debug: false,
writeResp: true,
async: false
}
exports = module.exports = koaEjs
/**
* set app.context.render
*
* usage:
* ```
* await ctx.render('user', {name: 'dead_horse'});
* ```
* @param {Application} app koa application instance
* @param {Object} settings user settings
*/
function koaEjs (app, settings) {
if (app.context.render) return
if (!settings || !settings.root) throw new Error('settings.root required')
settings.root = path.resolve(process.cwd(), settings.root)
// cache the generate package
const cache = {}
settings = { ...defaultSettings, ...settings }
settings.viewExt = settings.viewExt ? '.' + settings.viewExt.replace(/^\./, '') : ''
settings.fs = settings.fs || require('fs/promises')
// override `ejs` node_module `resolveInclude` function
ejs.resolveInclude = function (name, filename, isDir) {
if (!path.extname(name)) name += settings.viewExt
return parentResolveInclude(name, filename, isDir)
}
/**
* generate html with view name and options
*
* @param {String} view
* @param {Object} options
* @return {String} html
*/
async function render (view, options) {
view += settings.viewExt
const viewPath = path.join(settings.root, view)
debug(`render: ${viewPath}`)
// get from cache
if (settings.cache && cache[viewPath]) return cache[viewPath].call(options.scope, options)
const tpl = await settings.fs.readFile(viewPath, 'utf8')
const fn = ejs.compile(tpl, {
filename: viewPath,
_with: settings._with,
compileDebug: settings.debug && settings.compileDebug,
debug: settings.debug,
delimiter: settings.delimiter,
cache: settings.cache,
async: settings.async,
outputFunctionName: settings.outputFunctionName
})
if (settings.cache) cache[viewPath] = fn
return fn.call(options.scope, options)
}
app.context.render = async function (view, _context) {
const ctx = this
const context = { ...ctx.state, ..._context }
let html = await render(view, context)
const layout = context.layout === false ? false : (context.layout || settings.layout)
if (layout) {
// if using layout
context.body = html
html = await render(layout, context)
}
const writeResp = context.writeResp === false ? false : (context.writeResp || settings.writeResp)
if (writeResp) {
// normal operation
ctx.type = 'html'
ctx.body = html
}
// only return the html
return html
}
};
/**
* Expose ejs
*/
exports.ejs = ejs