swaf/src/components/NunjucksComponent.ts

94 lines
3.1 KiB
TypeScript
Raw Normal View History

import nunjucks, {Environment} from "nunjucks";
2020-04-23 11:18:23 +02:00
import config from "config";
import {Express, NextFunction, Request, Response, Router} from "express";
2020-04-23 11:18:23 +02:00
import ApplicationComponent from "../ApplicationComponent";
2020-10-02 12:13:34 +02:00
import Controller, {RouteParams} from "../Controller";
import * as querystring from "querystring";
2020-10-02 12:13:34 +02:00
import {ParsedUrlQueryInput} from "querystring";
import * as util from "util";
import * as path from "path";
import * as fs from "fs";
import {log} from "../Logger";
import Middleware from "../Middleware";
2020-04-23 11:18:23 +02:00
export default class NunjucksComponent extends ApplicationComponent {
private readonly viewsPath: string[];
private env?: Environment;
public constructor(viewsPath: string[] = ['views']) {
super();
this.viewsPath = viewsPath;
}
public async start(app: Express): Promise<void> {
2020-07-08 11:09:27 +02:00
let coreVersion = 'unknown';
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 {
coreVersion = JSON.parse(fs.readFileSync(file).toString()).version;
2020-07-08 11:09:27 +02:00
} catch (e) {
log.warn('Couldn\'t determine coreVersion.', e);
2020-07-08 11:09:27 +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-10-02 12:13:34 +02:00
.addGlobal('route', (
route: string,
params: RouteParams = [],
query: ParsedUrlQueryInput = {},
absolute: boolean = false,
): string => {
return Controller.route(route, params, query, absolute);
})
.addGlobal('app_version', this.getApp().getVersion())
2020-07-08 11:09:27 +02:00
.addGlobal('core_version', coreVersion)
.addGlobal('querystring', querystring)
.addGlobal('app', config.get('app'))
.addFilter('dump', (val) => {
return util.inspect(val);
})
2020-04-23 11:18:23 +02:00
.addFilter('hex', (v: number) => {
return v.toString(16);
});
this.env.express(app);
2020-04-23 11:18:23 +02:00
app.set('view engine', 'njk');
}
2020-04-23 11:18:23 +02:00
public async init(_router: Router): Promise<void> {
this.use(NunjucksMiddleware);
2020-04-23 11:18:23 +02:00
}
public getEnv(): Environment | undefined {
return this.env;
}
}
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;
}
}