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.
85 lines
2.7 KiB
85 lines
2.7 KiB
import LifecycleUnit from '../lifecycle/Unit.ts'
|
|
import {Unit} from '../lifecycle/decorators.ts'
|
|
import {Handlebars} from '../external/http.ts'
|
|
import {Logging} from '../service/logging/Logging.ts'
|
|
import {fs} from '../external/std.ts'
|
|
|
|
/**
|
|
* Lifecycle unit which sets up and provides basic view engine services.
|
|
* @extends LifecycleUnit
|
|
*/
|
|
@Unit()
|
|
export default class ViewEngine extends LifecycleUnit {
|
|
/**
|
|
* The Handlebars instance.
|
|
* @type Handlebars
|
|
*/
|
|
protected _handlebars!: Handlebars
|
|
|
|
// TODO include basic app info in view data
|
|
|
|
constructor(
|
|
protected readonly logger: Logging,
|
|
) {
|
|
super()
|
|
}
|
|
|
|
async up() {
|
|
this.logger.info(`Setting views base dir: ${this.app.app_path('http', 'views')}`)
|
|
this._handlebars = new Handlebars({
|
|
baseDir: this.app.app_path('http', 'views'),
|
|
extname: '.hbs',
|
|
layoutsDir: 'layouts',
|
|
partialsDir: 'partials',
|
|
defaultLayout: 'main',
|
|
helpers: undefined,
|
|
compilerOptions: undefined,
|
|
})
|
|
|
|
const main_layout_path = this.app.app_path('http', 'views', 'layouts', 'main.hbs')
|
|
if ( !(await fs.exists(main_layout_path)) ) {
|
|
this.logger.warn(`Unable to open main view layout file: ${main_layout_path}`)
|
|
this.logger.warn(`Unless you are using a custom layout, this could cause errors.`)
|
|
}
|
|
|
|
const partials_path = this.app.app_path('http', 'views', 'partials')
|
|
if ( !(await fs.exists(partials_path)) ) {
|
|
this.logger.warn(`Unable to open view partials directory: ${partials_path}`)
|
|
this.logger.warn(`This directory must exist for the view engine to function, even if it is empty.`)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The handlebars instance.
|
|
* @type Handlebars
|
|
*/
|
|
get handlebars(): Handlebars {
|
|
return this._handlebars
|
|
}
|
|
|
|
/**
|
|
* Render a view with the given name, using the specified arguments and layout.
|
|
* @param {string} view
|
|
* @param [args]
|
|
* @param {string} [layout]
|
|
* @return Promise<string>
|
|
*/
|
|
async render(view: string, args?: any, layout?: string): Promise<string> {
|
|
this.logger.debug(`Rendering view: ${view}`)
|
|
return this.handlebars.renderView(view, args, layout)
|
|
}
|
|
|
|
/**
|
|
* Render a partial view with the given name, using the specified arguments.
|
|
* @param {string} view
|
|
* @param [args]
|
|
*/
|
|
async partial(view: string, args?: any) {
|
|
const parts = `${view}.hbs`.split(':')
|
|
const resolved = this.app.app_path('http', 'views', ...parts)
|
|
|
|
this.logger.debug(`Rendering partial: ${view} from ${resolved}`)
|
|
return this.handlebars.render(resolved, args)
|
|
}
|
|
}
|