2020-07-11 11:46:16 +02:00
|
|
|
import nunjucks, {Environment} from "nunjucks";
|
2020-04-23 11:18:23 +02:00
|
|
|
import config from "config";
|
2020-09-25 22:03:22 +02:00
|
|
|
import {Express, NextFunction, Request, Response, Router} from "express";
|
2020-04-23 11:18:23 +02:00
|
|
|
import ApplicationComponent from "../ApplicationComponent";
|
|
|
|
import Controller from "../Controller";
|
|
|
|
import {ServerError} from "../HttpError";
|
2020-07-15 10:24:01 +02:00
|
|
|
import * as querystring from "querystring";
|
2020-07-15 11:42:49 +02:00
|
|
|
import {ParsedUrlQueryInput} from "querystring";
|
2020-07-26 11:37:36 +02:00
|
|
|
import * as util from "util";
|
2020-09-24 22:33:37 +02:00
|
|
|
import * as path from "path";
|
2020-09-25 22:03:22 +02:00
|
|
|
import * as fs from "fs";
|
|
|
|
import Logger from "../Logger";
|
|
|
|
import Middleware from "../Middleware";
|
2020-04-23 11:18:23 +02:00
|
|
|
|
2020-09-25 22:03:22 +02:00
|
|
|
export default class NunjucksComponent extends ApplicationComponent {
|
2020-09-24 22:33:37 +02:00
|
|
|
private readonly viewsPath: string[];
|
2020-07-11 11:46:16 +02:00
|
|
|
private env?: Environment;
|
2020-07-08 10:49:29 +02:00
|
|
|
|
2020-09-24 22:33:37 +02:00
|
|
|
public constructor(viewsPath: string[] = ['views']) {
|
2020-07-08 10:49:29 +02:00
|
|
|
super();
|
|
|
|
this.viewsPath = viewsPath;
|
|
|
|
}
|
|
|
|
|
2020-07-11 11:46:16 +02:00
|
|
|
public async start(app: Express): Promise<void> {
|
2020-07-08 11:09:27 +02:00
|
|
|
let coreVersion = 'unknown';
|
2020-09-25 22:03:22 +02:00
|
|
|
const file = fs.existsSync(path.join(__dirname, '../../package.json')) ?
|
|
|
|
path.join(__dirname, '../../package.json') :
|
|
|
|
path.join(__dirname, '../package.json');
|
|
|
|
|
2020-07-08 11:09:27 +02:00
|
|
|
try {
|
2020-09-25 22:03:22 +02:00
|
|
|
coreVersion = JSON.parse(fs.readFileSync(file).toString()).version;
|
2020-07-08 11:09:27 +02:00
|
|
|
} catch (e) {
|
2020-09-25 22:03:22 +02:00
|
|
|
Logger.warn('Couldn\'t determine coreVersion.', e);
|
2020-07-08 11:09:27 +02:00
|
|
|
}
|
|
|
|
|
2020-09-24 22:33:37 +02:00
|
|
|
this.env = new nunjucks.Environment([
|
|
|
|
...this.viewsPath.map(path => new nunjucks.FileSystemLoader(path)),
|
|
|
|
new nunjucks.FileSystemLoader(path.join(__dirname, '../../../views')),
|
|
|
|
new nunjucks.FileSystemLoader(path.join(__dirname, '../views')),
|
2020-07-12 11:46:21 +02:00
|
|
|
], {
|
2020-04-23 11:18:23 +02:00
|
|
|
autoescape: true,
|
|
|
|
noCache: !config.get('view.cache'),
|
|
|
|
throwOnUndefined: true,
|
|
|
|
})
|
2020-07-15 11:42:49 +02:00
|
|
|
.addGlobal('route', (route: string, params?: { [p: string]: string } | [], query?: ParsedUrlQueryInput, absolute?: boolean) => {
|
|
|
|
const path = Controller.route(route, params, query, absolute);
|
2020-04-23 11:18:23 +02:00
|
|
|
if (path === null) throw new ServerError(`Route ${route} not found.`);
|
|
|
|
return path;
|
|
|
|
})
|
2020-09-25 22:03:22 +02:00
|
|
|
.addGlobal('app_version', this.getApp().getVersion())
|
2020-07-08 11:09:27 +02:00
|
|
|
.addGlobal('core_version', coreVersion)
|
2020-07-15 10:24:01 +02:00
|
|
|
.addGlobal('querystring', querystring)
|
2020-09-23 16:11:51 +02:00
|
|
|
.addGlobal('app', config.get('app'))
|
|
|
|
|
2020-07-26 11:37:36 +02:00
|
|
|
.addFilter('dump', (val) => {
|
|
|
|
return util.inspect(val);
|
|
|
|
})
|
2020-04-23 11:18:23 +02:00
|
|
|
.addFilter('hex', (v: number) => {
|
|
|
|
return v.toString(16);
|
|
|
|
});
|
2020-09-24 22:33:37 +02:00
|
|
|
this.env.express(app);
|
2020-04-23 11:18:23 +02:00
|
|
|
app.set('view engine', 'njk');
|
2020-07-11 11:46:16 +02:00
|
|
|
}
|
2020-04-23 11:18:23 +02:00
|
|
|
|
2020-07-11 11:46:16 +02:00
|
|
|
public async init(router: Router): Promise<void> {
|
2020-09-25 22:03:22 +02:00
|
|
|
this.use(NunjucksMiddleware);
|
2020-04-23 11:18:23 +02:00
|
|
|
}
|
2020-09-23 16:11:51 +02:00
|
|
|
|
|
|
|
public getEnv(): Environment | undefined {
|
|
|
|
return this.env;
|
|
|
|
}
|
2020-09-25 22:03:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export class NunjucksMiddleware extends Middleware {
|
|
|
|
private env?: Environment;
|
|
|
|
|
|
|
|
protected async handle(req: Request, res: Response, next: NextFunction): Promise<void> {
|
|
|
|
this.env = this.app.as(NunjucksComponent).getEnv();
|
|
|
|
res.locals.url = req.url;
|
|
|
|
res.locals.params = req.params;
|
|
|
|
res.locals.query = req.query;
|
|
|
|
res.locals.body = req.body;
|
|
|
|
|
|
|
|
next();
|
|
|
|
}
|
|
|
|
|
|
|
|
public getEnvironment(): Environment {
|
|
|
|
if (!this.env) throw new Error('Environment not initialized.');
|
|
|
|
return this.env;
|
|
|
|
}
|
|
|
|
}
|