@absolunet/ioc2.1.0

View on GitHub

view/services/Engine/drivers/JsRenderDriver.js

//--------------------------------------------------------
//-- Node IoC - View - Services - Drivers - JSRender driver
//--------------------------------------------------------

import Driver from './Driver';


/**
 * JSRender view engine driver.
 *
 * @memberof view.services.Engine.drivers
 * @augments view.services.Engine.drivers.Driver
 * @hideconstructor
 */
class JsRenderDriver extends Driver {

	/**
	 * Class dependencies: <code>['app']</code>.
	 *
	 * @type {Array<string>}
	 */
	static get dependencies() {
		return (super.dependencies || []).concat(['app']);
	}

	/**
	 * @inheritdoc
	 * @private
	 */
	init() {
		this.setEngine(require('jsrender')); // eslint-disable-line global-require
		this.createCustomHelpers();
		this.createCustomTags();
	}

	/**
	 * @inheritdoc
	 */
	make(view) {
		return this.engine.templates(view);
	}

	/**
	 * @inheritdoc
	 */
	render(view, data = {}) {
		return this.make(view).render(data);
	}

	/**
	 * Create custom JSRender helper functions.
	 */
	createCustomHelpers() {
		this.createInjectHelper();
		this.createConfigHelper();
		this.createRouteHelper();
		this.createTranslateHelper();
		this.createDumpHelper();
	}

	/**
	 * Create "inject" helper function.
	 */
	createInjectHelper() {
		this.engine.views.helpers('inject', (...parameters) => {
			return this.app.make(...parameters);
		});
	}

	/**
	 * Create "config" helper function.
	 */
	createConfigHelper() {
		this.engine.views.helpers('config', (...parameters) => {
			return this.app.make('config').get(...parameters);
		});
	}

	/**
	 * Create "route" helper function.
	 */
	createRouteHelper() {
		this.engine.views.helpers('route', (name, parameters = {}) => {
			const route = this.app.make('router.route').findByName(name);

			return route.compilePath(parameters).compiledPath || '/';
		});
	}

	/**
	 * Create "t" helper function.
	 */
	createTranslateHelper() {
		this.engine.views.helpers('t', (...parameters) => {
			return this.app.make('translator').translate(...parameters);
		});
	}

	/**
	 * Create "dump" helper function.
	 */
	createDumpHelper() {
		const { app } = this;
		this.engine.views.helpers('dump', function(...parameters) {
			const dumper = app.make('dumper');
			let meta;
			let current = this; // eslint-disable-line consistent-this

			while (!meta && current) {
				({ __meta: meta } = current.data);
				current = current.parent;
			}

			if (meta) {
				return dumper.getDumpForFile(meta.path, ...parameters);
			}

			return dumper.getDump(...parameters);
		});
	}

	/**
	 * Create all JSRender custom tags.
	 */
	createCustomTags() {
		this.createIncludeTag();
	}

	/**
	 * Create "include" tag.
	 * JSRender already defines this tag, but an overwrite is necessary in order to use the view resolver.
	 */
	createIncludeTag() {
		const self = this;

		this.engine.views.tags('include', {
			render() {
				const { name, data = {}, inline, escape } = this.tagCtx.props;
				data.slot = data.slot || this.tagCtx.render();

				let render = self.view.make(name, data);

				if (inline) {
					render = render.replace(/\n/gu, '');
				}

				if (escape) {
					render = render.replace(/\\/gu, '\\\\');
				}

				return render;
			}
		});

	}

	/**
	 * View factory.
	 *
	 * @type {view.services.Factory}
	 */
	get view() {
		return this.app.make('view');
	}

}


export default JsRenderDriver;