smarty4js
Version:
A JavaScript Template Engine Most Like Smarty
191 lines (174 loc) • 7.04 kB
JavaScript
/**
* @file module of smarty (extends, include, block)
* @author johnson [zoumiaojiang@gmail.com]
*/
var utils = require('../utils');
var fs = require('fs');
var path = require('path');
module.exports = function (Renderer) {
utils.mixin(Renderer.prototype, {
/**
* render include
* {%include file="./a/b/c.tpl" assign=xxx%}
* @param {Object} node ast node
* @return {string} render result
*/
_getInclude: function (node) {
var me = this;
var attrs = node.attrs;
var filePath;
var Class = me.eClass;
var s = new Class(me.engine.conf);
var includeRet;
var fc = '__ic' + utils.getGUID();
var ret = 'var ' + fc + '={};';
s.dirname = me.engine.dirname || process.cwd();
me.ctxScope.push(fc);
for (var index = 0, l = attrs.length; index < l; index++) {
var attr = attrs[index];
var key = attr.key.value;
if (key === 'file' || !attr.value) {
var vn = attr.value;
var tmpPath = me._getExpr(vn ? vn : attr.key).replace(/\"/g, '');
filePath = path.resolve(s.dirname, tmpPath);
if (fs.existsSync(filePath)) {
s.dirname = path.dirname(filePath);
includeRet = s.compile(fs.readFileSync(filePath, 'utf8')).getJsTpl(1);
}
else {
console.log('No such file `' + filePath + '`');
}
break;
}
}
attrs.forEach(function (attr) {
var key = attr.key.value;
var value = attr.value;
if (key === 'assign') {
if (value.type === 'STR') {
includeRet = '\nfunction __fn__' + value.value + '(){' + includeRet + '\n}';
me.includeAssign[value.value] = true;
}
}
else if (key === 'file' || !value) {}
else {
ret += fc + '["' + key + '"]=' + (attr.value ? me._getExpr(attr.value) : '') + ';';
}
});
me.ctxScope.pop();
return ret + includeRet;
},
/**
* render extends
* @param {Object} node ast node
* @return {string} render result
*/
_getExtends: function (node) {
var me = this;
var filePath;
var Class = me.eClass;
var s = new Class(me.engine.conf);
var extendsRet = '';
s.dirname = me.engine.dirname || process.cwd();
for (var index = 0, l = node.attrs.length; index < l; index++) {
var attr = node.attrs[index];
var key = attr.key.value;
if (key === 'file' || !attr.value) {
var vn = attr.value;
var tmpPath = me._getExpr(vn ? vn : attr.key).replace(/\"/g, '');
filePath = path.resolve(s.dirname, tmpPath);
if (fs.existsSync(filePath)) {
s.dirname = path.dirname(filePath);
extendsRet = s.compile(fs.readFileSync(filePath, 'utf8')).getJsTpl(1);
}
else {
console.log('No such file `' + filePath + '`');
}
break;
}
}
return extendsRet;
},
/**
* render block in master of extends
* @param {Object} node ast node
* @return {string} render result
*/
_getMasterBlock: function (node) { // name="aaa"
var me = this;
var attrs = node.attrs;
var block = node.block;
var scope = me.extScope;
var ret = '';
if (attrs) {
attrs.forEach(function (attr) {
var key = attr.key;
var val = attr.value;
if (key.value === 'name' && val && val.type === 'STR') {
var defaultFunc = '';
var des = '';
if (scope.length > 1) {
for (var i = 0; i < scope.length - 1; i++) {
des = scope[i] + val.value;
ret += 'function ' + des + '(){return 0;}';
}
for (i = 0; i < scope.length - 1; i++) {
des = scope[i] + val.value;
defaultFunc += des + '(__p)||';
}
}
var es = scope[scope.length - 1] + val.value;
ret += 'function ' + es + '(__p){' + defaultFunc + '__p.c();return 1;};'
+ es + '({'
+ 'c: function(){' + me._init(block) + 'return 1;}'
+ '});';
}
});
}
return ret;
},
/**
* render block in child of extends
* @param {Object} node ast node
* @return {string} render result
*/
_getSubBlock: function (node) { // name="aaa" append && prepend
var me = this;
var attrs = node.attrs;
var block = node.block;
var name = '';
var pos = '';
var content = '';
var ret = '';
var scope = me.extScope;
if (attrs) {
for (var i = 0, l = attrs.length; i < l; i++) {
var attr = attrs[i];
var key = attr.key.value;
var val = attr.value;
if (key === 'name' && val && val.type === 'STR') {
name = val.value;
}
if (key === 'append') {
pos = 1;
}
else if (key === 'prepend') {
pos = 2;
}
}
if (scope.length === 1) {
content += me._init(block);
}
else {
for (i = scope.length - 2; i >= 0; i--) {
content += scope[i] + name + '({c:function (){' + me._init(block) + '}});';
}
}
content = pos ? (pos === 1 ? ('__p.c();' + content) : (content + '__p.c();')) : content;
var es = scope[scope.length - 1] + name;
ret += '\nfunction ' + es + '(__p){' + content + 'return 1;}';
}
return ret;
}
});
};