smarty4js
Version:
A JavaScript Template Engine Most Like Smarty
192 lines (163 loc) • 5.12 kB
JavaScript
/**
* @file Smarty4js
* @author johnson [zoumiaojiang@gmail.com]
* @date 2014-11-13
*/
var Compiler = require('./lib/compiler');
var Renderer = require('./lib/renderer');
var phpfunc = require('./lib/phpfunc');
var func = require('./lib/func');
var utils = require('./lib/utils');
var path = require('path');
var fs = require('fs');
/**
* pretreatment template code
*
* @param {string} code template code
* @param {Object} conf smarty config
* @return {string} code of after pre define
*/
function pretreatmentCode(code, conf) {
var ld = conf.left_delimiter;
var rd = conf.right_delimiter;
var reld = utils.regEscape(ld);
var rerd = utils.regEscape(rd);
// literal filter
var literalPaserModulePath = path.resolve(__dirname, 'lib', 'parser','literal.js');
var literalPaserFile = fs.readFileSync(literalPaserModulePath, 'utf8');
var homePath = utils.getHomePath();
var realLiteralParserFilePath = path.resolve(homePath, 'literal.js');
if (ld !== '{%') {
literalPaserFile = literalPaserFile.replace(/\\\{%/g, reld);
}
if (rd !== '%}') {
literalPaserFile = literalPaserFile.replace(/%\\\}/g, rerd);
}
fs.writeFileSync(realLiteralParserFilePath, literalPaserFile);
var literalAst = require(realLiteralParserFilePath).parse(code);
var newCode = '';
literalAst.forEach(function (node) {
var type = node.type;
var value = node.value;
if (value && value.trim().length > 0) {
if (type === 'TEXT') {
newCode += value;
}
else if (type === 'LTEXT') {
newCode += value.replace(new RegExp(reld, 'g'), '__LD').replace(new RegExp(rerd, 'g'), '__RD');
}
}
});
// jison hack
newCode += (ld + '*smarty4js*' + rd);
return newCode
.replace(/\\\"/g, '__QD') // replace \" in string ""
.replace(/\\\'/g, '__QS'); // replace \' in string ''
}
/**
* @constructor
*/
function Smarty() {
this.id = '__smarty__' + utils.getGUID();
this.phpfunc = phpfunc;
this.func = func;
this.conf = {
'left_delimiter': '{%',
'right_delimiter': '%}',
'isAmd': true,
'isCmd': true,
'globalVar': '_smartyTpl'
};
this.config.apply(this, arguments);
this.compiler = new Compiler(this);
this.renderer = new Renderer(this);
}
/**
* smarty config
* @param {Object} conf config options
*/
Smarty.prototype.config = function (conf) {
this.conf = utils.extend(this.conf, conf);
};
/**
* set tpl file base dir
* @param {string} path base path
*/
Smarty.prototype.setBasedir = function (path) {
this.dirname = path;
}
/**
* compile the smarty template code
* @param {string} tpl smarty template code/file path
* @return {Object} smarty Compiler object, have `render` mathod
*/
Smarty.prototype.compile = function (tpl) {
var conf = this.conf;
var filePath = path.resolve(process.cwd(), (tpl || '' + utils.getGUID()));
var ld = conf.left_delimiter;
var rd = conf.right_delimiter;
var paserModulePath = path.resolve(__dirname, 'lib', 'parser','index.js');
var paserFile = fs.readFileSync(paserModulePath, 'utf8');
var homePath = utils.getHomePath();
var realParserFilePath = path.resolve(homePath, 'index.js');
if (fs.existsSync(filePath)) {
tpl = fs.readFileSync(filePath, 'utf-8');
this.dirname = path.dirname(filePath);
}
if (ld !== '{%') {
paserFile = paserFile.replace(/\\\{%/g, utils.regEscape(ld));
}
if (rd !== '%}') {
paserFile = paserFile.replace(/%\\\}/g, utils.regEscape(rd));
}
fs.writeFileSync(realParserFilePath, paserFile);
this.ast = require(realParserFilePath).parse(pretreatmentCode(tpl, conf));
return this.compiler;
};
/**
* render tpl with json data
* @param {string} tpl template code/file path
* @param {Object} data json data
* @return {string} html string
*/
Smarty.prototype.render = function (tpl, data) {
var filePath = path.resolve(process.cwd(), tpl);
if (fs.existsSync(filePath)) {
tpl = fs.readFileSync(filePath, 'utf-8');
this.dirname = path.dirname(filePath);
}
return this.compile(tpl).render(data);
};
/**
* user-defined function regiester in smarty
* @param {Object} funcObj function Object
*/
Smarty.prototype.register = function (funcObj) {
for (var p in funcObj) {
if (funcObj.hasOwnProperty(p)) {
this.func[p] = funcObj[p];
}
}
};
/**
* php plugin regiester in smarty
* @param {Object} plugins plugin's Object
*/
Smarty.prototype.addPlugin = function (plugins) {
for (var p in plugins) {
if (plugins.hasOwnProperty(p)) {
this.phpfunc[p] = plugins[p];
}
}
};
/**
* support express
*
* @param {string} path tpl path
* @param {Object} options data
* @param {Function} fn callback
*/
Smarty.__express = function (path, options, fn) {
fn(null, new Smarty().render(path, options));
};
module.exports = Smarty;