UNPKG

apim-tools

Version:

APIM Tools

143 lines (121 loc) 3.95 kB
/** * @file etpl 模板渲染处理器 * @author wuhuiyao@baidu.com */ 'use strict'; const fs = require('fs'); const pathUtil = require('path'); const etpl = require('etpl'); const isPlainObject = require('lodash.isplainobject'); /** * 初始化过滤器 * * @param {Object} engine 模板引擎 * @param {Object} filters 要初始化的过滤器 */ function initFilters(engine, filters) { if (!filters) { return; } Object.keys(filters).forEach(name => { let f = filters[name]; if (typeof f === 'function') { engine.addFilter(name, f); } }); } const DEFAULT_OPTIONS = { tplDir: process.cwd(), tplExtName: 'etpl', encoding: 'utf-8', engine: { commandOpen: '{{', commandClose: '}}', variableOpen: '{%', variableClose: '%}' }, filters: { /* eslint-disable fecs-camelcase */ json_encode: function (source) { return JSON.stringify(source); } } }; function loadAllTpls(engine, options) { let glob = require('glob'); let templateDir = options.tplDir; let tplExtName = options.tplExtName; let files = glob.sync(`**/*${tplExtName}`, { cwd: templateDir, root: templateDir }); let encoding = options.encoding; files.forEach(file => { file = pathUtil.resolve(templateDir, file); engine.compile(fs.readFileSync(file, encoding).toString()); }); } function loadTplFile(tplFile, options, context) { tplFile = pathUtil.join(options.tplDir, tplFile); try { return fs.readFileSync(tplFile, options.encoding); } catch (ex) { context.logger.error('load tpl file', tplFile, 'fail'); return false; } } function createRenderEngine(options) { let enginOptions = Object.assign({}, DEFAULT_OPTIONS.engine, options.engine); const engine = new etpl.Engine(enginOptions); let filterOptions = Object.assign({}, DEFAULT_OPTIONS.filters, options.filters); initFilters(engine, filterOptions); return engine; } module.exports = exports = function (mockData, options, context) { const tplOptions = { tplDir: options.tplDir || DEFAULT_OPTIONS.tplDir || options.baseDir, tplExtName: options.tplExtName || DEFAULT_OPTIONS.tplExtName, encoding: options.encoding || DEFAULT_OPTIONS.encoding }; const engine = createRenderEngine(options); return new Promise((resolve, reject) => { if (!isPlainObject(mockData)) { /* eslint-disable fecs-camelcase */ return resolve({_data: mockData}); } let tplTarget = mockData._tplTarget; let tplPath = mockData._tpl; if (!tplTarget && tplPath) { let tplContent = loadTplFile(tplPath, tplOptions, context); if (tplContent === false) { return reject(`load tpl ${tplPath} fail`); } let parseInfo = etpl.util.parseSource(tplContent, engine); let targetNames = parseInfo.targets; if (targetNames.length) { tplTarget = targetNames[0]; } } if (!tplTarget) { return reject('tpl target not specified in mock data'); } try { loadAllTpls(engine, tplOptions); } catch (ex) { let errorInfo = `load tpl file fail: ${ex.toString()}`; context.logger.error(errorInfo); return reject(errorInfo); } let renderer = engine.getRenderer(tplTarget); if (!renderer) { return reject(`ETPL template target "${tplTarget}" not found`); } let tplData = context.normalizeMockData(mockData); context.logger.debug('render etpl using data', tplData); let result = renderer(tplData); /* eslint-disable fecs-camelcase */ return resolve({_data: result}); }); };