Files
HTCloud/HT.Cloud.Web/wwwroot/lib/layui/modules/laytpl.js

163 lines
4.3 KiB
JavaScript
Raw Normal View History

2024-11-14 09:01:55 +08:00
/**
2024-11-14 09:01:37 +08:00
* laytpl 轻量模板引擎
2023-03-10 16:39:21 +08:00
*/
layui.define(function(exports){
"use strict";
2024-11-14 09:01:37 +08:00
// 默认属性
2023-03-10 16:39:21 +08:00
var config = {
2024-11-14 09:01:37 +08:00
open: '{{', // 标签符前缀
close: '}}' // 标签符后缀
2023-03-10 16:39:21 +08:00
};
2024-11-14 09:01:37 +08:00
// 模板工具
2024-11-14 09:01:55 +08:00
var tool = {
2023-03-10 16:39:21 +08:00
escape: function(html){
var exp = /[<"'>]|&(?=#[a-zA-Z0-9]+)/g;
if(html === undefined || html === null) return '';
2024-11-14 09:01:55 +08:00
2023-03-10 16:39:21 +08:00
html += '';
if(!exp.test(html)) return html;
return html.replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&amp;')
.replace(/</g, '&lt;').replace(/>/g, '&gt;')
.replace(/'/g, '&#39;').replace(/"/g, '&quot;');
2024-11-14 09:01:37 +08:00
}
};
// 内部方法
var inner = {
exp: function(str){
return new RegExp(str, 'g');
2023-03-10 16:39:21 +08:00
},
2024-11-14 09:01:37 +08:00
// 错误提示
error: function(e, source){
2023-03-10 16:39:21 +08:00
var error = 'Laytpl Error: ';
2024-11-14 09:01:37 +08:00
typeof console === 'object' && console.error(error + e + '\n'+ (source || ''));
2023-03-10 16:39:21 +08:00
return error + e;
}
};
2024-11-14 09:01:37 +08:00
// constructor
var Class = function(template, options){
var that = this;
that.config = that.config || {};
that.template = template;
// 简单属性合并
var extend = function(obj){
for(var i in obj){
that.config[i] = obj[i];
}
};
extend(config);
extend(options);
2023-03-10 16:39:21 +08:00
};
2024-11-14 09:01:37 +08:00
// 标签正则
Class.prototype.tagExp = function(type, _, __){
var options = this.config;
var types = [
'#([\\s\\S])+?', // js 语句
'([^{#}])*?' // 普通字段
][type || 0];
return inner.exp((_||'') + options.open + types + options.close + (__||''));
};
2023-03-10 16:39:21 +08:00
2024-11-14 09:01:37 +08:00
// 模版解析
Class.prototype.parse = function(template, data){
var that = this;
var options = that.config;
var source = template;
var jss = inner.exp('^'+ options.open +'#', '');
var jsse = inner.exp(options.close +'$', '');
2023-03-10 16:39:21 +08:00
2024-11-14 09:01:37 +08:00
// 模板必须为 string 类型
if(typeof template !== 'string') return template;
2024-11-14 09:01:55 +08:00
2024-11-14 09:01:37 +08:00
// 正则解析
template = template.replace(/\s+|\r|\t|\n/g, ' ')
.replace(inner.exp(options.open +'#'), options.open +'# ')
.replace(inner.exp(options.close +'}'), '} '+ options.close).replace(/\\/g, '\\\\')
2024-11-14 09:01:55 +08:00
2024-11-14 09:01:37 +08:00
// 不匹配指定区域的内容
.replace(inner.exp(options.open + '!(.+?)!' + options.close), function(str){
str = str.replace(inner.exp('^'+ options.open + '!'), '')
.replace(inner.exp('!'+ options.close), '')
.replace(inner.exp(options.open + '|' + options.close), function(tag){
2023-03-10 16:39:21 +08:00
return tag.replace(/(.)/g, '\\$1')
});
return str
})
2024-11-14 09:01:55 +08:00
2024-11-14 09:01:37 +08:00
// 匹配 JS 语法
.replace(/(?="|')/g, '\\').replace(that.tagExp(), function(str){
2023-03-10 16:39:21 +08:00
str = str.replace(jss, '').replace(jsse, '');
return '";' + str.replace(/\\(.)/g, '$1') + ';view+="';
})
2024-11-14 09:01:55 +08:00
2024-11-14 09:01:37 +08:00
// 匹配普通输出语句
.replace(that.tagExp(1), function(str){
2023-03-10 16:39:21 +08:00
var start = '"+laytpl.escape(';
2024-11-14 09:01:37 +08:00
if(str.replace(/\s/g, '') === options.open + options.close){
2023-03-10 16:39:21 +08:00
return '';
}
2024-11-14 09:01:37 +08:00
str = str.replace(inner.exp(options.open + '|' + options.close), '');
2023-03-10 16:39:21 +08:00
if(/^=/.test(str)){
str = str.replace(/^=/, '');
} else if(/^-/.test(str)){
str = str.replace(/^-/, '');
start = '"+(';
}
return start + str.replace(/\\(.)/g, '$1') + ')+"';
});
2024-11-14 09:01:55 +08:00
2024-11-14 09:01:37 +08:00
template = '"use strict";var view = "' + template + '";return view;';
2023-03-10 16:39:21 +08:00
2024-11-14 09:01:37 +08:00
try {
2024-11-14 09:01:55 +08:00
/**
* 请注意: 开发者在使用模板语法时需确保模板中的 JS 语句不来自于页面用户输入
* 即模板中的 JS 语句必须在页面开发者自身的可控范围内否则请避免使用该模板解析
*/
2024-11-14 09:01:37 +08:00
that.cache = template = new Function('d, laytpl', template);
return template(data, tool);
} catch(e) {
2023-03-10 16:39:21 +08:00
delete that.cache;
2024-11-14 09:01:37 +08:00
return inner.error(e, source);
2023-03-10 16:39:21 +08:00
}
};
2024-11-14 09:01:37 +08:00
// 数据渲染
Class.prototype.render = function(data, callback){
data = data || {};
var that = this;
var result = that.cache ? that.cache(data, tool) : that.parse(that.template, data);
2024-11-14 09:01:55 +08:00
2024-11-14 09:01:37 +08:00
// 返回渲染结果
typeof callback === 'function' && callback(result);
return result;
2023-03-10 16:39:21 +08:00
};
2024-11-14 09:01:37 +08:00
// 创建实例
var laytpl = function(template, options){
return new Class(template, options);
2023-03-10 16:39:21 +08:00
};
2024-11-14 09:01:37 +08:00
// 配置全局属性
2023-03-10 16:39:21 +08:00
laytpl.config = function(options){
options = options || {};
for(var i in options){
config[i] = options[i];
}
};
2024-11-14 09:01:37 +08:00
laytpl.v = '2.0.0';
2024-11-14 09:01:55 +08:00
2024-11-14 09:01:37 +08:00
// export
2023-03-10 16:39:21 +08:00
exports('laytpl', laytpl);
2024-11-14 09:01:55 +08:00
});