UNPKG

sgapps-server

Version:
272 lines (253 loc) 7.19 kB
/* On template Rendering we have following variables var vars = {}; // variables that a sent from controllers var env = { error : [], vars : envVars, path : "", // filePath dirname : "", // dirname render : function( text, vars, env ) {}, // render function renderFile : function( file, vars, callback ) {}, // render file function // callback( error {{ [] or false }}, htm) }; env.vars = { // env varssent from app response : [object] // http reponse object } */ /** * @class * @name FaceboxTemplate * @param {object} options * @param {FSLibrary} options._fs */ function FaceboxTemplate(options) { /** * @memberof FaceboxTemplate# * @var {boolean} _debug */ let _debug = false; Object.defineProperty( this, '_debug', { get: () => _debug, set: (v) => { _debug = !!v; } } ); /** * @memberof FaceboxTemplate# * @var {Object<string,any>} _env */; let _env = {}; Object.defineProperty( this, '_env', { get: () => _env, set: (data) => { Object.assign(_env, data); } } ); /** * @memberof FaceboxTemplate# * @var {Object<string,string>} _cachedFiles */ this._cachedFiles = {}; const readFileSync = (addr) => { if (addr in this._cachedFiles) { return this._cachedFiles[addr]; } else { //@ts-ignore const content = options._fs.readFileSync( addr, { encoding: "utf-8" } ); // @ts-ignore if (!this._debug) { this._cachedFiles[addr] = content; } return content; } }; /** * @memberof FaceboxTemplate# * @var {number} INCLUDE_LEVEL */ this.INCLUDE_LEVEL = 10; /** * @memberof FaceboxTemplate# * @method render * @param {string} text * @param {Object<string,any>} vars * @param {Object<string,any>} env * @this FaceboxTemplate */ this.render = function FaceboxTemplateRender( text, vars, env ) { if (vars === undefined) vars = {}; const template = { text: text }; const replacers = []; let err = false; /** * @private * @param {string} addr * @returns {string} */ const parseAddr = function parseAddr(addr) { let err; if(addr.subs(1) == ":") { return `${env.dirname.replace(/\/+$/,'')}/${addr.subs(1,0)}`; } else { try { // jshint -W054 return (new Function( `const env = arguments[1];const vars = arguments[0];\n return ${addr}` ))(vars, env); // jshint +W054 } catch(err) { throw Error( `Unable to eval path: ${addr} ; ${err.meesage} ;` ); } } }.bind(this); text = text.replace( /\{\{(read|read\-base64|read\-hex)\:(.*?)\}\}/g, function (match, p1, p2, offset, string) { const x = '[[replacer-'+Math.floor(Math.random()*10000000)+'-'+Math.floor(Math.random()*10000000)+'-'+new Date().valueOf()+']]'; replacers.push({ id : x, type : 'action-'+p1, param : p2 }); return x; } ); text = text.replace( /\{\{(include)\:(.*?)\}\}/g, function (match, p1, p2, offset, string) { return readFileSync( parseAddr(p2) ); } ); text = text.replace( /\{\{(render)\:(.*?)\}\}/g, function (match, p1, p2, offset, string) { const addr = parseAddr(p2); return this.render( readFileSync(addr), vars, { vars : this._env, path : addr, dirname : ((addr).replace(/[^\/]+$/,'')+'/').replace(/^\/+$/,'/'), render : this.render, renderFile : this.renderFile } ); }.bind(this) ); text = text.replace( // jshint -W049 /\<script[^\>]+?type\s*?=\s*?\"text\/facebox\-template\"[^\>]*?\>([\s\S]*?)\<\/script\>/g, // jshint +W049 function (match, p1, p2, offset, string) { const x = '[[replacer-'+Math.floor(Math.random()*10000000)+'-'+Math.floor(Math.random()*10000000)+'-'+new Date().valueOf()+']]'; replacers.push({ id : x, type : 'js-return', code : p1 }); return x; } ); text = text.replace( /\{(code|js\-return|eval|js\-script|css\-style)\}([\s\S]*?)\{\/\1\}/g, function (match, p1, p2, offset, string) { const x = '[[replacer-'+Math.floor(Math.random()*10000000)+'-'+Math.floor(Math.random()*10000000)+'-'+new Date().valueOf()+']]'; replacers.push({ id : x, type : p1, code : p2 }); return x; } ); text = text.replace( /\{\{([\s\S]*?)\}\}/g, function (match, p1, offset, string) { const x = '[[replacer-'+Math.floor(Math.random()*10000000)+'-'+Math.floor(Math.random()*10000000)+'-'+new Date().valueOf()+']]'; replacers.push({ id : x, type : 'js-return', code : 'return '+p1 }); return x; } ); let i; for (i=0; i<replacers.length; i++) { switch(replacers[i].type) { case 'code': text = text.split(replacers[i].id).join(replacers[i].code); break; case 'js-return': // jshint -W054 text = text.split(replacers[i].id).join((new Function("var vars = arguments[0];var env = arguments[1];\nvar result = (function faceBoxTemplate_jsReturn() {\n"+replacers[i].code + "\n})(); if (result === undefined) return ''; return result;" ))( vars, env )); // jshint +W054 break; case 'eval': // jshint -W054 (new Function("var vars = arguments[0];var env = arguments[1];\n"+replacers[i].code ))( vars, env ); // jshint +W054 text = text.split(replacers[i].id).join(''); break; case 'js-script': text = text.split(replacers[i].id).join('<script type="text/javascript" charset="utf-8">\n'+replacers[i].code+'\n</script>'); break; case 'css-style': text = text.split(replacers[i].id).join('<style type="text/css">\n'+replacers[i].code+'\n</style>'); break; case 'action-read': text = text.split(replacers[i].id).join(readFileSync(parseAddr(replacers[i].param))); break; case 'action-read-base64': text = text.split(replacers[i].id).join(readFileSync(parseAddr(replacers[i].param)).base64encode()); break; case 'action-read-hex': text = text.split(replacers[i].id).join(readFileSync(parseAddr(replacers[i].param)).toHex()); break; } } return text; }.bind(this); /** * @memberof FaceboxTemplate# * @method renderFile * @param {string} filePath * @param {Object<string,any>} vars * @param {function} callback * @this FaceboxTemplate */ this.renderFile = function( filePath, vars, callback ) { const env = { vars : this._env, path : filePath, dirname : (filePath.replace(/[^\/]+$/,'')+'/').replace(/^\/+$/,'/'), render : this.render, renderFile : this.renderFile }; callback( null, this.render( readFileSync( filePath ), vars, env ) ); }.bind(this); /** * @memberof FaceboxTemplate# * @method renderCode * @param {string} code * @param {Object<string,any>} vars * @param {function} callback * @param {string} virtualFilePath * @this FaceboxTemplate */ this.renderCode = function( code, vars, callback, virtualFilePath ) { const env = { vars : this._env, path : virtualFilePath || '', dirname : ((virtualFilePath || '').replace(/[^\/]+$/,'')+'/').replace(/^\/+$/,'/'), render : this.render, renderFile : this.renderFile }; callback( null, this.render(code, vars, env) ); }.bind(this); return this; }; module.exports = FaceboxTemplate;