art-template 4.13.3 → 4.13.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +2 -2
- package/README.md +6 -0
- package/index.d.ts +2 -2
- package/lib/compile/adapter/caches.js +19 -0
- package/lib/compile/adapter/extend.js +37 -0
- package/lib/compile/adapter/html-minifier.js +29 -0
- package/lib/compile/adapter/include.js +21 -0
- package/lib/compile/adapter/loader.js +22 -0
- package/lib/compile/adapter/onerror.js +13 -0
- package/lib/compile/adapter/resolve-filename.js +36 -0
- package/lib/compile/adapter/rule.art.js +187 -0
- package/lib/compile/adapter/rule.native.js +34 -0
- package/lib/compile/compiler.js +470 -0
- package/lib/compile/defaults.js +95 -0
- package/lib/compile/error.js +60 -0
- package/lib/compile/es-tokenizer.js +26 -0
- package/lib/compile/index.js +136 -0
- package/lib/compile/runtime.js +99 -0
- package/lib/compile/tpl-tokenizer.js +98 -0
- package/lib/defaults.js +3 -0
- package/lib/extension.js +21 -0
- package/lib/index.js +26 -0
- package/lib/precompile.js +242 -0
- package/lib/render.js +16 -0
- package/lib/runtime.js +3 -0
- package/lib/template-web.js +3 -3
- package/package.json +1 -1
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
The MIT License (MIT)
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2016
|
|
3
|
+
Copyright (c) 2016 糖饼
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -29,3 +29,9 @@ art-template 是一个简约、超快的模板引擎。它采用作用域预声
|
|
|
29
29
|
5. 支持 Express、Koa、Webpack
|
|
30
30
|
6. 支持模板继承与子模板
|
|
31
31
|
7. 浏览器版本仅 6KB 大小
|
|
32
|
+
|
|
33
|
+
-----------------
|
|
34
|
+
|
|
35
|
+
[捐助我](https://cloud.githubusercontent.com/assets/1791748/25561320/09c9d6d0-2d9c-11e7-8689-1109f3f88f41.png)(微信支付)
|
|
36
|
+
|
|
37
|
+
[\[AD\] 前端招聘:在海边写代码](https://juejin.im/post/5a2651d06fb9a0451c3a40ad)
|
package/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ declare type artTemplateDefaults = {
|
|
|
11
11
|
* whether to automatically encode output statements of template. Setting false will close that functionality
|
|
12
12
|
* escape can prevent XSS attacks
|
|
13
13
|
*/
|
|
14
|
-
|
|
14
|
+
excape: boolean;
|
|
15
15
|
/**
|
|
16
16
|
* enable debug mode. If true: {cache:false, minimize:false, compileDebug:true}
|
|
17
17
|
*/
|
|
@@ -106,4 +106,4 @@ declare namespace artTemplate {
|
|
|
106
106
|
function render(source: string, data: any, options?: any): string;
|
|
107
107
|
function compile(source: string, options?: any): (data: any) => string;
|
|
108
108
|
}
|
|
109
|
-
export = artTemplate;
|
|
109
|
+
export = artTemplate;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var caches = {
|
|
4
|
+
__data: Object.create(null),
|
|
5
|
+
|
|
6
|
+
set: function set(key, val) {
|
|
7
|
+
this.__data[key] = val;
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
get: function get(key) {
|
|
11
|
+
return this.__data[key];
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
reset: function reset() {
|
|
15
|
+
this.__data = {};
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
module.exports = caches;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var toString = Object.prototype.toString;
|
|
4
|
+
var toType = function toType(value) {
|
|
5
|
+
// Null: 兼容 IE8
|
|
6
|
+
return value === null ? 'Null' : toString.call(value).slice(8, -1);
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 快速继承默认配置
|
|
11
|
+
* @param {Object} options
|
|
12
|
+
* @param {?Object} defaults
|
|
13
|
+
* @return {Object}
|
|
14
|
+
*/
|
|
15
|
+
var extend = function extend(target, defaults) {
|
|
16
|
+
var object = void 0;
|
|
17
|
+
var type = toType(target);
|
|
18
|
+
|
|
19
|
+
if (type === 'Object') {
|
|
20
|
+
object = Object.create(defaults || {});
|
|
21
|
+
} else if (type === 'Array') {
|
|
22
|
+
object = [].concat(defaults || []);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (object) {
|
|
26
|
+
for (var index in target) {
|
|
27
|
+
if (Object.hasOwnProperty.call(target, index)) {
|
|
28
|
+
object[index] = extend(target[index], object[index]);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return object;
|
|
32
|
+
} else {
|
|
33
|
+
return target;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
module.exports = extend;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
|
|
4
|
+
|
|
5
|
+
var detectNode = typeof window === 'undefined';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* HTML 压缩器
|
|
9
|
+
* @param {string} source
|
|
10
|
+
* @param {Object} options
|
|
11
|
+
* @return {string}
|
|
12
|
+
*/
|
|
13
|
+
var htmlMinifier = function htmlMinifier(source, options) {
|
|
14
|
+
if (detectNode) {
|
|
15
|
+
var _htmlMinifierOptions$;
|
|
16
|
+
|
|
17
|
+
var _htmlMinifier = require('html-minifier').minify;
|
|
18
|
+
var htmlMinifierOptions = options.htmlMinifierOptions;
|
|
19
|
+
var ignoreCustomFragments = options.rules.map(function (rule) {
|
|
20
|
+
return rule.test;
|
|
21
|
+
});
|
|
22
|
+
(_htmlMinifierOptions$ = htmlMinifierOptions.ignoreCustomFragments).push.apply(_htmlMinifierOptions$, _toConsumableArray(ignoreCustomFragments));
|
|
23
|
+
source = _htmlMinifier(source, htmlMinifierOptions);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return source;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
module.exports = htmlMinifier;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 载入子模板
|
|
5
|
+
* @param {string} filename
|
|
6
|
+
* @param {Object} data
|
|
7
|
+
* @param {Object} blocks
|
|
8
|
+
* @param {Object} options
|
|
9
|
+
* @return {string}
|
|
10
|
+
*/
|
|
11
|
+
var include = function include(filename, data, blocks, options) {
|
|
12
|
+
var compile = require('../index');
|
|
13
|
+
options = options.$extend({
|
|
14
|
+
filename: options.resolveFilename(filename, options),
|
|
15
|
+
bail: true,
|
|
16
|
+
source: null
|
|
17
|
+
});
|
|
18
|
+
return compile(options)(data, blocks);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
module.exports = include;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var detectNode = typeof window === 'undefined';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 读取模板内容(同步方法)
|
|
7
|
+
* @param {string} filename 模板名
|
|
8
|
+
* @param {?Object} options
|
|
9
|
+
* @return {string}
|
|
10
|
+
*/
|
|
11
|
+
var loader = function loader(filename /*, options*/) {
|
|
12
|
+
/* istanbul ignore else */
|
|
13
|
+
if (detectNode) {
|
|
14
|
+
var fs = require('fs');
|
|
15
|
+
return fs.readFileSync(filename, 'utf8');
|
|
16
|
+
} else {
|
|
17
|
+
var elem = document.getElementById(filename);
|
|
18
|
+
return elem.value || elem.innerHTML;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
module.exports = loader;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var detectNode = typeof window === 'undefined';
|
|
4
|
+
var LOCAL_MODULE = /^\.+\//;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 获取模板的绝对路径
|
|
8
|
+
* @param {string} filename
|
|
9
|
+
* @param {Object} options
|
|
10
|
+
* @return {string}
|
|
11
|
+
*/
|
|
12
|
+
var resolveFilename = function resolveFilename(filename, options) {
|
|
13
|
+
/* istanbul ignore else */
|
|
14
|
+
if (detectNode) {
|
|
15
|
+
var path = require('path');
|
|
16
|
+
var root = options.root;
|
|
17
|
+
var extname = options.extname;
|
|
18
|
+
|
|
19
|
+
if (LOCAL_MODULE.test(filename)) {
|
|
20
|
+
var from = options.filename;
|
|
21
|
+
var self = !from || filename === from;
|
|
22
|
+
var base = self ? root : path.dirname(from);
|
|
23
|
+
filename = path.resolve(base, filename);
|
|
24
|
+
} else {
|
|
25
|
+
filename = path.resolve(root, filename);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!path.extname(filename)) {
|
|
29
|
+
filename = filename + extname;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return filename;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
module.exports = resolveFilename;
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 简洁模板语法规则
|
|
5
|
+
*/
|
|
6
|
+
var artRule = {
|
|
7
|
+
test: /{{([@#]?)[ \t]*(\/?)([\w\W]*?)[ \t]*}}/,
|
|
8
|
+
use: function use(match, raw, close, code) {
|
|
9
|
+
var compiler = this;
|
|
10
|
+
var options = compiler.options;
|
|
11
|
+
var esTokens = compiler.getEsTokens(code);
|
|
12
|
+
var values = esTokens.map(function (token) {
|
|
13
|
+
return token.value;
|
|
14
|
+
});
|
|
15
|
+
var result = {};
|
|
16
|
+
|
|
17
|
+
var group = void 0;
|
|
18
|
+
var output = raw ? 'raw' : false;
|
|
19
|
+
var key = close + values.shift();
|
|
20
|
+
|
|
21
|
+
// 旧版语法升级提示
|
|
22
|
+
var warn = function warn(oldSyntax, newSyntax) {
|
|
23
|
+
console.warn((options.filename || 'anonymous') + ':' + (match.line + 1) + ':' + (match.start + 1) + '\n' + ('Template upgrade: {{' + oldSyntax + '}} -> {{' + newSyntax + '}}'));
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// v3 compat: #value
|
|
27
|
+
if (raw === '#') {
|
|
28
|
+
warn('#value', '@value');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
switch (key) {
|
|
32
|
+
case 'set':
|
|
33
|
+
code = 'var ' + values.join('').trim();
|
|
34
|
+
break;
|
|
35
|
+
|
|
36
|
+
case 'if':
|
|
37
|
+
code = 'if(' + values.join('').trim() + '){';
|
|
38
|
+
|
|
39
|
+
break;
|
|
40
|
+
|
|
41
|
+
case 'else':
|
|
42
|
+
var indexIf = values.indexOf('if');
|
|
43
|
+
|
|
44
|
+
if (~indexIf) {
|
|
45
|
+
values.splice(0, indexIf + 1);
|
|
46
|
+
code = '}else if(' + values.join('').trim() + '){';
|
|
47
|
+
} else {
|
|
48
|
+
code = '}else{';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
break;
|
|
52
|
+
|
|
53
|
+
case '/if':
|
|
54
|
+
code = '}';
|
|
55
|
+
break;
|
|
56
|
+
|
|
57
|
+
case 'each':
|
|
58
|
+
group = artRule._split(esTokens);
|
|
59
|
+
group.shift();
|
|
60
|
+
|
|
61
|
+
if (group[1] === 'as') {
|
|
62
|
+
// ... v3 compat ...
|
|
63
|
+
warn('each object as value index', 'each object value index');
|
|
64
|
+
group.splice(1, 1);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
var object = group[0] || '$data';
|
|
68
|
+
var value = group[1] || '$value';
|
|
69
|
+
var index = group[2] || '$index';
|
|
70
|
+
|
|
71
|
+
code = '$each(' + object + ',function(' + value + ',' + index + '){';
|
|
72
|
+
|
|
73
|
+
break;
|
|
74
|
+
|
|
75
|
+
case '/each':
|
|
76
|
+
code = '})';
|
|
77
|
+
break;
|
|
78
|
+
|
|
79
|
+
case 'block':
|
|
80
|
+
group = artRule._split(esTokens);
|
|
81
|
+
group.shift();
|
|
82
|
+
code = 'block(' + group.join(',').trim() + ',function(){';
|
|
83
|
+
break;
|
|
84
|
+
|
|
85
|
+
case '/block':
|
|
86
|
+
code = '})';
|
|
87
|
+
break;
|
|
88
|
+
|
|
89
|
+
case 'echo':
|
|
90
|
+
key = 'print';
|
|
91
|
+
warn('echo value', 'value');
|
|
92
|
+
case 'print':
|
|
93
|
+
case 'include':
|
|
94
|
+
case 'extend':
|
|
95
|
+
if (values.join('').trim().indexOf('(') !== 0) {
|
|
96
|
+
// 执行函数省略 `()` 与 `,`
|
|
97
|
+
group = artRule._split(esTokens);
|
|
98
|
+
group.shift();
|
|
99
|
+
code = key + '(' + group.join(',') + ')';
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
default:
|
|
104
|
+
if (~values.indexOf('|')) {
|
|
105
|
+
var v3split = ':'; // ... v3 compat ...
|
|
106
|
+
|
|
107
|
+
// 将过滤器解析成二维数组
|
|
108
|
+
var _group = esTokens.reduce(function (group, token) {
|
|
109
|
+
var value = token.value,
|
|
110
|
+
type = token.type;
|
|
111
|
+
|
|
112
|
+
if (value === '|') {
|
|
113
|
+
group.push([]);
|
|
114
|
+
} else if (type !== 'whitespace' && type !== 'comment') {
|
|
115
|
+
if (!group.length) {
|
|
116
|
+
group.push([]);
|
|
117
|
+
}
|
|
118
|
+
if (value === v3split && group[group.length - 1].length === 1) {
|
|
119
|
+
warn('value | filter: argv', 'value | filter argv');
|
|
120
|
+
} else {
|
|
121
|
+
group[group.length - 1].push(token);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return group;
|
|
125
|
+
}, []).map(function (g) {
|
|
126
|
+
return artRule._split(g);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// 将过滤器管道化
|
|
130
|
+
code = _group.reduce(function (accumulator, filter) {
|
|
131
|
+
var name = filter.shift();
|
|
132
|
+
filter.unshift(accumulator);
|
|
133
|
+
|
|
134
|
+
return '$imports.' + name + '(' + filter.join(',') + ')';
|
|
135
|
+
}, _group.shift().join(' ').trim());
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
output = output || 'escape';
|
|
139
|
+
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
result.code = code;
|
|
144
|
+
result.output = output;
|
|
145
|
+
|
|
146
|
+
return result;
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
// 将多个 javascript 表达式拆分成组
|
|
150
|
+
// 支持基本运算、三元表达式、取值、运行函数,不支持 `typeof value` 操作
|
|
151
|
+
// 只支持 string、number、boolean、null、undefined 这几种类型声明,不支持 function、object、array
|
|
152
|
+
_split: function _split(esTokens) {
|
|
153
|
+
esTokens = esTokens.filter(function (_ref) {
|
|
154
|
+
var type = _ref.type;
|
|
155
|
+
|
|
156
|
+
return type !== 'whitespace' && type !== 'comment';
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
var current = 0;
|
|
160
|
+
var lastToken = esTokens.shift();
|
|
161
|
+
var punctuator = 'punctuator';
|
|
162
|
+
var close = /\]|\)/;
|
|
163
|
+
var group = [[lastToken]];
|
|
164
|
+
|
|
165
|
+
while (current < esTokens.length) {
|
|
166
|
+
var esToken = esTokens[current];
|
|
167
|
+
|
|
168
|
+
if (esToken.type === punctuator || lastToken.type === punctuator && !close.test(lastToken.value)) {
|
|
169
|
+
group[group.length - 1].push(esToken);
|
|
170
|
+
} else {
|
|
171
|
+
group.push([esToken]);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
lastToken = esToken;
|
|
175
|
+
|
|
176
|
+
current++;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return group.map(function (g) {
|
|
180
|
+
return g.map(function (g) {
|
|
181
|
+
return g.value;
|
|
182
|
+
}).join('');
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
module.exports = artRule;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 原生模板语法规则
|
|
5
|
+
*/
|
|
6
|
+
var nativeRule = {
|
|
7
|
+
test: /<%(#?)((?:==|=#|[=-])?)[ \t]*([\w\W]*?)[ \t]*(-?)%>/,
|
|
8
|
+
use: function use(match, comment, output, code /*, trimMode*/) {
|
|
9
|
+
output = {
|
|
10
|
+
'-': 'raw',
|
|
11
|
+
'=': 'escape',
|
|
12
|
+
'': false,
|
|
13
|
+
// v3 compat: raw output
|
|
14
|
+
'==': 'raw',
|
|
15
|
+
'=#': 'raw'
|
|
16
|
+
}[output];
|
|
17
|
+
|
|
18
|
+
// ejs compat: comment tag
|
|
19
|
+
if (comment) {
|
|
20
|
+
code = '/*' + code.replace(/\*\//g, '* /') + '*/';
|
|
21
|
+
output = false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// ejs compat: trims following newline
|
|
25
|
+
// if (trimMode) {}
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
code: code,
|
|
29
|
+
output: output
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
module.exports = nativeRule;
|