Skip to content

Commit

Permalink
support custom fs module with same interface like 🐝 ..
Browse files Browse the repository at this point in the history
  • Loading branch information
3imed-jaberi committed Jul 9, 2022
1 parent 9fcef07 commit eb93c97
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 70 deletions.
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
The MIT License (MIT)

Copyright(c) 2017 dead_horse
Copyright(c) 2021-2022 imed-jaberi <imed-jaberi@outlook.com>
Copyright(c) 2017 dead_horse
Copyright(c) 2021-2022 3imed-jaberi <imed-jaberi@outlook.com>

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Or you can checkout the [example](https://github.com/koajs/ejs/tree/master/examp
### Settings

- root: view root directory.
- fs: file system module with same Node.js fs interface (default `Node.js fs module`).
- layout: global layout file, default is `layout`, set `false` to disable layout.
- viewExt: view file extension (default `html`).
- cache: cache compiled templates (default `true`).
Expand Down
51 changes: 51 additions & 0 deletions example/app-with-custom-fs-module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*!
* koa-ejs - example/app-with-custom-fs-module
*
* Copyright(c) 2022 3imed-jaberi <imed-jaberi@outlook.com>
* MIT Licensed
*/

'use strict'

/**
* Module dependencies.
*/

const Koa = require('koa')
const render = require('..')
const path = require('path')

const app = new Koa()

render(app, {
root: path.join(__dirname, 'view'),
fs: require('mz/fs'),
layout: 'template',
viewExt: 'html',
cache: false,
debug: false
})

app
.use(function (ctx, next) {
ctx.state = ctx.state || {}
ctx.state.now = new Date()
ctx.state.ip = ctx.ip
ctx.state.version = '2.0.0'
return next()
})
.use(async function (ctx) {
const users = [{ name: 'Dead Horse' }, { name: 'Imed Jaberi' }, { name: 'Tom' }]
await ctx.render('content', { users })
})

if (process.env.NODE_ENV === 'test') {
module.exports = app.callback()
} else {
app.listen(7001)
console.log('open http://localhost:7001')
}

app.on('error', function (err) {
console.log(err.stack)
})
1 change: 1 addition & 0 deletions example/app.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*!
* koa-ejs - example/app.js
*
* Copyright(c) 2017 dead_horse <dead_horse@qq.com>
* MIT Licensed
*/
Expand Down
8 changes: 4 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/*!
* koa-ejs
*
* Copyright(c) 2017 dead_horse <dead_horse@qq.com>
* Copyright(c) 2021-2022 imed-jaberi <imed-jaberi@outlook.com>
* Copyright(c) 2017 dead_horse <dead_horse@qq.com>
* Copyright(c) 2021-2022 3imed-jaberi <imed-jaberi@outlook.com>
* MIT Licensed
*/

Expand All @@ -14,7 +14,6 @@

const ejs = require('ejs')
const path = require('path')
const fs = require('fs/promises')
const debug = require('debug')('koa-ejs')

/**
Expand Down Expand Up @@ -57,6 +56,7 @@ function koaEjs (app, settings) {
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) {
Expand All @@ -78,7 +78,7 @@ function koaEjs (app, settings) {
// get from cache
if (settings.cache && cache[viewPath]) return cache[viewPath](options.scope, options)

const tpl = await fs.readFile(viewPath, 'utf8')
const tpl = await settings.fs.readFile(viewPath, 'utf8')

const fn = ejs.compile(tpl, {
filename: viewPath,
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"eslint-plugin-standard": "^5.0.0",
"koa": "^2.13.4",
"mocha": "^10.0.0",
"mz": "^2.7.0",
"nyc": "^15.1.0",
"should": "^13.2.3",
"supertest": "^6.2.4"
Expand Down
216 changes: 152 additions & 64 deletions test/koa-ejs.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,85 +39,173 @@ describe('test/koa-ejs.test.js', function () {
})

describe('server', function () {
it('should render page ok', function (done) {
const app = require('../example/app')
request(app)
.get('/')
.expect(200)
.expect('content-type', 'text/html; charset=utf-8')
.expect(/<title>koa ejs<\/title>/)
.expect(/Dead Horse/)
.expect(/Imed Jaberi/, done)
})
it('should render page ok with async functions', function (done) {
const app = new Koa()
render(app, {
root: 'example/view',
viewExt: 'html',
layout: false,
async: true
describe('with default node.js fs module', () => {
it('should render page ok', function (done) {
const app = require('../example/app')
request(app)
.get('/')
.expect(200)
.expect('content-type', 'text/html; charset=utf-8')
.expect(/<title>koa ejs<\/title>/)
.expect(/Dead Horse/)
.expect(/Imed Jaberi/, done)
})
it('should render page ok with async functions', function (done) {
const app = new Koa()
render(app, {
root: 'example/view',
viewExt: 'html',
layout: false,
async: true
})

app.use(async function (ctx) {
await ctx.render('async', {
async sayHello (name) {
return `Hello, ${name}`
}
app.use(async function (ctx) {
await ctx.render('async', {
async sayHello (name) {
return `Hello, ${name}`
}
})
})
request(app.callback())
.get('/')
.expect(200)
.expect('content-type', 'text/html; charset=utf-8')
.expect(/Hello, Jack/, done)
})
request(app.callback())
.get('/')
.expect(200)
.expect('content-type', 'text/html; charset=utf-8')
.expect(/Hello, Jack/, done)
})
it('should render page ok with custom open/close', function (done) {
const app = new Koa()
render(app, {
root: 'example/view',
layout: 'template.oc',
viewExt: 'html',
delimiter: '?'
it('should render page ok with custom open/close', function (done) {
const app = new Koa()
render(app, {
root: 'example/view',
layout: 'template.oc',
viewExt: 'html',
delimiter: '?'
})

app.use(async function (ctx) {
await ctx.render('user.oc', {
user: { name: 'Zed Gu' }
})
})
request(app.callback())
.get('/')
.expect(200)
.expect('content-type', 'text/html; charset=utf-8')
.expect(/Zed Gu/, done)
})
it('should render page ok with `viewExt` option supporting `include` directive', function (done) {
const app = new Koa()
render(app, {
root: 'example/view',
layout: 'template',
viewExt: 'html',
cache: false
})

app.use(function (ctx, next) {
ctx.state = ctx.state || {}
ctx.state.ip = ctx.ip
return next()
})

app.use(async function (ctx) {
await ctx.render('user.oc', {
user: { name: 'Zed Gu' }
app.use(async function (ctx) {
const users = [{ name: 'Dead Horse' }, { name: 'Runrioter Wung' }]
await ctx.render('content.noext', {
users
})
})
request(app.callback())
.get('/')
.expect(200)
.expect('content-type', 'text/html; charset=utf-8')
.expect(/Dead Horse/)
.expect(/Runrioter Wung/, done)
})
request(app.callback())
.get('/')
.expect(200)
.expect('content-type', 'text/html; charset=utf-8')
.expect(/Zed Gu/, done)
})
it('should render page ok with `viewExt` option supporting `include` directive', function (done) {
const app = new Koa()
render(app, {
root: 'example/view',
layout: 'template',
viewExt: 'html',
cache: false

describe('with custom node.js fs module like', () => {
it('should render page ok', function (done) {
const app = require('../example/app-with-custom-fs-module')
request(app)
.get('/')
.expect(200)
.expect('content-type', 'text/html; charset=utf-8')
.expect(/<title>koa ejs<\/title>/)
.expect(/Dead Horse/)
.expect(/Imed Jaberi/, done)
})
it('should render page ok with async functions', function (done) {
const app = new Koa()
render(app, {
root: 'example/view',
fs: require('mz/fs'),
viewExt: 'html',
layout: false,
async: true
})

app.use(function (ctx, next) {
ctx.state = ctx.state || {}
ctx.state.ip = ctx.ip
return next()
app.use(async function (ctx) {
await ctx.render('async', {
async sayHello (name) {
return `Hello, ${name}`
}
})
})
request(app.callback())
.get('/')
.expect(200)
.expect('content-type', 'text/html; charset=utf-8')
.expect(/Hello, Jack/, done)
})
it('should render page ok with custom open/close', function (done) {
const app = new Koa()
render(app, {
root: 'example/view',
fs: require('mz/fs'),
layout: 'template.oc',
viewExt: 'html',
delimiter: '?'
})

app.use(async function (ctx) {
await ctx.render('user.oc', {
user: { name: 'Zed Gu' }
})
})
request(app.callback())
.get('/')
.expect(200)
.expect('content-type', 'text/html; charset=utf-8')
.expect(/Zed Gu/, done)
})
it('should render page ok with `viewExt` option supporting `include` directive', function (done) {
const app = new Koa()
render(app, {
root: 'example/view',
fs: require('mz/fs'),
layout: 'template',
viewExt: 'html',
cache: false
})

app.use(function (ctx, next) {
ctx.state = ctx.state || {}
ctx.state.ip = ctx.ip
return next()
})

app.use(async function (ctx) {
const users = [{ name: 'Dead Horse' }, { name: 'Runrioter Wung' }]
await ctx.render('content.noext', {
users
app.use(async function (ctx) {
const users = [{ name: 'Dead Horse' }, { name: 'Runrioter Wung' }]
await ctx.render('content.noext', {
users
})
})
request(app.callback())
.get('/')
.expect(200)
.expect('content-type', 'text/html; charset=utf-8')
.expect(/Dead Horse/)
.expect(/Runrioter Wung/, done)
})
request(app.callback())
.get('/')
.expect(200)
.expect('content-type', 'text/html; charset=utf-8')
.expect(/Dead Horse/)
.expect(/Runrioter Wung/, done)
})
})
})

0 comments on commit eb93c97

Please sign in to comment.