You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lib/src/views/ViewEngine.ts

93 lines
2.9 KiB

import {AppClass} from '../lifecycle/AppClass'
import {Config} from '../service/Config'
import {Container} from '../di'
import {ErrorWithContext, UniversalPath} from '../util'
/**
* Abstract base class for rendering views via different view engines.
*/
export abstract class ViewEngine extends AppClass {
protected readonly config: Config
protected readonly debug: boolean
protected readonly namespaces: {[key: string]: UniversalPath} = {}
constructor() {
super()
this.config = Container.getContainer().make(Config)
this.debug = (this.config.get('server.mode', 'production') === 'development'
|| this.config.get('server.debug', false))
}
/**
* Get the UniversalPath to the base directory where views are loaded from.
*/
public get path(): UniversalPath {
return this.app().appPath(...['resources', 'views']) // FIXME allow configuring
}
/**
* Given a template string and a set of variables for the view, render the string to HTML and return it.
* @param templateString
* @param locals
*/
public abstract renderString(templateString: string, locals: {[key: string]: any}): string | Promise<string>
/**
* Given the canonical name of a template file, render the file using the provided variables.
* @param templateName
* @param locals
*/
public abstract renderByName(templateName: string, locals: {[key: string]: any}): string | Promise<string>
public registerNamespace(namespace: string, basePath: UniversalPath): this {
if ( namespace.startsWith('@') ) {
namespace = namespace.substr(1)
}
this.namespaces[namespace] = basePath
return this
}
public resolveName(templateName: string): UniversalPath {
let path = this.path
if ( templateName.startsWith('@') ) {
const [namespace, ...parts] = templateName.split(':')
path = this.namespaces[namespace.substr(1)]
if ( !path ) {
throw new ErrorWithContext('Invalid template namespace: ' + namespace, {
namespace,
templateName,
})
}
templateName = parts.join(':')
}
if ( !templateName.endsWith('.pug') ) {
templateName += '.pug'
}
return path.concat(...templateName.split(':'))
}
public resolveBasePath(templateName: string): UniversalPath {
let path = this.path
if ( templateName.startsWith('@') ) {
const [namespace] = templateName.split(':')
path = this.namespaces[namespace.substr(1)]
if ( !path ) {
throw new ErrorWithContext('Invalid template namespace: ' + namespace, {
namespace,
templateName,
})
}
}
return path
}
}