@kosatyi/ejs 0.0.68 → 0.0.70
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/dist/cjs/browser.js +845 -0
- package/dist/cjs/index.js +83 -79
- package/dist/esm/browser.js +945 -0
- package/dist/esm/index.js +131 -116
- package/dist/umd/browser.js +851 -0
- package/dist/umd/browser.min.js +1 -0
- package/dist/umd/index.js +84 -80
- package/dist/umd/index.min.js +1 -1
- package/package.json +7 -3
- package/dist/templates.js +0 -1
|
@@ -0,0 +1,945 @@
|
|
|
1
|
+
const typeProp = function () {
|
|
2
|
+
const args = [].slice.call(arguments);
|
|
3
|
+
const callback = args.shift();
|
|
4
|
+
return args.filter(callback).pop()
|
|
5
|
+
};
|
|
6
|
+
const isFunction = (v) => typeof v === 'function';
|
|
7
|
+
const isString = (v) => typeof v === 'string';
|
|
8
|
+
const isBoolean = (v) => typeof v === 'boolean';
|
|
9
|
+
const isUndefined = (v) => typeof v === 'undefined';
|
|
10
|
+
|
|
11
|
+
const isNodeEnv =
|
|
12
|
+
Object.prototype.toString.call(
|
|
13
|
+
typeof process !== 'undefined' ? process : 0
|
|
14
|
+
) === '[object process]';
|
|
15
|
+
|
|
16
|
+
const isNode = () => isNodeEnv;
|
|
17
|
+
|
|
18
|
+
const symbolEntities = {
|
|
19
|
+
"'": "'",
|
|
20
|
+
'\\': '\\',
|
|
21
|
+
'\r': 'r',
|
|
22
|
+
'\n': 'n',
|
|
23
|
+
'\t': 't',
|
|
24
|
+
'\u2028': 'u2028',
|
|
25
|
+
'\u2029': 'u2029',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const htmlEntities = {
|
|
29
|
+
'&': '&',
|
|
30
|
+
'<': '<',
|
|
31
|
+
'>': '>',
|
|
32
|
+
'"': '"',
|
|
33
|
+
"'": ''',
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const regexKeys = (obj) =>
|
|
37
|
+
new RegExp(['[', Object.keys(obj).join(''), ']'].join(''), 'g');
|
|
38
|
+
|
|
39
|
+
const htmlEntitiesMatch = regexKeys(htmlEntities);
|
|
40
|
+
|
|
41
|
+
const symbolEntitiesMatch = regexKeys(symbolEntities);
|
|
42
|
+
|
|
43
|
+
const entities = (string = '') => {
|
|
44
|
+
return ('' + string).replace(
|
|
45
|
+
htmlEntitiesMatch,
|
|
46
|
+
(match) => htmlEntities[match]
|
|
47
|
+
)
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const symbols = (string) => {
|
|
51
|
+
return ('' + string).replace(
|
|
52
|
+
symbolEntitiesMatch,
|
|
53
|
+
(match) => '\\' + symbolEntities[match]
|
|
54
|
+
)
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const safeValue = (value, escape) => {
|
|
58
|
+
const check = value;
|
|
59
|
+
return check == null ? '' : escape === true ? entities(check) : check
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const instanceOf = (object, instance) => {
|
|
63
|
+
return Boolean(object instanceof instance)
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const getPath = (context, name, strict) => {
|
|
67
|
+
let data = context;
|
|
68
|
+
let chunks = String(name).split('.');
|
|
69
|
+
let prop = chunks.pop();
|
|
70
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
71
|
+
const part = chunks[i];
|
|
72
|
+
if (isFunction(data['toJSON'])) {
|
|
73
|
+
data = data.toJSON();
|
|
74
|
+
}
|
|
75
|
+
if (strict && data.hasOwnProperty(part) === false) {
|
|
76
|
+
data = {};
|
|
77
|
+
break
|
|
78
|
+
}
|
|
79
|
+
data = data[part] = data[part] || {};
|
|
80
|
+
}
|
|
81
|
+
if (isFunction(data['toJSON'])) {
|
|
82
|
+
data = data.toJSON();
|
|
83
|
+
}
|
|
84
|
+
return [data, prop]
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const ext = (path, defaults) => {
|
|
88
|
+
const ext = path.split('.').pop();
|
|
89
|
+
if (ext !== defaults) {
|
|
90
|
+
path = [path, defaults].join('.');
|
|
91
|
+
}
|
|
92
|
+
return path
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @type {<T extends {}, U, V, W,Y>(T,U,V,W,Y)=> T & U & V & W & Y}
|
|
97
|
+
*/
|
|
98
|
+
const extend = (target, ...args) => {
|
|
99
|
+
return args
|
|
100
|
+
.filter((source) => source)
|
|
101
|
+
.reduce((target, source) => Object.assign(target, source), target)
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const noop = () => {};
|
|
105
|
+
|
|
106
|
+
const each = (object, callback) => {
|
|
107
|
+
let prop;
|
|
108
|
+
for (prop in object) {
|
|
109
|
+
if (hasProp(object, prop)) {
|
|
110
|
+
callback(object[prop], prop, object);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const map = (object, callback, context) => {
|
|
116
|
+
const result = [];
|
|
117
|
+
each(
|
|
118
|
+
object,
|
|
119
|
+
(value, key, object) => {
|
|
120
|
+
let item = callback(value, key, object);
|
|
121
|
+
if (isUndefined(item) === false) {
|
|
122
|
+
result.push(item);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
return result
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const filter = (object, callback, context) => {
|
|
129
|
+
const isArray = object instanceof Array;
|
|
130
|
+
const result = isArray ? [] : {};
|
|
131
|
+
each(
|
|
132
|
+
object,
|
|
133
|
+
(value, key, object) => {
|
|
134
|
+
let item = callback(value, key, object);
|
|
135
|
+
if (isUndefined(item) === false) {
|
|
136
|
+
if (isArray) {
|
|
137
|
+
result.push(item);
|
|
138
|
+
} else {
|
|
139
|
+
result[key] = item;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
return result
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const omit = (object, list) => {
|
|
147
|
+
return filter(object, (value, key) => {
|
|
148
|
+
if (list.indexOf(key) === -1) {
|
|
149
|
+
return value
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const resolve$1 = (value, callback, context) =>
|
|
155
|
+
Promise.resolve(value).then(callback.bind(context));
|
|
156
|
+
|
|
157
|
+
const hasProp = (object, prop) => {
|
|
158
|
+
return object && object.hasOwnProperty(prop)
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const joinPath = (path, template) => {
|
|
162
|
+
template = [path, template].join('/');
|
|
163
|
+
template = template.replace(/\/\//g, '/');
|
|
164
|
+
return template
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const defaults = {};
|
|
168
|
+
|
|
169
|
+
defaults.export = 'ejsPrecompiled';
|
|
170
|
+
defaults.cache = true;
|
|
171
|
+
defaults.chokidar = null;
|
|
172
|
+
defaults.path = 'views';
|
|
173
|
+
defaults.resolver = function (path, template) {
|
|
174
|
+
return Promise.resolve(
|
|
175
|
+
['resolver is not defined', path, template].join(' ')
|
|
176
|
+
)
|
|
177
|
+
};
|
|
178
|
+
defaults.extension = 'ejs';
|
|
179
|
+
defaults.rmWhitespace = true;
|
|
180
|
+
defaults.withObject = true;
|
|
181
|
+
defaults.vars = {
|
|
182
|
+
SCOPE: 'ejs',
|
|
183
|
+
COMPONENT: 'ui',
|
|
184
|
+
EXTEND: '$$e',
|
|
185
|
+
BUFFER: '$$a',
|
|
186
|
+
LAYOUT: '$$l',
|
|
187
|
+
BLOCKS: '$$b',
|
|
188
|
+
MACRO: '$$m',
|
|
189
|
+
SAFE: '$$v',
|
|
190
|
+
};
|
|
191
|
+
defaults.token = {
|
|
192
|
+
start: '<%',
|
|
193
|
+
end: '%>',
|
|
194
|
+
regex: '([\\s\\S]+?)',
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const configSchema = (config, options) => {
|
|
198
|
+
extend(config, {
|
|
199
|
+
path: typeProp(isString, defaults.path, config.path, options.path),
|
|
200
|
+
export: typeProp(
|
|
201
|
+
isString,
|
|
202
|
+
defaults.export,
|
|
203
|
+
config.export,
|
|
204
|
+
options.export
|
|
205
|
+
),
|
|
206
|
+
resolver: typeProp(
|
|
207
|
+
isFunction,
|
|
208
|
+
defaults.resolver,
|
|
209
|
+
config.resolver,
|
|
210
|
+
options.resolver
|
|
211
|
+
),
|
|
212
|
+
extension: typeProp(
|
|
213
|
+
isString,
|
|
214
|
+
defaults.extension,
|
|
215
|
+
config.extension,
|
|
216
|
+
options.extension
|
|
217
|
+
),
|
|
218
|
+
withObject: typeProp(
|
|
219
|
+
isBoolean,
|
|
220
|
+
defaults.withObject,
|
|
221
|
+
config.withObject,
|
|
222
|
+
options.withObject
|
|
223
|
+
),
|
|
224
|
+
rmWhitespace: typeProp(
|
|
225
|
+
isBoolean,
|
|
226
|
+
defaults.rmWhitespace,
|
|
227
|
+
config.rmWhitespace,
|
|
228
|
+
options.rmWhitespace
|
|
229
|
+
),
|
|
230
|
+
cache: typeProp(isBoolean, defaults.cache, config.cache, options.cache),
|
|
231
|
+
token: extend({}, defaults.token, config.token, options.token),
|
|
232
|
+
vars: extend({}, defaults.vars, config.vars, options.vars),
|
|
233
|
+
});
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const global = typeof globalThis !== 'undefined' ? globalThis : window || self;
|
|
237
|
+
|
|
238
|
+
function Cache(config) {
|
|
239
|
+
if (instanceOf(this, Cache) === false) return new Cache()
|
|
240
|
+
const cache = {
|
|
241
|
+
enabled: true,
|
|
242
|
+
list: {},
|
|
243
|
+
};
|
|
244
|
+
this.configure = function (config) {
|
|
245
|
+
cache.enabled = config.cache;
|
|
246
|
+
if (isNode() === false) {
|
|
247
|
+
this.load(global[config.export]);
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
this.clear = function () {
|
|
251
|
+
cache.list = {};
|
|
252
|
+
};
|
|
253
|
+
this.load = function (data) {
|
|
254
|
+
if (cache.enabled) {
|
|
255
|
+
extend(cache.list, data || {});
|
|
256
|
+
}
|
|
257
|
+
return this
|
|
258
|
+
};
|
|
259
|
+
this.get = function (key) {
|
|
260
|
+
if (cache.enabled) {
|
|
261
|
+
return cache.list[key]
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
this.set = function (key, value) {
|
|
265
|
+
if (cache.enabled) {
|
|
266
|
+
cache.list[key] = value;
|
|
267
|
+
}
|
|
268
|
+
return this
|
|
269
|
+
};
|
|
270
|
+
this.resolve = function (key) {
|
|
271
|
+
return Promise.resolve(this.get(key))
|
|
272
|
+
};
|
|
273
|
+
this.remove = function (key) {
|
|
274
|
+
delete cache.list[key];
|
|
275
|
+
};
|
|
276
|
+
this.exist = function (key) {
|
|
277
|
+
return hasProp(cache.list, key)
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const tagList = [
|
|
282
|
+
{
|
|
283
|
+
symbol: '-',
|
|
284
|
+
format(value) {
|
|
285
|
+
return `')\n${this.BUFFER}(${this.SAFE}(${value},1))\n${this.BUFFER}('`
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
symbol: '=',
|
|
290
|
+
format(value) {
|
|
291
|
+
return `')\n${this.BUFFER}(${this.SAFE}(${value}))\n${this.BUFFER}('`
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
symbol: '#',
|
|
296
|
+
format(value) {
|
|
297
|
+
return `')\n/**${value}**/\n${this.BUFFER}('`
|
|
298
|
+
},
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
symbol: '',
|
|
302
|
+
format(value) {
|
|
303
|
+
return `')\n${value.trim()}\n${this.BUFFER}('`
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
];
|
|
307
|
+
|
|
308
|
+
function matchTokens(regex, text, callback) {
|
|
309
|
+
let index = 0;
|
|
310
|
+
text.replace(regex, function () {
|
|
311
|
+
const params = [].slice.call(arguments, 0, -1);
|
|
312
|
+
const offset = params.pop();
|
|
313
|
+
const match = params.shift();
|
|
314
|
+
callback(params, index, offset);
|
|
315
|
+
index = offset + match.length;
|
|
316
|
+
return match
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function Compiler(config) {
|
|
321
|
+
if (instanceOf(this, Compiler) === false) return new Compiler(config)
|
|
322
|
+
|
|
323
|
+
const compiler = {};
|
|
324
|
+
|
|
325
|
+
this.configure = function (config) {
|
|
326
|
+
compiler.withObject = config.withObject;
|
|
327
|
+
compiler.rmWhitespace = config.rmWhitespace;
|
|
328
|
+
compiler.token = config.token;
|
|
329
|
+
compiler.vars = config.vars;
|
|
330
|
+
compiler.matches = [];
|
|
331
|
+
compiler.formats = [];
|
|
332
|
+
compiler.slurp = {
|
|
333
|
+
match: '[ \\t]*',
|
|
334
|
+
start: [compiler.token.start, '_'],
|
|
335
|
+
end: ['_', compiler.token.end],
|
|
336
|
+
};
|
|
337
|
+
tagList.forEach((item) => {
|
|
338
|
+
compiler.matches.push(
|
|
339
|
+
compiler.token.start
|
|
340
|
+
.concat(item.symbol)
|
|
341
|
+
.concat(compiler.token.regex)
|
|
342
|
+
.concat(compiler.token.end)
|
|
343
|
+
);
|
|
344
|
+
compiler.formats.push(item.format.bind(compiler.vars));
|
|
345
|
+
});
|
|
346
|
+
compiler.regex = new RegExp(
|
|
347
|
+
compiler.matches.join('|').concat('|$'),
|
|
348
|
+
'g'
|
|
349
|
+
);
|
|
350
|
+
compiler.slurpStart = new RegExp(
|
|
351
|
+
[compiler.slurp.match, compiler.slurp.start.join('')].join(''),
|
|
352
|
+
'gm'
|
|
353
|
+
);
|
|
354
|
+
compiler.slurpEnd = new RegExp(
|
|
355
|
+
[compiler.slurp.end.join(''), compiler.slurp.match].join(''),
|
|
356
|
+
'gm'
|
|
357
|
+
);
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
this.compile = function (content, path) {
|
|
361
|
+
const { SCOPE, SAFE, BUFFER, COMPONENT } = compiler.vars;
|
|
362
|
+
if (compiler.rmWhitespace) {
|
|
363
|
+
content = content
|
|
364
|
+
.replace(/[\r\n]+/g, '\n')
|
|
365
|
+
.replace(/^\s+|\s+$/gm, '');
|
|
366
|
+
}
|
|
367
|
+
content = content
|
|
368
|
+
.replace(compiler.slurpStart, compiler.token.start)
|
|
369
|
+
.replace(compiler.slurpEnd, compiler.token.end);
|
|
370
|
+
let source = `${BUFFER}('`;
|
|
371
|
+
matchTokens(compiler.regex, content, (params, index, offset) => {
|
|
372
|
+
source += symbols(content.slice(index, offset));
|
|
373
|
+
params.forEach((value, index) => {
|
|
374
|
+
if (value) {
|
|
375
|
+
source += compiler.formats[index](value);
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
source += `');`;
|
|
380
|
+
source = `try{${source}}catch(e){console.info(e)}`;
|
|
381
|
+
if (compiler.withObject) {
|
|
382
|
+
source = `with(${SCOPE}){${source}}`;
|
|
383
|
+
}
|
|
384
|
+
source = `${BUFFER}.start();${source}return ${BUFFER}.end();`;
|
|
385
|
+
source += `\n//# sourceURL=${path}`;
|
|
386
|
+
let result = null;
|
|
387
|
+
try {
|
|
388
|
+
result = new Function(SCOPE, COMPONENT, BUFFER, SAFE, source);
|
|
389
|
+
result.source = `(function(${SCOPE},${COMPONENT},${BUFFER},${SAFE}){\n${source}\n})`;
|
|
390
|
+
} catch (e) {
|
|
391
|
+
e.filename = path;
|
|
392
|
+
e.source = source;
|
|
393
|
+
throw e
|
|
394
|
+
}
|
|
395
|
+
return result
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
this.configure(config);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
function Template(config, cache, compiler) {
|
|
402
|
+
if (instanceOf(this, Template) === false)
|
|
403
|
+
return new Template(config, cache, compiler)
|
|
404
|
+
|
|
405
|
+
if (instanceOf(cache, Cache) === false)
|
|
406
|
+
throw new TypeError('cache is not instance of Cache')
|
|
407
|
+
|
|
408
|
+
if (instanceOf(compiler, Compiler) === false)
|
|
409
|
+
throw new TypeError('compiler is not instance of Compiler')
|
|
410
|
+
|
|
411
|
+
const template = {};
|
|
412
|
+
|
|
413
|
+
const result = (template, content) => {
|
|
414
|
+
cache.set(template, content);
|
|
415
|
+
return content
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
const resolve = (path) => {
|
|
419
|
+
return template.resolver(template.path, path)
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
const compile = (content, template) => {
|
|
423
|
+
if (isFunction(content)) {
|
|
424
|
+
return content
|
|
425
|
+
} else {
|
|
426
|
+
return compiler.compile(content, template)
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
this.configure = function (config) {
|
|
431
|
+
template.path = config.path;
|
|
432
|
+
template.cache = config.cache;
|
|
433
|
+
if (isFunction(config.resolver)) {
|
|
434
|
+
template.resolver = config.resolver;
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
this.get = function (template) {
|
|
439
|
+
if (cache.exist(template)) {
|
|
440
|
+
return cache.resolve(template)
|
|
441
|
+
}
|
|
442
|
+
return resolve(template).then((content) =>
|
|
443
|
+
result(template, compile(content, template))
|
|
444
|
+
)
|
|
445
|
+
};
|
|
446
|
+
this.configure(config);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
const selfClosed = [
|
|
450
|
+
'area',
|
|
451
|
+
'base',
|
|
452
|
+
'br',
|
|
453
|
+
'col',
|
|
454
|
+
'embed',
|
|
455
|
+
'hr',
|
|
456
|
+
'img',
|
|
457
|
+
'input',
|
|
458
|
+
'link',
|
|
459
|
+
'meta',
|
|
460
|
+
'param',
|
|
461
|
+
'source',
|
|
462
|
+
'track',
|
|
463
|
+
'wbr',
|
|
464
|
+
];
|
|
465
|
+
|
|
466
|
+
const space = ' ';
|
|
467
|
+
const quote = '"';
|
|
468
|
+
const equal = '=';
|
|
469
|
+
const slash = '/';
|
|
470
|
+
const lt = '<';
|
|
471
|
+
const gt = '>';
|
|
472
|
+
|
|
473
|
+
const element = (tag, attrs, content) => {
|
|
474
|
+
const result = [];
|
|
475
|
+
const hasClosedTag = selfClosed.indexOf(tag) === -1;
|
|
476
|
+
const attributes = map(attrs, (value, key) => {
|
|
477
|
+
if (value !== null && value !== undefined) {
|
|
478
|
+
return [
|
|
479
|
+
entities(key),
|
|
480
|
+
[quote, entities(value), quote].join(''),
|
|
481
|
+
].join(equal)
|
|
482
|
+
}
|
|
483
|
+
}).join(space);
|
|
484
|
+
result.push([lt, tag, space, attributes, gt].join(''));
|
|
485
|
+
if (content) {
|
|
486
|
+
result.push(content instanceof Array ? content.join('') : content);
|
|
487
|
+
}
|
|
488
|
+
if (hasClosedTag) {
|
|
489
|
+
result.push([lt, slash, tag, gt].join(''));
|
|
490
|
+
}
|
|
491
|
+
return result.join('')
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
function resolve(list) {
|
|
495
|
+
return Promise.all(list || []).then((list) => list.join(''))
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
function createBuffer() {
|
|
499
|
+
let store = [],
|
|
500
|
+
array = [];
|
|
501
|
+
function buffer(value) {
|
|
502
|
+
array.push(value);
|
|
503
|
+
}
|
|
504
|
+
buffer.start = function () {
|
|
505
|
+
array = [];
|
|
506
|
+
};
|
|
507
|
+
buffer.backup = function () {
|
|
508
|
+
store.push(array.concat());
|
|
509
|
+
array = [];
|
|
510
|
+
};
|
|
511
|
+
buffer.restore = function () {
|
|
512
|
+
const result = array.concat();
|
|
513
|
+
array = store.pop();
|
|
514
|
+
return resolve(result)
|
|
515
|
+
};
|
|
516
|
+
buffer.error = function (e) {
|
|
517
|
+
throw e
|
|
518
|
+
};
|
|
519
|
+
buffer.end = function () {
|
|
520
|
+
return resolve(array)
|
|
521
|
+
};
|
|
522
|
+
return buffer
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
function Context(config) {
|
|
526
|
+
if (instanceOf(this, Context) === false) return new Context(config)
|
|
527
|
+
this.configure = function (config, methods) {
|
|
528
|
+
const { BLOCKS, MACRO, EXTEND, LAYOUT, BUFFER, COMPONENT } = config.vars;
|
|
529
|
+
|
|
530
|
+
this.create = function (data) {
|
|
531
|
+
return new Scope(data)
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
this.helpers = function (methods) {
|
|
535
|
+
extend(Scope.prototype, methods || {});
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
function Scope(data) {
|
|
539
|
+
this[BLOCKS] = {};
|
|
540
|
+
this[MACRO] = {};
|
|
541
|
+
extend(this, data || {});
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
Scope.prototype = extend({}, methods || {});
|
|
545
|
+
Object.defineProperties(Scope.prototype, {
|
|
546
|
+
[BUFFER]: {
|
|
547
|
+
value: createBuffer(),
|
|
548
|
+
writable: true,
|
|
549
|
+
configurable: false,
|
|
550
|
+
enumerable: false,
|
|
551
|
+
},
|
|
552
|
+
[BLOCKS]: {
|
|
553
|
+
value: {},
|
|
554
|
+
writable: true,
|
|
555
|
+
configurable: false,
|
|
556
|
+
enumerable: false,
|
|
557
|
+
},
|
|
558
|
+
[MACRO]: {
|
|
559
|
+
value: {},
|
|
560
|
+
writable: true,
|
|
561
|
+
configurable: false,
|
|
562
|
+
enumerable: false,
|
|
563
|
+
},
|
|
564
|
+
[LAYOUT]: {
|
|
565
|
+
value: false,
|
|
566
|
+
writable: true,
|
|
567
|
+
configurable: false,
|
|
568
|
+
enumerable: false,
|
|
569
|
+
},
|
|
570
|
+
[EXTEND]: {
|
|
571
|
+
value: false,
|
|
572
|
+
writable: true,
|
|
573
|
+
configurable: false,
|
|
574
|
+
enumerable: false,
|
|
575
|
+
},
|
|
576
|
+
getMacro: {
|
|
577
|
+
value() {
|
|
578
|
+
return this[MACRO]
|
|
579
|
+
},
|
|
580
|
+
writable: false,
|
|
581
|
+
configurable: false,
|
|
582
|
+
enumerable: false,
|
|
583
|
+
},
|
|
584
|
+
getBuffer: {
|
|
585
|
+
value() {
|
|
586
|
+
return this[BUFFER]
|
|
587
|
+
},
|
|
588
|
+
writable: false,
|
|
589
|
+
configurable: false,
|
|
590
|
+
enumerable: false,
|
|
591
|
+
},
|
|
592
|
+
getComponent: {
|
|
593
|
+
value() {
|
|
594
|
+
const context = this;
|
|
595
|
+
if (COMPONENT in context) {
|
|
596
|
+
return function () {
|
|
597
|
+
return context[COMPONENT].apply(context, arguments)
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
return function () {
|
|
601
|
+
console.log('%s function not defined', COMPONENT);
|
|
602
|
+
}
|
|
603
|
+
},
|
|
604
|
+
writable: false,
|
|
605
|
+
configurable: false,
|
|
606
|
+
enumerable: false,
|
|
607
|
+
},
|
|
608
|
+
getBlocks: {
|
|
609
|
+
value() {
|
|
610
|
+
return this[BLOCKS]
|
|
611
|
+
},
|
|
612
|
+
writable: false,
|
|
613
|
+
configurable: false,
|
|
614
|
+
enumerable: false,
|
|
615
|
+
},
|
|
616
|
+
setExtend: {
|
|
617
|
+
value(value) {
|
|
618
|
+
this[EXTEND] = value;
|
|
619
|
+
},
|
|
620
|
+
writable: false,
|
|
621
|
+
configurable: false,
|
|
622
|
+
enumerable: false,
|
|
623
|
+
},
|
|
624
|
+
getExtend: {
|
|
625
|
+
value() {
|
|
626
|
+
return this[EXTEND]
|
|
627
|
+
},
|
|
628
|
+
writable: false,
|
|
629
|
+
configurable: false,
|
|
630
|
+
enumerable: false,
|
|
631
|
+
},
|
|
632
|
+
setLayout: {
|
|
633
|
+
value(layout) {
|
|
634
|
+
this[LAYOUT] = layout;
|
|
635
|
+
},
|
|
636
|
+
writable: false,
|
|
637
|
+
configurable: false,
|
|
638
|
+
enumerable: false,
|
|
639
|
+
},
|
|
640
|
+
getLayout: {
|
|
641
|
+
value() {
|
|
642
|
+
return this[LAYOUT]
|
|
643
|
+
},
|
|
644
|
+
writable: false,
|
|
645
|
+
configurable: false,
|
|
646
|
+
enumerable: false,
|
|
647
|
+
},
|
|
648
|
+
clone: {
|
|
649
|
+
value(exclude_blocks) {
|
|
650
|
+
const filter = [LAYOUT, EXTEND, BUFFER];
|
|
651
|
+
if (exclude_blocks === true) {
|
|
652
|
+
filter.push(BLOCKS);
|
|
653
|
+
}
|
|
654
|
+
return omit(this, filter)
|
|
655
|
+
},
|
|
656
|
+
writable: false,
|
|
657
|
+
configurable: false,
|
|
658
|
+
enumerable: false,
|
|
659
|
+
},
|
|
660
|
+
extend: {
|
|
661
|
+
value(layout) {
|
|
662
|
+
this.setExtend(true);
|
|
663
|
+
this.setLayout(layout);
|
|
664
|
+
},
|
|
665
|
+
writable: false,
|
|
666
|
+
configurable: false,
|
|
667
|
+
enumerable: false,
|
|
668
|
+
},
|
|
669
|
+
echo: {
|
|
670
|
+
value(layout) {
|
|
671
|
+
const buffer = this.getBuffer();
|
|
672
|
+
const params = [].slice.call(arguments);
|
|
673
|
+
params.forEach(buffer);
|
|
674
|
+
},
|
|
675
|
+
writable: false,
|
|
676
|
+
configurable: false,
|
|
677
|
+
enumerable: false,
|
|
678
|
+
},
|
|
679
|
+
fn: {
|
|
680
|
+
value(callback) {
|
|
681
|
+
const buffer = this.getBuffer();
|
|
682
|
+
const context = this;
|
|
683
|
+
return function () {
|
|
684
|
+
buffer.backup();
|
|
685
|
+
if (isFunction(callback)) {
|
|
686
|
+
callback.apply(context, arguments);
|
|
687
|
+
}
|
|
688
|
+
return buffer.restore()
|
|
689
|
+
}
|
|
690
|
+
},
|
|
691
|
+
writable: false,
|
|
692
|
+
configurable: false,
|
|
693
|
+
enumerable: false,
|
|
694
|
+
},
|
|
695
|
+
get: {
|
|
696
|
+
value(name, defaults) {
|
|
697
|
+
const path = getPath(this, name, true);
|
|
698
|
+
const result = path.shift();
|
|
699
|
+
const prop = path.pop();
|
|
700
|
+
return hasProp(result, prop) ? result[prop] : defaults
|
|
701
|
+
},
|
|
702
|
+
writable: false,
|
|
703
|
+
configurable: false,
|
|
704
|
+
enumerable: false,
|
|
705
|
+
},
|
|
706
|
+
set: {
|
|
707
|
+
value(name, value) {
|
|
708
|
+
const path = getPath(this, name, false);
|
|
709
|
+
const result = path.shift();
|
|
710
|
+
const prop = path.pop();
|
|
711
|
+
if (this.getExtend() && hasProp(result, prop)) {
|
|
712
|
+
return result[prop]
|
|
713
|
+
}
|
|
714
|
+
return (result[prop] = value)
|
|
715
|
+
},
|
|
716
|
+
writable: false,
|
|
717
|
+
configurable: false,
|
|
718
|
+
enumerable: false,
|
|
719
|
+
},
|
|
720
|
+
macro: {
|
|
721
|
+
value(name, callback) {
|
|
722
|
+
const list = this.getMacro();
|
|
723
|
+
const macro = this.fn(callback);
|
|
724
|
+
const context = this;
|
|
725
|
+
list[name] = function () {
|
|
726
|
+
return context.echo(macro.apply(undefined, arguments))
|
|
727
|
+
};
|
|
728
|
+
},
|
|
729
|
+
writable: false,
|
|
730
|
+
configurable: false,
|
|
731
|
+
enumerable: false,
|
|
732
|
+
},
|
|
733
|
+
call: {
|
|
734
|
+
value(name) {
|
|
735
|
+
const list = this.getMacro();
|
|
736
|
+
const macro = list[name];
|
|
737
|
+
const params = [].slice.call(arguments, 1);
|
|
738
|
+
if (isFunction(macro)) {
|
|
739
|
+
return macro.apply(macro, params)
|
|
740
|
+
}
|
|
741
|
+
},
|
|
742
|
+
writable: false,
|
|
743
|
+
configurable: false,
|
|
744
|
+
enumerable: false,
|
|
745
|
+
},
|
|
746
|
+
block: {
|
|
747
|
+
value(name, callback) {
|
|
748
|
+
const blocks = this.getBlocks();
|
|
749
|
+
blocks[name] = blocks[name] || [];
|
|
750
|
+
blocks[name].push(this.fn(callback));
|
|
751
|
+
if (this.getExtend()) return
|
|
752
|
+
const list = Object.assign([], blocks[name]);
|
|
753
|
+
const current = function () {
|
|
754
|
+
return list.shift()
|
|
755
|
+
};
|
|
756
|
+
const next = () => {
|
|
757
|
+
const parent = current();
|
|
758
|
+
if (parent) {
|
|
759
|
+
return () => {
|
|
760
|
+
this.echo(parent(next()));
|
|
761
|
+
}
|
|
762
|
+
} else {
|
|
763
|
+
return noop
|
|
764
|
+
}
|
|
765
|
+
};
|
|
766
|
+
this.echo(current()(next()));
|
|
767
|
+
},
|
|
768
|
+
writable: false,
|
|
769
|
+
configurable: false,
|
|
770
|
+
enumerable: false,
|
|
771
|
+
},
|
|
772
|
+
include: {
|
|
773
|
+
value(path, data, cx) {
|
|
774
|
+
const context = cx === false ? {} : this.clone(true);
|
|
775
|
+
const params = extend(context, data || {});
|
|
776
|
+
const promise = this.render(path, params);
|
|
777
|
+
this.echo(promise);
|
|
778
|
+
},
|
|
779
|
+
writable: false,
|
|
780
|
+
configurable: false,
|
|
781
|
+
enumerable: false,
|
|
782
|
+
},
|
|
783
|
+
use: {
|
|
784
|
+
value(path, namespace) {
|
|
785
|
+
const promise = this.require(path);
|
|
786
|
+
this.echo(
|
|
787
|
+
resolve$1(
|
|
788
|
+
promise,
|
|
789
|
+
function (exports) {
|
|
790
|
+
const list = this.getMacro();
|
|
791
|
+
each(exports, function (macro, name) {
|
|
792
|
+
list[[namespace, name].join('.')] = macro;
|
|
793
|
+
});
|
|
794
|
+
},
|
|
795
|
+
this
|
|
796
|
+
)
|
|
797
|
+
);
|
|
798
|
+
},
|
|
799
|
+
writable: false,
|
|
800
|
+
configurable: false,
|
|
801
|
+
enumerable: false,
|
|
802
|
+
},
|
|
803
|
+
async: {
|
|
804
|
+
value(promise, callback) {
|
|
805
|
+
this.echo(
|
|
806
|
+
resolve$1(
|
|
807
|
+
promise,
|
|
808
|
+
function (data) {
|
|
809
|
+
return this.fn(callback)(data)
|
|
810
|
+
},
|
|
811
|
+
this
|
|
812
|
+
)
|
|
813
|
+
);
|
|
814
|
+
},
|
|
815
|
+
writable: false,
|
|
816
|
+
configurable: false,
|
|
817
|
+
enumerable: false,
|
|
818
|
+
},
|
|
819
|
+
each: {
|
|
820
|
+
value: function (object, callback) {
|
|
821
|
+
if (isString(object)) {
|
|
822
|
+
object = this.get(object, []);
|
|
823
|
+
}
|
|
824
|
+
each(object, callback);
|
|
825
|
+
},
|
|
826
|
+
writable: false,
|
|
827
|
+
configurable: false,
|
|
828
|
+
enumerable: false,
|
|
829
|
+
},
|
|
830
|
+
element: {
|
|
831
|
+
value(tag, attr, content) {
|
|
832
|
+
return element(tag, attr, content)
|
|
833
|
+
},
|
|
834
|
+
},
|
|
835
|
+
el: {
|
|
836
|
+
value(tag, attr, content) {
|
|
837
|
+
if (isFunction(content)) {
|
|
838
|
+
content = this.fn(content)();
|
|
839
|
+
}
|
|
840
|
+
this.echo(
|
|
841
|
+
resolve$1(
|
|
842
|
+
content,
|
|
843
|
+
function (content) {
|
|
844
|
+
return this.element(tag, attr, content)
|
|
845
|
+
},
|
|
846
|
+
this
|
|
847
|
+
)
|
|
848
|
+
);
|
|
849
|
+
},
|
|
850
|
+
writable: false,
|
|
851
|
+
configurable: false,
|
|
852
|
+
enumerable: false,
|
|
853
|
+
},
|
|
854
|
+
});
|
|
855
|
+
};
|
|
856
|
+
this.configure(config);
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
function EJS(options) {
|
|
860
|
+
if (instanceOf(this, EJS) === false) return new EJS(options)
|
|
861
|
+
|
|
862
|
+
const scope = {};
|
|
863
|
+
const config = {};
|
|
864
|
+
|
|
865
|
+
configSchema(config, options || {});
|
|
866
|
+
|
|
867
|
+
const context = new Context(config);
|
|
868
|
+
const compiler = new Compiler(config);
|
|
869
|
+
const cache = new Cache();
|
|
870
|
+
const template = new Template(config, cache, compiler);
|
|
871
|
+
|
|
872
|
+
const output = (path, scope) => {
|
|
873
|
+
return template.get(path).then(function (callback) {
|
|
874
|
+
return callback.call(
|
|
875
|
+
scope,
|
|
876
|
+
scope,
|
|
877
|
+
scope.getComponent(),
|
|
878
|
+
scope.getBuffer(),
|
|
879
|
+
safeValue
|
|
880
|
+
)
|
|
881
|
+
})
|
|
882
|
+
};
|
|
883
|
+
const require = (name) => {
|
|
884
|
+
const filepath = ext(name, config.extension);
|
|
885
|
+
const scope = context.create({});
|
|
886
|
+
return output(filepath, scope).then(() => {
|
|
887
|
+
return scope.getMacro()
|
|
888
|
+
})
|
|
889
|
+
};
|
|
890
|
+
const render = (name, data) => {
|
|
891
|
+
const filepath = ext(name, config.extension);
|
|
892
|
+
const scope = context.create(data);
|
|
893
|
+
return output(filepath, scope).then((content) => {
|
|
894
|
+
if (scope.getExtend()) {
|
|
895
|
+
scope.setExtend(false);
|
|
896
|
+
const layout = scope.getLayout();
|
|
897
|
+
const data = scope.clone();
|
|
898
|
+
return render(layout, data)
|
|
899
|
+
}
|
|
900
|
+
return content
|
|
901
|
+
})
|
|
902
|
+
};
|
|
903
|
+
this.configure = function (options) {
|
|
904
|
+
options = options || {};
|
|
905
|
+
configSchema(config, options);
|
|
906
|
+
context.configure(config, scope);
|
|
907
|
+
compiler.configure(config);
|
|
908
|
+
cache.configure(config);
|
|
909
|
+
template.configure(config);
|
|
910
|
+
return config
|
|
911
|
+
};
|
|
912
|
+
this.render = function (name, data) {
|
|
913
|
+
return render(name, data)
|
|
914
|
+
};
|
|
915
|
+
this.helpers = function (methods) {
|
|
916
|
+
context.helpers(extend(scope, methods));
|
|
917
|
+
};
|
|
918
|
+
this.preload = function (list) {
|
|
919
|
+
return cache.load(list || {})
|
|
920
|
+
};
|
|
921
|
+
this.create = function (options) {
|
|
922
|
+
return new EJS(options)
|
|
923
|
+
};
|
|
924
|
+
this.compile = function (content, path) {
|
|
925
|
+
return compiler.compile(content, path)
|
|
926
|
+
};
|
|
927
|
+
this.context = function (data) {
|
|
928
|
+
return context.create(data)
|
|
929
|
+
};
|
|
930
|
+
this.helpers({ require, render });
|
|
931
|
+
return this
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
const httpRequest = (path, template) => {
|
|
935
|
+
return fetch(joinPath(path, template)).then(
|
|
936
|
+
(response) => response.text(),
|
|
937
|
+
(reason) => String(reason)
|
|
938
|
+
)
|
|
939
|
+
};
|
|
940
|
+
|
|
941
|
+
const ejs = new EJS({ resolver: httpRequest });
|
|
942
|
+
|
|
943
|
+
const { render, context, compile, helpers, preload, configure, create } = ejs;
|
|
944
|
+
|
|
945
|
+
export { compile, configure, context, create, helpers, preload, render };
|