@kosatyi/ejs 0.0.107 → 0.0.109
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/README.md +4 -7
- package/bin/bundler.js +21 -9
- package/dist/cjs/browser.js +532 -651
- package/dist/cjs/bundler.js +105 -66
- package/dist/cjs/element.js +28 -63
- package/dist/cjs/index.js +540 -668
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/worker.js +553 -976
- package/dist/esm/browser.js +511 -540
- package/dist/esm/bundler.js +104 -66
- package/dist/esm/element.js +13 -47
- package/dist/esm/index.js +514 -555
- package/dist/esm/worker.js +519 -565
- package/dist/kosatyi-ejs-0.0.107.tgz +0 -0
- package/dist/kosatyi-ejs-0.0.108.tgz +0 -0
- package/dist/umd/browser.js +533 -652
- package/dist/umd/browser.js.map +7 -0
- package/dist/umd/browser.min.js +1 -1
- package/dist/umd/browser.min.js.map +7 -0
- package/dist/umd/element.js +28 -63
- package/dist/umd/element.min.js +1 -1
- package/dist/umd/index.js +541 -669
- package/dist/umd/index.min.js +1 -1
- package/dist/umd/worker.js +819 -1242
- package/dist/umd/worker.min.js +1 -3
- package/package.json +80 -71
- package/types/browser.d.ts +14 -0
- package/types/bundler.d.ts +11 -12
- package/types/context.d.ts +96 -0
- package/types/ejs.d.ts +111 -73
- package/types/element.d.ts +9 -0
- package/types/error.d.ts +14 -0
- package/types/global.d.ts +6 -6
- package/types/index.d.ts +16 -0
- package/types/worker.d.ts +35 -0
package/dist/esm/index.js
CHANGED
|
@@ -1,23 +1,117 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
1
|
import path from 'node:path';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @type {EjsConfig}
|
|
6
|
+
*/
|
|
7
|
+
const ejsDefaults = {
|
|
8
|
+
precompiled: 'ejsPrecompiled',
|
|
9
|
+
cache: true,
|
|
10
|
+
path: 'views',
|
|
11
|
+
extension: 'ejs',
|
|
12
|
+
rmWhitespace: true,
|
|
13
|
+
strict: true,
|
|
14
|
+
resolver: (path, template) => {
|
|
15
|
+
return Promise.resolve(
|
|
16
|
+
['resolver is not defined', path, template].join(' '),
|
|
17
|
+
)
|
|
18
|
+
},
|
|
19
|
+
globals: [],
|
|
20
|
+
vars: {
|
|
21
|
+
SCOPE: 'ejs',
|
|
22
|
+
COMPONENT: 'ui',
|
|
23
|
+
ELEMENT: 'el',
|
|
24
|
+
EXTEND: '$$e',
|
|
25
|
+
BUFFER: '$$a',
|
|
26
|
+
LAYOUT: '$$l',
|
|
27
|
+
BLOCKS: '$$b',
|
|
28
|
+
MACRO: '$$m',
|
|
29
|
+
SAFE: '$$v',
|
|
30
|
+
},
|
|
31
|
+
token: {
|
|
32
|
+
start: '<%',
|
|
33
|
+
end: '%>',
|
|
34
|
+
regex: '([\\s\\S]+?)',
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const jsVariableName = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/;
|
|
3
39
|
|
|
4
40
|
const typeProp = function () {
|
|
5
41
|
const args = [].slice.call(arguments);
|
|
6
42
|
const callback = args.shift();
|
|
7
43
|
return args.filter(callback).pop()
|
|
8
44
|
};
|
|
9
|
-
const isArray = (
|
|
10
|
-
const isFunction = (
|
|
11
|
-
const isString = (
|
|
12
|
-
const isBoolean = (
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
45
|
+
const isArray = (value) => Array.isArray(value);
|
|
46
|
+
const isFunction = (value) => typeof value === 'function';
|
|
47
|
+
const isString = (value) => typeof value === 'string';
|
|
48
|
+
const isBoolean = (value) => typeof value === 'boolean';
|
|
49
|
+
const isArrayOfVariables = (value) => {
|
|
50
|
+
if (!isArray(value)) return false
|
|
51
|
+
return value.filter((name) => {
|
|
52
|
+
const valid = jsVariableName.test(name);
|
|
53
|
+
if (valid === false)
|
|
54
|
+
console.log(
|
|
55
|
+
`ejsConfig.globals: expected '${name}' to be valid variable name --> skipped`,
|
|
56
|
+
);
|
|
57
|
+
return valid
|
|
58
|
+
})
|
|
59
|
+
};
|
|
19
60
|
|
|
20
|
-
const
|
|
61
|
+
const configSchema = (config, options) => {
|
|
62
|
+
return Object.assign(config, {
|
|
63
|
+
path: typeProp(isString, ejsDefaults.path, config.path, options.path),
|
|
64
|
+
precompiled: typeProp(
|
|
65
|
+
isString,
|
|
66
|
+
ejsDefaults.precompiled,
|
|
67
|
+
config.export,
|
|
68
|
+
options.export,
|
|
69
|
+
),
|
|
70
|
+
resolver: typeProp(
|
|
71
|
+
isFunction,
|
|
72
|
+
ejsDefaults.resolver,
|
|
73
|
+
config.resolver,
|
|
74
|
+
options.resolver,
|
|
75
|
+
),
|
|
76
|
+
extension: typeProp(
|
|
77
|
+
isString,
|
|
78
|
+
ejsDefaults.extension,
|
|
79
|
+
config.extension,
|
|
80
|
+
options.extension,
|
|
81
|
+
),
|
|
82
|
+
strict: typeProp(
|
|
83
|
+
isBoolean,
|
|
84
|
+
ejsDefaults.strict,
|
|
85
|
+
config.strict,
|
|
86
|
+
options.strict,
|
|
87
|
+
),
|
|
88
|
+
rmWhitespace: typeProp(
|
|
89
|
+
isBoolean,
|
|
90
|
+
ejsDefaults.rmWhitespace,
|
|
91
|
+
config.rmWhitespace,
|
|
92
|
+
options.rmWhitespace,
|
|
93
|
+
),
|
|
94
|
+
cache: typeProp(
|
|
95
|
+
isBoolean,
|
|
96
|
+
ejsDefaults.cache,
|
|
97
|
+
config.cache,
|
|
98
|
+
options.cache,
|
|
99
|
+
),
|
|
100
|
+
globals: typeProp(
|
|
101
|
+
isArray,
|
|
102
|
+
ejsDefaults.globals,
|
|
103
|
+
config.globals,
|
|
104
|
+
isArrayOfVariables(options.globals),
|
|
105
|
+
),
|
|
106
|
+
token: Object.assign(
|
|
107
|
+
{},
|
|
108
|
+
ejsDefaults.token,
|
|
109
|
+
config.token,
|
|
110
|
+
options.token,
|
|
111
|
+
),
|
|
112
|
+
vars: Object.assign({}, ejsDefaults.vars, config.vars, options.vars),
|
|
113
|
+
})
|
|
114
|
+
};
|
|
21
115
|
|
|
22
116
|
const symbolEntities = {
|
|
23
117
|
"'": "'",
|
|
@@ -88,25 +182,6 @@ const getPath = (context, name, strict) => {
|
|
|
88
182
|
return [data, prop]
|
|
89
183
|
};
|
|
90
184
|
|
|
91
|
-
const ext = (path, defaults) => {
|
|
92
|
-
const ext = path.split('.').pop();
|
|
93
|
-
if (ext !== defaults) {
|
|
94
|
-
path = [path, defaults].join('.');
|
|
95
|
-
}
|
|
96
|
-
return path
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* @type {<T extends {}, U, V, W,Y>(T,U,V,W,Y)=> T & U & V & W & Y}
|
|
101
|
-
*/
|
|
102
|
-
const extend = (target, ...args) => {
|
|
103
|
-
return args
|
|
104
|
-
.filter((source) => source)
|
|
105
|
-
.reduce((target, source) => Object.assign(target, source), target)
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
const noop = () => {};
|
|
109
|
-
|
|
110
185
|
const each = (object, callback) => {
|
|
111
186
|
let prop;
|
|
112
187
|
for (prop in object) {
|
|
@@ -116,53 +191,16 @@ const each = (object, callback) => {
|
|
|
116
191
|
}
|
|
117
192
|
};
|
|
118
193
|
|
|
119
|
-
const map = (object, callback, context) => {
|
|
120
|
-
const result = [];
|
|
121
|
-
each(
|
|
122
|
-
object,
|
|
123
|
-
(value, key, object) => {
|
|
124
|
-
let item = callback(value, key, object);
|
|
125
|
-
if (isUndefined(item) === false) {
|
|
126
|
-
result.push(item);
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
return result
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
const filter = (object, callback, context) => {
|
|
133
|
-
const isArray = object instanceof Array;
|
|
134
|
-
const result = isArray ? [] : {};
|
|
135
|
-
each(
|
|
136
|
-
object,
|
|
137
|
-
(value, key, object) => {
|
|
138
|
-
let item = callback(value, key, object);
|
|
139
|
-
if (isUndefined(item) === false) {
|
|
140
|
-
if (isArray) {
|
|
141
|
-
result.push(item);
|
|
142
|
-
} else {
|
|
143
|
-
result[key] = item;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
return result
|
|
148
|
-
};
|
|
149
|
-
|
|
150
194
|
const omit = (object, list) => {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
195
|
+
const result = { ...object };
|
|
196
|
+
for (const key of list) {
|
|
197
|
+
delete result[key];
|
|
198
|
+
}
|
|
199
|
+
return result
|
|
156
200
|
};
|
|
157
201
|
|
|
158
|
-
/**
|
|
159
|
-
*
|
|
160
|
-
* @param object
|
|
161
|
-
* @param prop
|
|
162
|
-
* @return {boolean}
|
|
163
|
-
*/
|
|
164
202
|
const hasProp = (object, prop) => {
|
|
165
|
-
return object &&
|
|
203
|
+
return object && Object.hasOwn(object, prop)
|
|
166
204
|
};
|
|
167
205
|
|
|
168
206
|
const joinPath = (path, template) => {
|
|
@@ -171,9 +209,68 @@ const joinPath = (path, template) => {
|
|
|
171
209
|
return template
|
|
172
210
|
};
|
|
173
211
|
|
|
174
|
-
const
|
|
212
|
+
const bindContext = (object, methods = []) => {
|
|
213
|
+
for (let i = 0, len = methods.length; i < len; i++) {
|
|
214
|
+
const name = methods[i];
|
|
215
|
+
if (name in object) {
|
|
216
|
+
object[name] = object[name].bind(object);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
class Template {
|
|
222
|
+
#path
|
|
223
|
+
#resolver
|
|
224
|
+
#cache
|
|
225
|
+
#compiler
|
|
226
|
+
static exports = ['configure', 'get', 'compile']
|
|
227
|
+
constructor(options, cache, compiler) {
|
|
228
|
+
bindContext(this, this.constructor.exports);
|
|
229
|
+
this.#cache = cache;
|
|
230
|
+
this.#compiler = compiler;
|
|
231
|
+
this.configure(options ?? {});
|
|
232
|
+
}
|
|
233
|
+
configure(options) {
|
|
234
|
+
this.#path = options.path;
|
|
235
|
+
if (isFunction(options.resolver)) {
|
|
236
|
+
this.#resolver = options.resolver;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
#resolve(template) {
|
|
240
|
+
const cached = this.#cache.get(template);
|
|
241
|
+
if (cached instanceof Promise) return cached
|
|
242
|
+
const result = Promise.resolve(this.#resolver(this.#path, template));
|
|
243
|
+
this.#cache.set(template, result);
|
|
244
|
+
return result
|
|
245
|
+
}
|
|
246
|
+
compile(content, template) {
|
|
247
|
+
const cached = this.#cache.get(template);
|
|
248
|
+
if (typeof cached === 'function') return cached
|
|
249
|
+
if (typeof content === 'string') {
|
|
250
|
+
content = this.#compiler.compile(content, template);
|
|
251
|
+
}
|
|
252
|
+
if (typeof content === 'function') {
|
|
253
|
+
this.#cache.set(template, content);
|
|
254
|
+
return content
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
get(template) {
|
|
258
|
+
return this.#resolve(template).then((content) =>
|
|
259
|
+
this.compile(content, template),
|
|
260
|
+
)
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const tokenList = [
|
|
265
|
+
['-', (v, b, s) => `')\n${b}(${s}(${v},1))\n${b}('`],
|
|
266
|
+
['=', (v, b, s) => `')\n${b}(${s}(${v}))\n${b}('`],
|
|
267
|
+
['#', (v, b) => `')\n/**${v}**/\n${b}('`],
|
|
268
|
+
['', (v, b) => `')\n${v}\n${b}('`],
|
|
269
|
+
];
|
|
270
|
+
|
|
271
|
+
const tokensMatch = (regex, content, callback) => {
|
|
175
272
|
let index = 0;
|
|
176
|
-
|
|
273
|
+
content.replace(regex, function () {
|
|
177
274
|
const params = [].slice.call(arguments, 0, -1);
|
|
178
275
|
const offset = params.pop();
|
|
179
276
|
const match = params.shift();
|
|
@@ -183,284 +280,167 @@ const matchTokens = (regex, text, callback) => {
|
|
|
183
280
|
});
|
|
184
281
|
};
|
|
185
282
|
|
|
186
|
-
|
|
283
|
+
class Compiler {
|
|
284
|
+
#config = {}
|
|
285
|
+
static exports = ['compile']
|
|
187
286
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
defaults.path = 'views';
|
|
192
|
-
defaults.resolver = function (path, template) {
|
|
193
|
-
return Promise.resolve(
|
|
194
|
-
['resolver is not defined', path, template].join(' '),
|
|
195
|
-
)
|
|
196
|
-
};
|
|
197
|
-
defaults.extension = 'ejs';
|
|
198
|
-
defaults.rmWhitespace = true;
|
|
199
|
-
defaults.withObject = true;
|
|
200
|
-
defaults.globalHelpers = [];
|
|
201
|
-
defaults.vars = {
|
|
202
|
-
SCOPE: 'ejs',
|
|
203
|
-
COMPONENT: 'ui',
|
|
204
|
-
ELEMENT: 'el',
|
|
205
|
-
EXTEND: '$$e',
|
|
206
|
-
BUFFER: '$$a',
|
|
207
|
-
LAYOUT: '$$l',
|
|
208
|
-
BLOCKS: '$$b',
|
|
209
|
-
MACRO: '$$m',
|
|
210
|
-
SAFE: '$$v',
|
|
211
|
-
};
|
|
212
|
-
defaults.token = {
|
|
213
|
-
start: '<%',
|
|
214
|
-
end: '%>',
|
|
215
|
-
regex: '([\\s\\S]+?)',
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
const configSchema = (config, options) => {
|
|
219
|
-
return extend(config, {
|
|
220
|
-
path: typeProp(isString, defaults.path, config.path, options.path),
|
|
221
|
-
export: typeProp(
|
|
222
|
-
isString,
|
|
223
|
-
defaults.export,
|
|
224
|
-
config.export,
|
|
225
|
-
options.export,
|
|
226
|
-
),
|
|
227
|
-
resolver: typeProp(
|
|
228
|
-
isFunction,
|
|
229
|
-
defaults.resolver,
|
|
230
|
-
config.resolver,
|
|
231
|
-
options.resolver,
|
|
232
|
-
),
|
|
233
|
-
extension: typeProp(
|
|
234
|
-
isString,
|
|
235
|
-
defaults.extension,
|
|
236
|
-
config.extension,
|
|
237
|
-
options.extension,
|
|
238
|
-
),
|
|
239
|
-
withObject: typeProp(
|
|
240
|
-
isBoolean,
|
|
241
|
-
defaults.withObject,
|
|
242
|
-
config.withObject,
|
|
243
|
-
options.withObject,
|
|
244
|
-
),
|
|
245
|
-
rmWhitespace: typeProp(
|
|
246
|
-
isBoolean,
|
|
247
|
-
defaults.rmWhitespace,
|
|
248
|
-
config.rmWhitespace,
|
|
249
|
-
options.rmWhitespace,
|
|
250
|
-
),
|
|
251
|
-
cache: typeProp(isBoolean, defaults.cache, config.cache, options.cache),
|
|
252
|
-
token: extend({}, defaults.token, config.token, options.token),
|
|
253
|
-
vars: extend({}, defaults.vars, config.vars, options.vars),
|
|
254
|
-
globalHelpers: typeProp(
|
|
255
|
-
isArray,
|
|
256
|
-
defaults.globalHelpers,
|
|
257
|
-
config.globalHelpers,
|
|
258
|
-
options.globalHelpers,
|
|
259
|
-
),
|
|
260
|
-
})
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
const Template = (options, cache, compiler) => {
|
|
264
|
-
const config = {
|
|
265
|
-
path: null,
|
|
266
|
-
resolver: null,
|
|
267
|
-
};
|
|
268
|
-
const resolve = (path) => {
|
|
269
|
-
return config.resolver(config.path, path)
|
|
270
|
-
};
|
|
271
|
-
const result = (template, content) => {
|
|
272
|
-
cache.set(template, content);
|
|
273
|
-
return content
|
|
274
|
-
};
|
|
275
|
-
const compile = (content, template) => {
|
|
276
|
-
if (isFunction(content)) {
|
|
277
|
-
return content
|
|
278
|
-
} else {
|
|
279
|
-
return compiler.compile(content, template)
|
|
280
|
-
}
|
|
281
|
-
};
|
|
282
|
-
const get = (template) => {
|
|
283
|
-
if (cache.exist(template)) {
|
|
284
|
-
return cache.resolve(template)
|
|
285
|
-
}
|
|
286
|
-
return resolve(template).then((content) =>
|
|
287
|
-
result(template, compile(content, template)),
|
|
288
|
-
)
|
|
289
|
-
};
|
|
290
|
-
const configure = (options) => {
|
|
291
|
-
config.path = options.path;
|
|
292
|
-
if (isFunction(options.resolver)) {
|
|
293
|
-
config.resolver = options.resolver;
|
|
294
|
-
}
|
|
295
|
-
};
|
|
296
|
-
configure(options);
|
|
297
|
-
return {
|
|
298
|
-
get,
|
|
299
|
-
configure,
|
|
300
|
-
compile,
|
|
287
|
+
constructor(options) {
|
|
288
|
+
bindContext(this, this.constructor.exports);
|
|
289
|
+
this.configure(options);
|
|
301
290
|
}
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
const configSymbols = [
|
|
305
|
-
{
|
|
306
|
-
symbol: '-',
|
|
307
|
-
format(value) {
|
|
308
|
-
return `')\n${this.BUFFER}(${this.SAFE}(${value},1))\n${this.BUFFER}('`
|
|
309
|
-
},
|
|
310
|
-
},
|
|
311
|
-
{
|
|
312
|
-
symbol: '=',
|
|
313
|
-
format(value) {
|
|
314
|
-
return `')\n${this.BUFFER}(${this.SAFE}(${value}))\n${this.BUFFER}('`
|
|
315
|
-
},
|
|
316
|
-
},
|
|
317
|
-
{
|
|
318
|
-
symbol: '#',
|
|
319
|
-
format(value) {
|
|
320
|
-
return `')\n/**${value}**/\n${this.BUFFER}('`
|
|
321
|
-
},
|
|
322
|
-
},
|
|
323
|
-
{
|
|
324
|
-
symbol: '',
|
|
325
|
-
format(value) {
|
|
326
|
-
return `')\n${value.trim()}\n${this.BUFFER}('`
|
|
327
|
-
},
|
|
328
|
-
},
|
|
329
|
-
];
|
|
330
291
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
config.
|
|
335
|
-
config.
|
|
336
|
-
config.
|
|
337
|
-
config.
|
|
338
|
-
config.
|
|
339
|
-
config.matches = [];
|
|
340
|
-
config.formats = [];
|
|
341
|
-
config.slurp = {
|
|
292
|
+
configure(options) {
|
|
293
|
+
this.#config.strict = options.strict;
|
|
294
|
+
this.#config.rmWhitespace = options.rmWhitespace;
|
|
295
|
+
this.#config.token = options.token;
|
|
296
|
+
this.#config.vars = options.vars;
|
|
297
|
+
this.#config.globals = options.globals;
|
|
298
|
+
this.#config.legacy = options.legacy ?? true;
|
|
299
|
+
this.#config.slurp = {
|
|
342
300
|
match: '[s\t\n]*',
|
|
343
|
-
start: [config.token.start, '_'],
|
|
344
|
-
end: ['_', config.token.end],
|
|
301
|
+
start: [this.#config.token.start, '_'],
|
|
302
|
+
end: ['_', this.#config.token.end],
|
|
345
303
|
};
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
.concat(
|
|
304
|
+
this.#config.matches = [];
|
|
305
|
+
this.#config.formats = [];
|
|
306
|
+
for (const [symbol, format] of tokenList) {
|
|
307
|
+
this.#config.matches.push(
|
|
308
|
+
this.#config.token.start
|
|
309
|
+
.concat(symbol)
|
|
310
|
+
.concat(this.#config.token.regex)
|
|
311
|
+
.concat(this.#config.token.end),
|
|
352
312
|
);
|
|
353
|
-
config.formats.push(
|
|
354
|
-
}
|
|
355
|
-
config.regex = new RegExp(
|
|
356
|
-
|
|
357
|
-
|
|
313
|
+
this.#config.formats.push(format);
|
|
314
|
+
}
|
|
315
|
+
this.#config.regex = new RegExp(
|
|
316
|
+
this.#config.matches.join('|').concat('|$'),
|
|
317
|
+
'g',
|
|
318
|
+
);
|
|
319
|
+
this.#config.slurpStart = new RegExp(
|
|
320
|
+
[this.#config.slurp.match, this.#config.slurp.start.join('')].join(
|
|
321
|
+
'',
|
|
322
|
+
),
|
|
358
323
|
'gm',
|
|
359
324
|
);
|
|
360
|
-
config.slurpEnd = new RegExp(
|
|
361
|
-
[config.slurp.end.join(''), config.slurp.match].join(
|
|
325
|
+
this.#config.slurpEnd = new RegExp(
|
|
326
|
+
[this.#config.slurp.end.join(''), this.#config.slurp.match].join(
|
|
327
|
+
'',
|
|
328
|
+
),
|
|
362
329
|
'gm',
|
|
363
330
|
);
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
331
|
+
if (this.#config.globals.length) {
|
|
332
|
+
if (this.#config.legacy) {
|
|
333
|
+
this.#config.globalVariables = `const ${this.#config.globals
|
|
334
|
+
.map((name) => `${name}=${this.#config.vars.SCOPE}.${name}`)
|
|
335
|
+
.join(',')};`;
|
|
336
|
+
} else {
|
|
337
|
+
this.#config.globalVariables = `const {${this.#config.globals.join(',')}} = ${this.#config.vars.SCOPE};`;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
compile(content, path) {
|
|
342
|
+
const GLOBALS = this.#config.globalVariables;
|
|
343
|
+
const { SCOPE, SAFE, BUFFER, COMPONENT, ELEMENT } = this.#config.vars;
|
|
344
|
+
if (this.#config.rmWhitespace) {
|
|
369
345
|
content = String(content)
|
|
370
346
|
.replace(/[\r\n]+/g, '\n')
|
|
371
347
|
.replace(/^\s+|\s+$/gm, '');
|
|
372
348
|
}
|
|
373
349
|
content = String(content)
|
|
374
|
-
.replace(config.slurpStart, config.token.start)
|
|
375
|
-
.replace(config.slurpEnd, config.token.end);
|
|
376
|
-
let
|
|
377
|
-
|
|
378
|
-
|
|
350
|
+
.replace(this.#config.slurpStart, this.#config.token.start)
|
|
351
|
+
.replace(this.#config.slurpEnd, this.#config.token.end);
|
|
352
|
+
let OUTPUT = `${BUFFER}('`;
|
|
353
|
+
tokensMatch(this.#config.regex, content, (params, index, offset) => {
|
|
354
|
+
OUTPUT += symbols(content.slice(index, offset));
|
|
379
355
|
params.forEach((value, index) => {
|
|
380
356
|
if (value) {
|
|
381
|
-
|
|
357
|
+
OUTPUT += this.#config.formats[index](
|
|
358
|
+
value.trim(),
|
|
359
|
+
BUFFER,
|
|
360
|
+
SAFE,
|
|
361
|
+
);
|
|
382
362
|
}
|
|
383
363
|
});
|
|
384
364
|
});
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
if (config.
|
|
388
|
-
|
|
365
|
+
OUTPUT += `');`;
|
|
366
|
+
OUTPUT = `try{${OUTPUT}}catch(e){return ${BUFFER}.error(e,'${path}')}`;
|
|
367
|
+
if (this.#config.strict === false) {
|
|
368
|
+
OUTPUT = `with(${SCOPE}){${OUTPUT}}`;
|
|
369
|
+
}
|
|
370
|
+
OUTPUT = `${BUFFER}.start();${OUTPUT}return ${BUFFER}.end();`;
|
|
371
|
+
OUTPUT += `\n//# sourceURL=${path}`;
|
|
372
|
+
if (GLOBALS) {
|
|
373
|
+
OUTPUT = `${GLOBALS}\n${OUTPUT}`;
|
|
389
374
|
}
|
|
390
|
-
source = `${BUFFER}.start();${source}return ${BUFFER}.end();`;
|
|
391
|
-
source += `\n//# sourceURL=${path}`;
|
|
392
|
-
let result = null;
|
|
393
|
-
let params = [SCOPE, COMPONENT, ELEMENT, BUFFER, SAFE].concat(GLOBALS);
|
|
394
375
|
try {
|
|
395
|
-
|
|
396
|
-
result
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
376
|
+
const params = [SCOPE, COMPONENT, ELEMENT, BUFFER, SAFE];
|
|
377
|
+
const result = Function.apply(null, params.concat(OUTPUT));
|
|
378
|
+
result.source = `(function(${params.join(',')}){\n${OUTPUT}\n});`;
|
|
379
|
+
return result
|
|
380
|
+
} catch (error) {
|
|
381
|
+
error.filename = path;
|
|
382
|
+
error.source = OUTPUT;
|
|
383
|
+
throw error
|
|
401
384
|
}
|
|
402
|
-
return result
|
|
403
|
-
};
|
|
404
|
-
configure(options);
|
|
405
|
-
return {
|
|
406
|
-
configure,
|
|
407
|
-
compile,
|
|
408
385
|
}
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
const global = typeof globalThis !== 'undefined' ? globalThis : window || self;
|
|
386
|
+
}
|
|
412
387
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
388
|
+
class Cache {
|
|
389
|
+
static exports = [
|
|
390
|
+
'load',
|
|
391
|
+
'set',
|
|
392
|
+
'get',
|
|
393
|
+
'exist',
|
|
394
|
+
'clear',
|
|
395
|
+
'remove',
|
|
396
|
+
'resolve',
|
|
397
|
+
]
|
|
398
|
+
#cache = true
|
|
399
|
+
#precompiled
|
|
400
|
+
#list = {}
|
|
401
|
+
constructor(options) {
|
|
402
|
+
bindContext(this, this.constructor.exports);
|
|
403
|
+
this.configure(options);
|
|
404
|
+
}
|
|
405
|
+
get(key) {
|
|
406
|
+
if (this.#cache) {
|
|
407
|
+
return this.#list[key]
|
|
419
408
|
}
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
if (
|
|
423
|
-
|
|
409
|
+
}
|
|
410
|
+
set(key, value) {
|
|
411
|
+
if (this.#cache) {
|
|
412
|
+
this.#list[key] = value;
|
|
424
413
|
}
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
if (
|
|
428
|
-
list
|
|
414
|
+
}
|
|
415
|
+
exist(key) {
|
|
416
|
+
if (this.#cache) {
|
|
417
|
+
return this.#list.hasOwnProperty(key)
|
|
429
418
|
}
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
419
|
+
}
|
|
420
|
+
clear() {
|
|
421
|
+
Object.keys(this.#list).forEach(this.remove);
|
|
422
|
+
}
|
|
423
|
+
remove(key) {
|
|
424
|
+
delete this.#list[key];
|
|
425
|
+
}
|
|
426
|
+
resolve(key) {
|
|
427
|
+
return Promise.resolve(this.get(key))
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
load(data) {
|
|
431
|
+
if (this.#cache) {
|
|
432
|
+
Object.assign(this.#list, data || {});
|
|
434
433
|
}
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
const resolve = (key) => {
|
|
443
|
-
return Promise.resolve(get(key))
|
|
444
|
-
};
|
|
445
|
-
const configure = (options = {}) => {
|
|
446
|
-
config.enabled = options.cache;
|
|
447
|
-
config.export = options.export;
|
|
448
|
-
if (isNode() === false) {
|
|
449
|
-
load(global[config.export]);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
configure(options) {
|
|
437
|
+
this.#cache = options.cache;
|
|
438
|
+
this.#precompiled = options.precompiled;
|
|
439
|
+
if (typeof window === 'object') {
|
|
440
|
+
this.load(window[this.#precompiled]);
|
|
450
441
|
}
|
|
451
|
-
};
|
|
452
|
-
configure(options);
|
|
453
|
-
return {
|
|
454
|
-
configure,
|
|
455
|
-
load,
|
|
456
|
-
set,
|
|
457
|
-
get,
|
|
458
|
-
exist,
|
|
459
|
-
clear,
|
|
460
|
-
remove,
|
|
461
|
-
resolve,
|
|
462
442
|
}
|
|
463
|
-
}
|
|
443
|
+
}
|
|
464
444
|
|
|
465
445
|
const selfClosed = [
|
|
466
446
|
'area',
|
|
@@ -486,20 +466,24 @@ const slash = '/';
|
|
|
486
466
|
const lt = '<';
|
|
487
467
|
const gt = '>';
|
|
488
468
|
|
|
469
|
+
const eachAttribute = ([key, value]) => {
|
|
470
|
+
if (value !== null && value !== undefined) {
|
|
471
|
+
return [entities(key), [quote, entities(value), quote].join('')].join(
|
|
472
|
+
equal,
|
|
473
|
+
)
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
|
|
489
477
|
const element = (tag, attrs, content) => {
|
|
490
478
|
const result = [];
|
|
491
479
|
const hasClosedTag = selfClosed.indexOf(tag) === -1;
|
|
492
|
-
const attributes =
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
[quote, entities(value), quote].join(''),
|
|
497
|
-
].join(equal)
|
|
498
|
-
}
|
|
499
|
-
}).join(space);
|
|
480
|
+
const attributes = Object.entries(attrs ?? {})
|
|
481
|
+
.map(eachAttribute)
|
|
482
|
+
.filter((e) => e)
|
|
483
|
+
.join(space);
|
|
500
484
|
result.push([lt, tag, space, attributes, gt].join(''));
|
|
501
485
|
if (content && hasClosedTag) {
|
|
502
|
-
result.push(content
|
|
486
|
+
result.push(Array.isArray(content) ? content.join('') : content);
|
|
503
487
|
}
|
|
504
488
|
if (hasClosedTag) {
|
|
505
489
|
result.push([lt, slash, tag, gt].join(''));
|
|
@@ -507,93 +491,73 @@ const element = (tag, attrs, content) => {
|
|
|
507
491
|
return result.join('')
|
|
508
492
|
};
|
|
509
493
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
494
|
+
class TemplateError extends Error {
|
|
495
|
+
name = 'TemplateError'
|
|
496
|
+
constructor(error) {
|
|
497
|
+
super(error);
|
|
498
|
+
if (error instanceof Error) {
|
|
499
|
+
this.stack = error.stack;
|
|
500
|
+
this.filename = error.filename;
|
|
501
|
+
this.lineno = error.lineno;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
516
504
|
}
|
|
517
|
-
Object.setPrototypeOf(TemplateError.prototype, Error.prototype);
|
|
518
|
-
Object.assign(TemplateError.prototype, {
|
|
519
|
-
code: 0,
|
|
520
|
-
getCode() {
|
|
521
|
-
return this.code
|
|
522
|
-
},
|
|
523
|
-
getMessage() {
|
|
524
|
-
return this.message
|
|
525
|
-
},
|
|
526
|
-
toString() {
|
|
527
|
-
return this.getMessage()
|
|
528
|
-
},
|
|
529
|
-
});
|
|
530
505
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
*/
|
|
535
|
-
function TemplateNotFound() {
|
|
536
|
-
TemplateError.call(this);
|
|
506
|
+
class TemplateNotFound extends TemplateError {
|
|
507
|
+
name = 'TemplateNotFound'
|
|
508
|
+
code = 404
|
|
537
509
|
}
|
|
538
|
-
Object.setPrototypeOf(TemplateNotFound.prototype, TemplateError.prototype);
|
|
539
|
-
Object.assign(TemplateNotFound.prototype, { code: 404 });
|
|
540
510
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
*/
|
|
545
|
-
function TemplateSyntaxError() {
|
|
546
|
-
TemplateError.call(this);
|
|
511
|
+
class TemplateSyntaxError extends TemplateError {
|
|
512
|
+
name = 'TemplateSyntaxError'
|
|
513
|
+
code = 500
|
|
547
514
|
}
|
|
548
|
-
Object.setPrototypeOf(TemplateSyntaxError.prototype, TemplateError.prototype);
|
|
549
|
-
Object.assign(TemplateSyntaxError.prototype, { code: 500 });
|
|
550
515
|
|
|
551
|
-
|
|
516
|
+
const resolve = (list) => {
|
|
552
517
|
return Promise.all(list || [])
|
|
553
518
|
.then((list) => list.join(''))
|
|
554
519
|
.catch((e) => e)
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
function reject(error) {
|
|
558
|
-
return Promise.reject(new TemplateSyntaxError(error.message))
|
|
559
|
-
}
|
|
520
|
+
};
|
|
560
521
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
*/
|
|
565
|
-
function createBuffer() {
|
|
566
|
-
let store = [],
|
|
567
|
-
array = [];
|
|
522
|
+
const reject = (error) => {
|
|
523
|
+
return Promise.reject(new TemplateSyntaxError(error))
|
|
524
|
+
};
|
|
568
525
|
|
|
569
|
-
|
|
526
|
+
const EjsBuffer = () => {
|
|
527
|
+
let store = [];
|
|
528
|
+
let array = [];
|
|
529
|
+
/**
|
|
530
|
+
*
|
|
531
|
+
* @param value
|
|
532
|
+
* @constructor
|
|
533
|
+
*/
|
|
534
|
+
const EjsBuffer = (value) => {
|
|
570
535
|
array.push(value);
|
|
571
536
|
};
|
|
572
|
-
|
|
573
|
-
buffer.start = () => {
|
|
537
|
+
EjsBuffer.start = () => {
|
|
574
538
|
array = [];
|
|
575
539
|
};
|
|
576
|
-
|
|
540
|
+
EjsBuffer.backup = () => {
|
|
577
541
|
store.push(array.concat());
|
|
578
542
|
array = [];
|
|
579
543
|
};
|
|
580
|
-
|
|
544
|
+
EjsBuffer.restore = () => {
|
|
581
545
|
const result = array.concat();
|
|
582
546
|
array = store.pop();
|
|
583
547
|
return resolve(result)
|
|
584
548
|
};
|
|
585
|
-
|
|
549
|
+
EjsBuffer.error = (e, filename) => {
|
|
586
550
|
return reject(e)
|
|
587
551
|
};
|
|
588
|
-
|
|
552
|
+
EjsBuffer.end = () => {
|
|
589
553
|
return resolve(array)
|
|
590
554
|
};
|
|
591
|
-
return
|
|
592
|
-
}
|
|
555
|
+
return EjsBuffer
|
|
556
|
+
};
|
|
593
557
|
|
|
594
|
-
const PARENT = Symbol('
|
|
558
|
+
const PARENT = Symbol('EjsContext.parentTemplate');
|
|
595
559
|
|
|
596
|
-
const
|
|
560
|
+
const createContext$1 = (config, methods) => {
|
|
597
561
|
const {
|
|
598
562
|
BLOCKS,
|
|
599
563
|
MACRO,
|
|
@@ -605,17 +569,8 @@ const createContextScope = (config, methods) => {
|
|
|
605
569
|
COMPONENT,
|
|
606
570
|
ELEMENT,
|
|
607
571
|
} = config.vars;
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
* @type {symbol}
|
|
611
|
-
*/
|
|
612
|
-
|
|
613
|
-
/**
|
|
614
|
-
* @name ContextScope
|
|
615
|
-
* @param data
|
|
616
|
-
* @constructor
|
|
617
|
-
*/
|
|
618
|
-
function ContextScope(data) {
|
|
572
|
+
const globals = config.globals || [];
|
|
573
|
+
function EjsContext(data) {
|
|
619
574
|
this[PARENT] = null;
|
|
620
575
|
this[BLOCKS] = {};
|
|
621
576
|
this[MACRO] = {};
|
|
@@ -624,32 +579,36 @@ const createContextScope = (config, methods) => {
|
|
|
624
579
|
omit(data, [SCOPE, BUFFER, SAFE, COMPONENT, ELEMENT]),
|
|
625
580
|
);
|
|
626
581
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
582
|
+
Object.entries(methods).forEach(([name, value]) => {
|
|
583
|
+
if (isFunction(value) && globals.includes(name)) {
|
|
584
|
+
value = value.bind(EjsContext.prototype);
|
|
585
|
+
}
|
|
586
|
+
EjsContext.prototype[name] = value;
|
|
631
587
|
});
|
|
632
|
-
Object.defineProperty(
|
|
588
|
+
Object.defineProperty(EjsContext.prototype, BUFFER, {
|
|
589
|
+
value: EjsBuffer(),
|
|
590
|
+
});
|
|
591
|
+
Object.defineProperty(EjsContext.prototype, BLOCKS, {
|
|
633
592
|
value: {},
|
|
634
593
|
writable: true,
|
|
635
594
|
});
|
|
636
|
-
Object.defineProperty(
|
|
595
|
+
Object.defineProperty(EjsContext.prototype, MACRO, {
|
|
637
596
|
value: {},
|
|
638
597
|
writable: true,
|
|
639
598
|
});
|
|
640
|
-
Object.defineProperty(
|
|
599
|
+
Object.defineProperty(EjsContext.prototype, LAYOUT, {
|
|
641
600
|
value: false,
|
|
642
601
|
writable: true,
|
|
643
602
|
});
|
|
644
|
-
Object.defineProperty(
|
|
603
|
+
Object.defineProperty(EjsContext.prototype, EXTEND, {
|
|
645
604
|
value: false,
|
|
646
605
|
writable: true,
|
|
647
606
|
});
|
|
648
|
-
Object.defineProperty(
|
|
607
|
+
Object.defineProperty(EjsContext.prototype, PARENT, {
|
|
649
608
|
value: null,
|
|
650
609
|
writable: true,
|
|
651
610
|
});
|
|
652
|
-
Object.defineProperties(
|
|
611
|
+
Object.defineProperties(EjsContext.prototype, {
|
|
653
612
|
/** @type {function} */
|
|
654
613
|
setParentTemplate: {
|
|
655
614
|
value(value) {
|
|
@@ -691,16 +650,16 @@ const createContextScope = (config, methods) => {
|
|
|
691
650
|
}
|
|
692
651
|
},
|
|
693
652
|
},
|
|
694
|
-
/** @type {
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
return this[
|
|
653
|
+
/** @type {function} */
|
|
654
|
+
useBuffer: {
|
|
655
|
+
get() {
|
|
656
|
+
return this[BUFFER]
|
|
698
657
|
},
|
|
699
658
|
},
|
|
700
659
|
/** @type {function} */
|
|
701
|
-
|
|
660
|
+
getMacro: {
|
|
702
661
|
value() {
|
|
703
|
-
return this[
|
|
662
|
+
return this[MACRO]
|
|
704
663
|
},
|
|
705
664
|
},
|
|
706
665
|
/** @type {function} */
|
|
@@ -754,22 +713,18 @@ const createContextScope = (config, methods) => {
|
|
|
754
713
|
},
|
|
755
714
|
/** @type {function} */
|
|
756
715
|
echo: {
|
|
757
|
-
value(
|
|
758
|
-
|
|
759
|
-
const params = [].slice.call(arguments);
|
|
760
|
-
params.forEach(buffer);
|
|
716
|
+
value() {
|
|
717
|
+
return [].slice.call(arguments).forEach(this.useBuffer)
|
|
761
718
|
},
|
|
762
719
|
},
|
|
763
720
|
/** @type {function} */
|
|
764
721
|
fn: {
|
|
765
722
|
value(callback) {
|
|
766
|
-
|
|
767
|
-
const context = this;
|
|
768
|
-
return function () {
|
|
723
|
+
return () => {
|
|
769
724
|
if (isFunction(callback)) {
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
return
|
|
725
|
+
this.useBuffer.backup();
|
|
726
|
+
this.useBuffer(callback.apply(this, arguments));
|
|
727
|
+
return this.useBuffer.restore()
|
|
773
728
|
}
|
|
774
729
|
}
|
|
775
730
|
},
|
|
@@ -804,20 +759,18 @@ const createContextScope = (config, methods) => {
|
|
|
804
759
|
blocks[name].push(this.fn(callback));
|
|
805
760
|
if (this.getExtend()) return
|
|
806
761
|
const list = Object.assign([], blocks[name]);
|
|
807
|
-
const
|
|
808
|
-
return list.shift()
|
|
809
|
-
};
|
|
762
|
+
const shift = () => list.shift();
|
|
810
763
|
const next = () => {
|
|
811
|
-
const parent =
|
|
764
|
+
const parent = shift();
|
|
812
765
|
if (parent) {
|
|
813
766
|
return () => {
|
|
814
767
|
this.echo(parent(next()));
|
|
815
768
|
}
|
|
816
769
|
} else {
|
|
817
|
-
return
|
|
770
|
+
return () => {}
|
|
818
771
|
}
|
|
819
772
|
};
|
|
820
|
-
this.echo(
|
|
773
|
+
this.echo(shift()(next()));
|
|
821
774
|
},
|
|
822
775
|
},
|
|
823
776
|
/** @type {function} */
|
|
@@ -830,7 +783,7 @@ const createContextScope = (config, methods) => {
|
|
|
830
783
|
include: {
|
|
831
784
|
value(path, data, cx) {
|
|
832
785
|
const context = cx === false ? {} : this.clone(true);
|
|
833
|
-
const params =
|
|
786
|
+
const params = Object.assign(context, data || {});
|
|
834
787
|
const promise = this.render(path, params);
|
|
835
788
|
this.echo(promise);
|
|
836
789
|
},
|
|
@@ -839,9 +792,9 @@ const createContextScope = (config, methods) => {
|
|
|
839
792
|
use: {
|
|
840
793
|
value(path, namespace) {
|
|
841
794
|
this.echo(
|
|
842
|
-
Promise.resolve(this.require(path)).then((exports) => {
|
|
795
|
+
Promise.resolve(this.require(path)).then((exports$1) => {
|
|
843
796
|
const list = this.getMacro();
|
|
844
|
-
each(exports,
|
|
797
|
+
each(exports$1, (macro, name) => {
|
|
845
798
|
list[[namespace, name].join('.')] = macro;
|
|
846
799
|
});
|
|
847
800
|
}),
|
|
@@ -877,7 +830,7 @@ const createContextScope = (config, methods) => {
|
|
|
877
830
|
},
|
|
878
831
|
/** @type {function} */
|
|
879
832
|
each: {
|
|
880
|
-
value
|
|
833
|
+
value(object, callback) {
|
|
881
834
|
if (isString(object)) {
|
|
882
835
|
object = this.get(object, []);
|
|
883
836
|
}
|
|
@@ -903,127 +856,126 @@ const createContextScope = (config, methods) => {
|
|
|
903
856
|
writable: true,
|
|
904
857
|
},
|
|
905
858
|
});
|
|
906
|
-
return
|
|
859
|
+
return EjsContext
|
|
907
860
|
};
|
|
908
861
|
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
*/
|
|
916
|
-
const create = (data) => {
|
|
917
|
-
return new config.Scope(data)
|
|
918
|
-
};
|
|
919
|
-
const helpers = (methods) => {
|
|
920
|
-
extend(config.Scope.prototype, methods || {});
|
|
921
|
-
};
|
|
922
|
-
const configure = (options, methods) => {
|
|
923
|
-
config.Scope = createContextScope(options, methods);
|
|
924
|
-
};
|
|
925
|
-
configure(options, methods);
|
|
926
|
-
return {
|
|
927
|
-
configure,
|
|
928
|
-
create,
|
|
929
|
-
helpers,
|
|
862
|
+
class Context {
|
|
863
|
+
#context
|
|
864
|
+
static exports = ['create', 'globals', 'helpers']
|
|
865
|
+
constructor(options, methods) {
|
|
866
|
+
bindContext(this, this.constructor.exports);
|
|
867
|
+
this.configure(options, methods);
|
|
930
868
|
}
|
|
931
|
-
|
|
869
|
+
create(data) {
|
|
870
|
+
return new this.#context(data)
|
|
871
|
+
}
|
|
872
|
+
helpers(methods) {
|
|
873
|
+
Object.assign(this.#context.prototype, methods);
|
|
874
|
+
}
|
|
875
|
+
configure(options, methods) {
|
|
876
|
+
this.#context = createContext$1(options, methods);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
932
879
|
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
}
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
880
|
+
class EjsInstance {
|
|
881
|
+
#cache
|
|
882
|
+
#context
|
|
883
|
+
#compiler
|
|
884
|
+
#template
|
|
885
|
+
#config = {}
|
|
886
|
+
#methods = {}
|
|
887
|
+
static exports = [
|
|
888
|
+
'configure',
|
|
889
|
+
'create',
|
|
890
|
+
'createContext',
|
|
891
|
+
'render',
|
|
892
|
+
'require',
|
|
893
|
+
'preload',
|
|
894
|
+
'compile',
|
|
895
|
+
'helpers',
|
|
896
|
+
]
|
|
897
|
+
constructor(options = {}) {
|
|
898
|
+
bindContext(this, this.constructor.exports);
|
|
899
|
+
this.#methods = {};
|
|
900
|
+
this.#config = configSchema({}, options);
|
|
901
|
+
this.#context = new Context(this.#config, this.#methods);
|
|
902
|
+
this.#compiler = new Compiler(this.#config);
|
|
903
|
+
this.#cache = new Cache(this.#config);
|
|
904
|
+
this.#template = new Template(this.#config, this.#cache, this.#compiler);
|
|
905
|
+
this.helpers({ render: this.render, require: this.require });
|
|
906
|
+
}
|
|
907
|
+
create(options) {
|
|
908
|
+
return new this.constructor(options)
|
|
909
|
+
}
|
|
910
|
+
configure(options) {
|
|
911
|
+
if (options) {
|
|
912
|
+
configSchema(this.#config, options);
|
|
913
|
+
this.#context.configure(this.#config, this.#methods);
|
|
914
|
+
this.#compiler.configure(this.#config);
|
|
915
|
+
this.#cache.configure(this.#config);
|
|
916
|
+
this.#template.configure(this.#config);
|
|
917
|
+
}
|
|
918
|
+
return this.#config
|
|
919
|
+
}
|
|
920
|
+
createContext(data) {
|
|
921
|
+
return this.#context.create(data)
|
|
922
|
+
}
|
|
923
|
+
preload(list) {
|
|
924
|
+
return this.#cache.load(list || {})
|
|
925
|
+
}
|
|
926
|
+
compile(content, path) {
|
|
927
|
+
return this.#compiler.compile(content, path)
|
|
928
|
+
}
|
|
929
|
+
helpers(methods) {
|
|
930
|
+
this.#context.helpers(Object.assign(this.#methods, methods));
|
|
931
|
+
}
|
|
932
|
+
async render(name, params) {
|
|
933
|
+
const data = this.createContext(params);
|
|
934
|
+
return this.#output(this.#path(name), data).then(
|
|
935
|
+
this.#outputContent(name, data),
|
|
936
|
+
)
|
|
937
|
+
}
|
|
938
|
+
async require(name) {
|
|
939
|
+
const data = this.createContext({});
|
|
940
|
+
return this.#output(this.#path(name), data).then(() => data.getMacro())
|
|
941
|
+
}
|
|
942
|
+
#path(name) {
|
|
943
|
+
const ext = name.split('.').pop();
|
|
944
|
+
if (ext !== this.#config.extension) {
|
|
945
|
+
name = [name, this.#config.extension].join('.');
|
|
946
|
+
}
|
|
947
|
+
return name
|
|
948
|
+
}
|
|
949
|
+
#output(path, data) {
|
|
950
|
+
return this.#template
|
|
951
|
+
.get(path)
|
|
952
|
+
.then((callback) =>
|
|
953
|
+
callback.apply(data, [
|
|
954
|
+
data,
|
|
955
|
+
data.useComponent,
|
|
956
|
+
data.useElement,
|
|
957
|
+
data.useBuffer,
|
|
958
|
+
data.useSafeValue,
|
|
959
|
+
]),
|
|
960
|
+
)
|
|
961
|
+
}
|
|
962
|
+
#renderLayout(name, params, parentTemplate) {
|
|
963
|
+
const data = this.createContext(params);
|
|
964
|
+
if (parentTemplate) data.setParentTemplate(parentTemplate);
|
|
965
|
+
return this.#output(this.#path(name), data).then(
|
|
966
|
+
this.#outputContent(name, data),
|
|
967
|
+
)
|
|
968
|
+
}
|
|
969
|
+
#outputContent(name, data) {
|
|
960
970
|
return (content) => {
|
|
961
|
-
if (
|
|
962
|
-
|
|
963
|
-
return renderLayout(
|
|
971
|
+
if (data.getExtend()) {
|
|
972
|
+
data.setExtend(false);
|
|
973
|
+
return this.#renderLayout(data.getLayout(), data, name)
|
|
964
974
|
}
|
|
965
975
|
return content
|
|
966
976
|
}
|
|
967
|
-
};
|
|
968
|
-
const renderLayout = (name, data, parent) => {
|
|
969
|
-
const scope = createContext(data);
|
|
970
|
-
if (parent) scope.setParentTemplate(parent);
|
|
971
|
-
return output(filePath(name), scope).then(outputContent(name, scope))
|
|
972
|
-
};
|
|
973
|
-
const helpers = (extendMethods) => {
|
|
974
|
-
context.helpers(extend(methods, extendMethods));
|
|
975
|
-
};
|
|
976
|
-
const createContext = (data) => {
|
|
977
|
-
return context.create(data)
|
|
978
|
-
};
|
|
979
|
-
const compile = (content, path) => {
|
|
980
|
-
return compiler.compile(content, path)
|
|
981
|
-
};
|
|
982
|
-
const preload = (list) => {
|
|
983
|
-
return cache.load(list || {})
|
|
984
|
-
};
|
|
985
|
-
const create = (config) => {
|
|
986
|
-
return EJS(config)
|
|
987
|
-
};
|
|
988
|
-
const output = (path, scope) => {
|
|
989
|
-
const params = [
|
|
990
|
-
scope,
|
|
991
|
-
scope.useComponent,
|
|
992
|
-
scope.useElement,
|
|
993
|
-
scope.getBuffer(),
|
|
994
|
-
scope.useSafeValue,
|
|
995
|
-
];
|
|
996
|
-
const globals = config.globalHelpers
|
|
997
|
-
.filter((name) => isFunction(scope[name]))
|
|
998
|
-
.map((name) => scope[name].bind(scope));
|
|
999
|
-
return template
|
|
1000
|
-
.get(path)
|
|
1001
|
-
.then((callback) => callback.apply(scope, params.concat(globals)))
|
|
1002
|
-
};
|
|
1003
|
-
helpers({ render, require });
|
|
1004
|
-
return {
|
|
1005
|
-
configure,
|
|
1006
|
-
create,
|
|
1007
|
-
createContext,
|
|
1008
|
-
render,
|
|
1009
|
-
require,
|
|
1010
|
-
preload,
|
|
1011
|
-
compile,
|
|
1012
|
-
helpers,
|
|
1013
977
|
}
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
const readFile = (path, template) => {
|
|
1017
|
-
return new Promise((resolve, reject) => {
|
|
1018
|
-
fs.readFile(joinPath(path, template), (error, data) => {
|
|
1019
|
-
if (error) {
|
|
1020
|
-
reject(new TemplateError());
|
|
1021
|
-
} else {
|
|
1022
|
-
resolve(data.toString());
|
|
1023
|
-
}
|
|
1024
|
-
});
|
|
1025
|
-
})
|
|
1026
|
-
};
|
|
978
|
+
}
|
|
1027
979
|
|
|
1028
980
|
/**
|
|
1029
981
|
*
|
|
@@ -1038,14 +990,14 @@ const expressRenderer = (configure, render) => {
|
|
|
1038
990
|
options = {};
|
|
1039
991
|
}
|
|
1040
992
|
options = options || {};
|
|
1041
|
-
const settings =
|
|
1042
|
-
const viewPath = typeProp(isString,
|
|
993
|
+
const settings = Object.assign({}, options.settings);
|
|
994
|
+
const viewPath = typeProp(isString, ejsDefaults.path, settings['views']);
|
|
1043
995
|
const viewCache = typeProp(
|
|
1044
996
|
isBoolean,
|
|
1045
|
-
|
|
997
|
+
ejsDefaults.cache,
|
|
1046
998
|
settings['view cache'],
|
|
1047
999
|
);
|
|
1048
|
-
const viewOptions =
|
|
1000
|
+
const viewOptions = Object.assign({}, settings['view options']);
|
|
1049
1001
|
const filename = path.relative(viewPath, name);
|
|
1050
1002
|
viewOptions.path = viewPath;
|
|
1051
1003
|
viewOptions.cache = viewCache;
|
|
@@ -1060,6 +1012,13 @@ const expressRenderer = (configure, render) => {
|
|
|
1060
1012
|
}
|
|
1061
1013
|
};
|
|
1062
1014
|
|
|
1015
|
+
const readFile = (path, template) => {
|
|
1016
|
+
return fs
|
|
1017
|
+
.readFile(joinPath(path, template))
|
|
1018
|
+
.then((contents) => contents.toString())
|
|
1019
|
+
.then((text) => String(text))
|
|
1020
|
+
};
|
|
1021
|
+
|
|
1063
1022
|
const {
|
|
1064
1023
|
render,
|
|
1065
1024
|
createContext,
|
|
@@ -1068,7 +1027,7 @@ const {
|
|
|
1068
1027
|
preload,
|
|
1069
1028
|
configure,
|
|
1070
1029
|
create,
|
|
1071
|
-
} =
|
|
1030
|
+
} = new EjsInstance({
|
|
1072
1031
|
resolver: readFile,
|
|
1073
1032
|
});
|
|
1074
1033
|
|