/*! * artTemplate - Template Engine * https://github.com/aui/artTemplate * Released under the MIT, BSD, and GPL Licenses */ /** * 妯℃澘寮曟搸璺敱鍑芥暟 * 鑻ョ浜屼釜鍙傛暟绫诲瀷涓 Object 鍒欐墽琛 render 鏂规硶, 鍚﹀垯 compile 鏂规硶 * @name template * @param {String} 妯℃澘ID (鍙€? * @param {Object, String} 鏁版嵁鎴栬€呮ā鏉垮瓧绗︿覆 * @return {String, Function} 娓叉煋濂界殑HTML瀛楃涓叉垨鑰呮覆鏌撴柟娉 */ var template = function (id, content) { return template[ typeof content === 'object' ? 'render' : 'compile' ].apply(template, arguments); }; (function (exports, global) { 'use strict'; exports.version = '2.0.1'; exports.openTag = '{% '; // 璁剧疆閫昏緫璇硶寮€濮嬫爣绛 exports.closeTag = ' %}'; // 璁剧疆閫昏緫璇硶缁撴潫鏍囩 exports.isEscape = true; // HTML瀛楃缂栫爜杈撳嚭寮€鍏 exports.isCompress = false; // 鍓旈櫎娓叉煋鍚嶩TML澶氫綑鐨勭┖鐧藉紑鍏 exports.parser = null; // 鑷畾涔夎娉曟彃浠舵帴鍙 /** * 娓叉煋妯℃澘 * @name template.render * @param {String} 妯℃澘ID * @param {Object} 鏁版嵁 * @return {String} 娓叉煋濂界殑HTML瀛楃涓 */ exports.render = function (id, data) { var cache = _getCache(id); if (cache === undefined) { return _debug({ id: id, name: 'Render Error', message: 'No Template' }); } return cache(data); }; /** * 缂栬瘧妯℃澘 * 2012-6-6: * define 鏂规硶鍚嶆敼涓 compile, * 涓 Node Express 淇濇寔涓€鑷? * 鎰熻阿 TooBug 鎻愪緵甯姪! * @name template.compile * @param {String} 妯℃澘ID (鍙€? * @param {String} 妯℃澘瀛楃涓 * @return {Function} 娓叉煋鏂规硶 */ exports.compile = function (id, source) { var params = arguments; var isDebug = params[2]; var anonymous = 'anonymous'; if (typeof source !== 'string') { isDebug = params[1]; source = params[0]; id = anonymous; } try { var Render = _compile(source, isDebug); } catch (e) { e.id = id || source; e.name = 'Syntax Error'; return _debug(e); } function render (data) { try { return new Render(data) + ''; } catch (e) { if (!isDebug) { return exports.compile(id, source, true)(data); } e.id = id || source; e.name = 'Render Error'; e.source = source; return _debug(e); } } render.prototype = Render.prototype; render.toString = function () { return Render.toString(); }; if (id !== anonymous) { _cache[id] = render; } return render; }; /** * 娣诲姞妯℃澘杈呭姪鏂规硶 * @name template.helper * @param {String} 鍚嶇О * @param {Function} 鏂规硶 */ exports.helper = function (name, helper) { exports.prototype[name] = helper; }; /** * 妯℃澘閿欒浜嬩欢 * @name template.onerror * @event */ exports.onerror = function (e) { var content = '[template]:\n' + e.id + '\n\n[name]:\n' + e.name; if (e.message) { content += '\n\n[message]:\n' + e.message; } if (e.line) { content += '\n\n[line]:\n' + e.line; content += '\n\n[source]:\n' + e.source.split(/\n/)[e.line - 1].replace(/^[\s\t]+/, ''); } if (e.temp) { content += '\n\n[temp]:\n' + e.temp; } if (global.console) { console.error(content); } }; // 缂栬瘧濂界殑鍑芥暟缂撳瓨 var _cache = {}; // 鑾峰彇妯℃澘缂撳瓨 var _getCache = function (id) { var cache = _cache[id]; if (cache === undefined && 'document' in global) { var elem = document.getElementById(id); if (elem) { var source = elem.value || elem.innerHTML; return exports.compile(id, source.replace(/^\s*|\s*$/g, '')); } } else if (_cache.hasOwnProperty(id)) { return cache; } }; // 妯℃澘璋冭瘯鍣 var _debug = function (e) { exports.onerror(e); function error () { return error + ''; } error.toString = function () { return '{Template Error}'; }; return error; }; // 妯℃澘缂栬瘧鍣 var _compile = (function () { // 杈呭姪鏂规硶闆嗗悎 exports.prototype = { $render: exports.render, $escape: function (content) { return typeof content === 'string' ? content.replace(/&(?![\w#]+;)|[<>"']/g, function (s) { return { "<": "<", ">": ">", '"': """, "'": "'", "&": "&" }[s]; }) : content; }, $string: function (value) { if (typeof value === 'string' || typeof value === 'number') { return value; } else if (typeof value === 'function') { return value(); } else { return ''; } } }; var arrayforEach = Array.prototype.forEach || function (block, thisObject) { var len = this.length >>> 0; for (var i = 0; i < len; i++) { if (i in this) { block.call(thisObject, this[i], i, this); } } }; // 鏁扮粍杩唬 var forEach = function (array, callback) { arrayforEach.call(array, callback); }; // 闈欐€佸垎鏋愭ā鏉垮彉閲 var KEYWORDS = // 鍏抽敭瀛 'break,case,catch,continue,debugger,default,delete,do,else,false' + ',finally,for,function,if,in,instanceof,new,null,return,switch,this' + ',throw,true,try,typeof,var,void,while,with' // 淇濈暀瀛 + ',abstract,boolean,byte,char,class,const,double,enum,export,extends' + ',final,float,goto,implements,import,int,interface,long,native' + ',package,private,protected,public,short,static,super,synchronized' + ',throws,transient,volatile' // ECMA 5 - use strict + ',arguments,let,yield' + ',undefined'; var REMOVE_RE = /\/\*(?:.|\n)*?\*\/|\/\/[^\n]*\n|\/\/[^\n]*$|'[^']*'|"[^"]*"|[\s\t\n]*\.[\s\t\n]*[$\w\.]+/g; var SPLIT_RE = /[^\w$]+/g; var KEYWORDS_RE = new RegExp(["\\b" + KEYWORDS.replace(/,/g, '\\b|\\b') + "\\b"].join('|'), 'g'); var NUMBER_RE = /\b\d[^,]*/g; var BOUNDARY_RE = /^,+|,+$/g; var getVariable = function (code) { code = code .replace(REMOVE_RE, '') .replace(SPLIT_RE, ',') .replace(KEYWORDS_RE, '') .replace(NUMBER_RE, '') .replace(BOUNDARY_RE, ''); code = code ? code.split(/,+/) : []; return code; }; return function (source, isDebug) { var openTag = exports.openTag; var closeTag = exports.closeTag; var parser = exports.parser; var code = source; var tempCode = ''; var line = 1; var uniq = {$data:true,$helpers:true,$out:true,$line:true}; var helpers = exports.prototype; var prototype = {}; var variables = "var $helpers=this," + (isDebug ? "$line=0," : ""); var isNewEngine = ''.trim;// '__proto__' in {} var replaces = isNewEngine ? ["$out='';", "$out+=", ";", "$out"] : ["$out=[];", "$out.push(", ");", "$out.join('')"]; var concat = isNewEngine ? "if(content!==undefined){$out+=content;return content}" : "$out.push(content);"; var print = "function(content){" + concat + "}"; var include = "function(id,data){" + "if(data===undefined){data=$data}" + "var content=$helpers.$render(id,data);" + concat + "}"; // html涓庨€昏緫璇硶鍒嗙 forEach(code.split(openTag), function (code, i) { code = code.split(closeTag); var $0 = code[0]; var $1 = code[1]; // code: [html] if (code.length === 1) { tempCode += html($0); // code: [logic, html] } else { tempCode += logic($0); if ($1) { tempCode += html($1); } } }); code = tempCode; // 璋冭瘯璇彞 if (isDebug) { code = 'try{' + code + '}catch(e){' + 'e.line=$line;' + 'throw e' + '}'; } code = "'use strict';" + variables + replaces[0] + code + 'return new String(' + replaces[3] + ')'; try { var Render = new Function('$data', code); Render.prototype = prototype; return Render; } catch (e) { e.temp = 'function anonymous($data) {' + code + '}'; throw e; } // 澶勭悊 HTML 璇彞 function html (code) { // 璁板綍琛屽彿 line += code.split(/\n/).length - 1; if (exports.isCompress) { code = code.replace(/[\n\r\t\s]+/g, ' '); } code = code // 鍗曞紩鍙蜂笌鍙嶆枩鏉犺浆涔?鍥犱负缂栬瘧鍚庣殑鍑芥暟榛樿浣跨敤鍗曞紩鍙凤紝鍥犳鍙屽紩鍙锋棤闇€杞箟) .replace(/('|\\)/g, '\\$1') // 鎹㈣绗﹁浆涔?windows + linux) .replace(/\r/g, '\\r') .replace(/\n/g, '\\n'); code = replaces[1] + "'" + code + "'" + replaces[2]; return code + '\n'; } // 澶勭悊閫昏緫璇彞 function logic (code) { var thisLine = line; if (parser) { // 璇硶杞崲鎻掍欢閽╁瓙 code = parser(code); } else if (isDebug) { // 璁板綍琛屽彿 code = code.replace(/\n/g, function () { line ++; return '$line=' + line + ';'; }); } // 杈撳嚭璇彞. 杞箟: <%=value%> 涓嶈浆涔堹<%==value%> if (code.indexOf('=') === 0) { var isEscape = code.indexOf('==') !== 0; code = code.replace(/^=*|[\s;]*$/g, ''); if (isEscape && exports.isEscape) { // 杞箟澶勭悊锛屼絾鎺掗櫎杈呭姪鏂规硶 var name = code.replace(/\s*\([^\)]+\)/, ''); if ( !helpers.hasOwnProperty(name) && !/^(include|print)$/.test(name) ) { code = '$escape($string(' + code + '))'; } } else { code = '$string(' + code + ')'; } code = replaces[1] + code + replaces[2]; } if (isDebug) { code = '$line=' + thisLine + ';' + code; } getKey(code); return code + '\n'; } // 鎻愬彇妯℃澘涓殑鍙橀噺鍚 function getKey (code) { code = getVariable(code); // 鍒嗚瘝 forEach(code, function (name) { // 闄ら噸 if (!uniq.hasOwnProperty(name)) { setValue(name); uniq[name] = true; } }); } // 澹版槑妯℃澘鍙橀噺 // 璧嬪€间紭鍏堢骇: // 鍐呯疆鐗规潈鏂规硶(include, print) > 绉佹湁妯℃澘杈呭姪鏂规硶 > 鏁版嵁 > 鍏敤妯℃澘杈呭姪鏂规硶 function setValue (name) { var value; if (name === 'print') { value = print; } else if (name === 'include') { prototype['$render'] = helpers['$render']; value = include; } else { value = '$data.' + name; if (helpers.hasOwnProperty(name)) { prototype[name] = helpers[name]; if (name.indexOf('$') === 0) { value = '$helpers.' + name; } else { value = value + '===undefined?$helpers.' + name + ':' + value; } } } variables += name + '=' + value + ','; } }; })(); })(template, this); // RequireJS || SeaJS if (typeof define === 'function') { define(function(require, exports, module) { module.exports = template; }); // NodeJS } else if (typeof exports !== 'undefined') { module.exports = template; }