更新前端文件
This commit is contained in:
366
public/static/libs/art-template/src/compile.js
Normal file
366
public/static/libs/art-template/src/compile.js
Normal file
@@ -0,0 +1,366 @@
|
||||
/**
|
||||
* 编译模板
|
||||
* 2012-6-6 @TooBug: define 方法名改为 compile,与 Node Express 保持一致
|
||||
* @name template.compile
|
||||
* @param {String} 模板字符串
|
||||
* @param {Object} 编译选项
|
||||
*
|
||||
* - openTag {String}
|
||||
* - closeTag {String}
|
||||
* - filename {String}
|
||||
* - escape {Boolean}
|
||||
* - compress {Boolean}
|
||||
* - debug {Boolean}
|
||||
* - cache {Boolean}
|
||||
* - parser {Function}
|
||||
*
|
||||
* @return {Function} 渲染方法
|
||||
*/
|
||||
var compile = template.compile = function (source, options) {
|
||||
|
||||
// 合并默认配置
|
||||
options = options || {};
|
||||
for (var name in defaults) {
|
||||
if (options[name] === undefined) {
|
||||
options[name] = defaults[name];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var filename = options.filename;
|
||||
|
||||
|
||||
try {
|
||||
|
||||
var Render = compiler(source, options);
|
||||
|
||||
} catch (e) {
|
||||
|
||||
e.filename = filename || 'anonymous';
|
||||
e.name = 'Syntax Error';
|
||||
|
||||
return showDebugInfo(e);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 对编译结果进行一次包装
|
||||
|
||||
function render (data) {
|
||||
|
||||
try {
|
||||
|
||||
return new Render(data, filename) + '';
|
||||
|
||||
} catch (e) {
|
||||
|
||||
// 运行时出错后自动开启调试模式重新编译
|
||||
if (!options.debug) {
|
||||
options.debug = true;
|
||||
return compile(source, options)(data);
|
||||
}
|
||||
|
||||
return showDebugInfo(e)();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
render.prototype = Render.prototype;
|
||||
render.toString = function () {
|
||||
return Render.toString();
|
||||
};
|
||||
|
||||
|
||||
if (filename && options.cache) {
|
||||
cacheStore[filename] = render;
|
||||
}
|
||||
|
||||
|
||||
return render;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// 数组迭代
|
||||
var forEach = utils.$each;
|
||||
|
||||
|
||||
// 静态分析模板变量
|
||||
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 = /\/\*[\w\W]*?\*\/|\/\/[^\n]*\n|\/\/[^\n]*$|"(?:[^"\\]|\\[\w\W])*"|'(?:[^'\\]|\\[\w\W])*'|\s*\.\s*[$\w\.]+/g;
|
||||
var SPLIT_RE = /[^\w$]+/g;
|
||||
var KEYWORDS_RE = new RegExp(["\\b" + KEYWORDS.replace(/,/g, '\\b|\\b') + "\\b"].join('|'), 'g');
|
||||
var NUMBER_RE = /^\d[^,]*|,\d[^,]*/g;
|
||||
var BOUNDARY_RE = /^,+|,+$/g;
|
||||
var SPLIT2_RE = /^$|,+/;
|
||||
|
||||
|
||||
// 获取变量
|
||||
function getVariable (code) {
|
||||
return code
|
||||
.replace(REMOVE_RE, '')
|
||||
.replace(SPLIT_RE, ',')
|
||||
.replace(KEYWORDS_RE, '')
|
||||
.replace(NUMBER_RE, '')
|
||||
.replace(BOUNDARY_RE, '')
|
||||
.split(SPLIT2_RE);
|
||||
};
|
||||
|
||||
|
||||
// 字符串转义
|
||||
function stringify (code) {
|
||||
return "'" + code
|
||||
// 单引号与反斜杠转义
|
||||
.replace(/('|\\)/g, '\\$1')
|
||||
// 换行符转义(windows + linux)
|
||||
.replace(/\r/g, '\\r')
|
||||
.replace(/\n/g, '\\n') + "'";
|
||||
}
|
||||
|
||||
|
||||
function compiler (source, options) {
|
||||
|
||||
var debug = options.debug;
|
||||
var openTag = options.openTag;
|
||||
var closeTag = options.closeTag;
|
||||
var parser = options.parser;
|
||||
var compress = options.compress;
|
||||
var escape = options.escape;
|
||||
|
||||
|
||||
|
||||
var line = 1;
|
||||
var uniq = {$data:1,$filename:1,$utils:1,$helpers:1,$out:1,$line:1};
|
||||
|
||||
|
||||
|
||||
var isNewEngine = ''.trim;// '__proto__' in {}
|
||||
var replaces = isNewEngine
|
||||
? ["$out='';", "$out+=", ";", "$out"]
|
||||
: ["$out=[];", "$out.push(", ");", "$out.join('')"];
|
||||
|
||||
var concat = isNewEngine
|
||||
? "$out+=text;return $out;"
|
||||
: "$out.push(text);";
|
||||
|
||||
var print = "function(){"
|
||||
+ "var text=''.concat.apply('',arguments);"
|
||||
+ concat
|
||||
+ "}";
|
||||
|
||||
var include = "function(filename,data){"
|
||||
+ "data=data||$data;"
|
||||
+ "var text=$utils.$include(filename,data,$filename);"
|
||||
+ concat
|
||||
+ "}";
|
||||
|
||||
var headerCode = "'use strict';"
|
||||
+ "var $utils=this,$helpers=$utils.$helpers,"
|
||||
+ (debug ? "$line=0," : "");
|
||||
|
||||
var mainCode = replaces[0];
|
||||
|
||||
var footerCode = "return new String(" + replaces[3] + ");"
|
||||
|
||||
// html与逻辑语法分离
|
||||
forEach(source.split(openTag), function (code) {
|
||||
code = code.split(closeTag);
|
||||
|
||||
var $0 = code[0];
|
||||
var $1 = code[1];
|
||||
|
||||
// code: [html]
|
||||
if (code.length === 1) {
|
||||
|
||||
mainCode += html($0);
|
||||
|
||||
// code: [logic, html]
|
||||
} else {
|
||||
|
||||
mainCode += logic($0);
|
||||
|
||||
if ($1) {
|
||||
mainCode += html($1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
var code = headerCode + mainCode + footerCode;
|
||||
|
||||
// 调试语句
|
||||
if (debug) {
|
||||
code = "try{" + code + "}catch(e){"
|
||||
+ "throw {"
|
||||
+ "filename:$filename,"
|
||||
+ "name:'Render Error',"
|
||||
+ "message:e.message,"
|
||||
+ "line:$line,"
|
||||
+ "source:" + stringify(source)
|
||||
+ ".split(/\\n/)[$line-1].replace(/^\\s+/,'')"
|
||||
+ "};"
|
||||
+ "}";
|
||||
}
|
||||
|
||||
|
||||
|
||||
try {
|
||||
|
||||
|
||||
var Render = new Function("$data", "$filename", code);
|
||||
Render.prototype = utils;
|
||||
|
||||
return Render;
|
||||
|
||||
} catch (e) {
|
||||
e.temp = "function anonymous($data,$filename) {" + code + "}";
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 处理 HTML 语句
|
||||
function html (code) {
|
||||
|
||||
// 记录行号
|
||||
line += code.split(/\n/).length - 1;
|
||||
|
||||
// 压缩多余空白与注释
|
||||
if (compress) {
|
||||
code = code
|
||||
.replace(/\s+/g, ' ')
|
||||
.replace(/<!--[\w\W]*?-->/g, '');
|
||||
}
|
||||
|
||||
if (code) {
|
||||
code = replaces[1] + stringify(code) + replaces[2] + "\n";
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
// 处理逻辑语句
|
||||
function logic (code) {
|
||||
|
||||
var thisLine = line;
|
||||
|
||||
if (parser) {
|
||||
|
||||
// 语法转换插件钩子
|
||||
code = parser(code, options);
|
||||
|
||||
} else if (debug) {
|
||||
|
||||
// 记录行号
|
||||
code = code.replace(/\n/g, function () {
|
||||
line ++;
|
||||
return "$line=" + line + ";";
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 输出语句. 编码: <%=value%> 不编码:<%=#value%>
|
||||
// <%=#value%> 等同 v2.0.3 之前的 <%==value%>
|
||||
if (code.indexOf('=') === 0) {
|
||||
|
||||
var escapeSyntax = escape && !/^=[=#]/.test(code);
|
||||
|
||||
code = code.replace(/^=[=#]?|[\s;]*$/g, '');
|
||||
|
||||
// 对内容编码
|
||||
if (escapeSyntax) {
|
||||
|
||||
var name = code.replace(/\s*\([^\)]+\)/, '');
|
||||
|
||||
// 排除 utils.* | include | print
|
||||
|
||||
if (!utils[name] && !/^(include|print)$/.test(name)) {
|
||||
code = "$escape(" + code + ")";
|
||||
}
|
||||
|
||||
// 不编码
|
||||
} else {
|
||||
code = "$string(" + code + ")";
|
||||
}
|
||||
|
||||
|
||||
code = replaces[1] + code + replaces[2];
|
||||
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
code = "$line=" + thisLine + ";" + code;
|
||||
}
|
||||
|
||||
// 提取模板中的变量名
|
||||
forEach(getVariable(code), function (name) {
|
||||
|
||||
// name 值可能为空,在安卓低版本浏览器下
|
||||
if (!name || uniq[name]) {
|
||||
return;
|
||||
}
|
||||
|
||||
var value;
|
||||
|
||||
// 声明模板变量
|
||||
// 赋值优先级:
|
||||
// [include, print] > utils > helpers > data
|
||||
if (name === 'print') {
|
||||
|
||||
value = print;
|
||||
|
||||
} else if (name === 'include') {
|
||||
|
||||
value = include;
|
||||
|
||||
} else if (utils[name]) {
|
||||
|
||||
value = "$utils." + name;
|
||||
|
||||
} else if (helpers[name]) {
|
||||
|
||||
value = "$helpers." + name;
|
||||
|
||||
} else {
|
||||
|
||||
value = "$data." + name;
|
||||
}
|
||||
|
||||
headerCode += name + "=" + value + ",";
|
||||
uniq[name] = true;
|
||||
|
||||
|
||||
});
|
||||
|
||||
return code + "\n";
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user