@kosatyi/ejs 0.0.97 → 0.0.99

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.
@@ -57,13 +57,22 @@ const symbols = (string) => {
57
57
 
58
58
  const safeValue = (value, escape) => {
59
59
  const check = value;
60
- return check == null ? '' : Boolean(escape) === true ? entities(check) : check
60
+ return check == null
61
+ ? ''
62
+ : Boolean(escape) === true
63
+ ? entities(check)
64
+ : check
61
65
  };
62
66
 
63
67
  const instanceOf = (object, instance) => {
64
68
  return Boolean(object instanceof instance)
65
69
  };
66
70
 
71
+ const assertInstanceOf = (object, instance) => {
72
+ if (instanceOf(object, instance) === false)
73
+ throw new TypeError(`${object} in not instance of ${instance}`)
74
+ };
75
+
67
76
  const getPath = (context, name, strict) => {
68
77
  let data = context;
69
78
  let chunks = String(name).split('.');
@@ -85,6 +94,14 @@ const getPath = (context, name, strict) => {
85
94
  return [data, prop]
86
95
  };
87
96
 
97
+ const bindContext = (object, methods = []) => {
98
+ methods.forEach((name) => {
99
+ if (name in object) {
100
+ object[name] = object[name].bind(object);
101
+ }
102
+ });
103
+ };
104
+
88
105
  const ext = (path, defaults) => {
89
106
  const ext = path.split('.').pop();
90
107
  if (ext !== defaults) {
@@ -152,10 +169,28 @@ const omit = (object, list) => {
152
169
  })
153
170
  };
154
171
 
172
+ /**
173
+ *
174
+ * @param object
175
+ * @param prop
176
+ * @return {boolean}
177
+ */
155
178
  const hasProp = (object, prop) => {
156
179
  return object && object.hasOwnProperty(prop)
157
180
  };
158
181
 
182
+ const matchTokens = (regex, text, callback) => {
183
+ let index = 0;
184
+ text.replace(regex, function () {
185
+ const params = [].slice.call(arguments, 0, -1);
186
+ const offset = params.pop();
187
+ const match = params.shift();
188
+ callback(params, index, offset);
189
+ index = offset + match.length;
190
+ return match
191
+ });
192
+ };
193
+
159
194
  const defaults = {};
160
195
 
161
196
  defaults.export = 'ejsPrecompiled';
@@ -174,6 +209,7 @@ defaults.globalHelpers = [];
174
209
  defaults.vars = {
175
210
  SCOPE: 'ejs',
176
211
  COMPONENT: 'ui',
212
+ ELEMENT: 'el',
177
213
  EXTEND: '$$e',
178
214
  BUFFER: '$$a',
179
215
  LAYOUT: '$$l',
@@ -234,159 +270,146 @@ const configSchema = (config, options) => {
234
270
 
235
271
  const global = typeof globalThis !== 'undefined' ? globalThis : window || self;
236
272
 
237
- function Cache(config) {
238
- if (instanceOf(this, Cache) === false) return new Cache()
239
- const cache = {
240
- enabled: true,
241
- list: {},
242
- };
243
- this.configure = function (config) {
244
- cache.enabled = config.cache;
245
- if (isNode() === false) {
246
- this.load(global[config.export]);
247
- }
248
- };
249
- this.clear = function () {
250
- cache.list = {};
251
- };
252
- this.load = function (data) {
253
- if (cache.enabled) {
254
- extend(cache.list, data || {});
273
+ class Cache {
274
+ #enabled = true
275
+ #list = {}
276
+ constructor(config) {
277
+ this.configure(config);
278
+ }
279
+ load(data) {
280
+ if (this.#enabled) {
281
+ extend(this.#list, data || {});
255
282
  }
256
- return this
257
- };
258
- this.get = function (key) {
259
- if (cache.enabled) {
260
- return cache.list[key]
283
+ }
284
+ get(key) {
285
+ if (this.#enabled) {
286
+ return this.#list[key]
261
287
  }
262
- };
263
- this.set = function (key, value) {
264
- if (cache.enabled) {
265
- cache.list[key] = value;
288
+ }
289
+ set(key, value) {
290
+ if (this.#enabled) {
291
+ this.#list[key] = value;
266
292
  }
267
- return this
268
- };
269
- this.resolve = function (key) {
293
+ }
294
+ exist(key) {
295
+ return hasProp(this.#list, key)
296
+ }
297
+ clear() {
298
+ this.#list = {};
299
+ }
300
+ remove(key) {
301
+ delete this.#list[key];
302
+ }
303
+ resolve(key) {
270
304
  return Promise.resolve(this.get(key))
271
- };
272
- this.remove = function (key) {
273
- delete cache.list[key];
274
- };
275
- this.exist = function (key) {
276
- return hasProp(cache.list, key)
277
- };
305
+ }
306
+ configure(config) {
307
+ this.#enabled = config.cache;
308
+ if (isNode() === false) {
309
+ this.load(global[config.export]);
310
+ }
311
+ }
278
312
  }
279
313
 
280
- const tagList = [
281
- {
282
- symbol: '-',
283
- format(value) {
284
- return `')\n${this.BUFFER}(${this.SAFE}(${value},1))\n${this.BUFFER}('`
314
+ class Compiler {
315
+ #config = {}
316
+ #symbols = [
317
+ {
318
+ symbol: '-',
319
+ format(value) {
320
+ return `')\n${this.BUFFER}(${this.SAFE}(${value},1))\n${this.BUFFER}('`
321
+ },
285
322
  },
286
- },
287
- {
288
- symbol: '=',
289
- format(value) {
290
- return `')\n${this.BUFFER}(${this.SAFE}(${value}))\n${this.BUFFER}('`
323
+ {
324
+ symbol: '=',
325
+ format(value) {
326
+ return `')\n${this.BUFFER}(${this.SAFE}(${value}))\n${this.BUFFER}('`
327
+ },
291
328
  },
292
- },
293
- {
294
- symbol: '#',
295
- format(value) {
296
- return `')\n/**${value}**/\n${this.BUFFER}('`
329
+ {
330
+ symbol: '#',
331
+ format(value) {
332
+ return `')\n/**${value}**/\n${this.BUFFER}('`
333
+ },
297
334
  },
298
- },
299
- {
300
- symbol: '',
301
- format(value) {
302
- return `')\n${value.trim()}\n${this.BUFFER}('`
335
+ {
336
+ symbol: '',
337
+ format(value) {
338
+ return `')\n${value.trim()}\n${this.BUFFER}('`
339
+ },
303
340
  },
304
- },
305
- ];
306
-
307
- function matchTokens(regex, text, callback) {
308
- let index = 0;
309
- text.replace(regex, function () {
310
- const params = [].slice.call(arguments, 0, -1);
311
- const offset = params.pop();
312
- const match = params.shift();
313
- callback(params, index, offset);
314
- index = offset + match.length;
315
- return match
316
- });
317
- }
318
-
319
- function Compiler(config) {
320
- if (instanceOf(this, Compiler) === false) return new Compiler(config)
321
-
322
- const compiler = {};
323
-
324
- this.configure = function (config) {
325
- compiler.withObject = config.withObject;
326
- compiler.rmWhitespace = config.rmWhitespace;
327
- compiler.token = config.token;
328
- compiler.vars = config.vars;
329
- compiler.globalHelpers = config.globalHelpers;
330
- compiler.matches = [];
331
- compiler.formats = [];
332
- compiler.slurp = {
333
- match: '[\s\t\n]*',
334
- start: [compiler.token.start, '_'],
335
- end: ['_', compiler.token.end],
341
+ ]
342
+ constructor(config) {
343
+ this.configure(config);
344
+ }
345
+ configure(config) {
346
+ this.#config.withObject = config.withObject;
347
+ this.#config.rmWhitespace = config.rmWhitespace;
348
+ this.#config.token = config.token;
349
+ this.#config.vars = config.vars;
350
+ this.#config.globalHelpers = config.globalHelpers;
351
+ this.#config.matches = [];
352
+ this.#config.formats = [];
353
+ this.#config.slurp = {
354
+ match: '[s\t\n]*',
355
+ start: [this.#config.token.start, '_'],
356
+ end: ['_', this.#config.token.end],
336
357
  };
337
- tagList.forEach((item) => {
338
- compiler.matches.push(
339
- compiler.token.start
358
+ this.#symbols.forEach((item) => {
359
+ this.#config.matches.push(
360
+ this.#config.token.start
340
361
  .concat(item.symbol)
341
- .concat(compiler.token.regex)
342
- .concat(compiler.token.end)
362
+ .concat(this.#config.token.regex)
363
+ .concat(this.#config.token.end)
343
364
  );
344
- compiler.formats.push(item.format.bind(compiler.vars));
365
+ this.#config.formats.push(item.format.bind(this.#config.vars));
345
366
  });
346
- compiler.regex = new RegExp(
347
- compiler.matches.join('|').concat('|$'),
367
+ this.#config.regex = new RegExp(
368
+ this.#config.matches.join('|').concat('|$'),
348
369
  'g'
349
370
  );
350
- compiler.slurpStart = new RegExp(
351
- [compiler.slurp.match, compiler.slurp.start.join('')].join(''),
371
+ this.#config.slurpStart = new RegExp(
372
+ [this.#config.slurp.match, this.#config.slurp.start.join('')].join(
373
+ ''
374
+ ),
352
375
  'gm'
353
376
  );
354
- compiler.slurpEnd = new RegExp(
355
- [compiler.slurp.end.join(''), compiler.slurp.match].join(''),
377
+ this.#config.slurpEnd = new RegExp(
378
+ [this.#config.slurp.end.join(''), this.#config.slurp.match].join(
379
+ ''
380
+ ),
356
381
  'gm'
357
382
  );
358
- };
359
-
360
- this.compile = function (content, path) {
361
- const { SCOPE, SAFE, BUFFER, COMPONENT } = compiler.vars;
362
- const GLOBALS = compiler.globalHelpers;
363
- content = String(content);
364
- if (compiler.rmWhitespace) {
365
- content = content
383
+ }
384
+ compile(content, path) {
385
+ const { SCOPE, SAFE, BUFFER, COMPONENT, ELEMENT } = this.#config.vars;
386
+ const GLOBALS = this.#config.globalHelpers;
387
+ if (this.#config.rmWhitespace) {
388
+ content = String(content)
366
389
  .replace(/[\r\n]+/g, '\n')
367
390
  .replace(/^\s+|\s+$/gm, '');
368
391
  }
369
- content = content
370
- .replace(compiler.slurpStart, compiler.token.start)
371
- .replace(compiler.slurpEnd, compiler.token.end);
392
+ content = String(content)
393
+ .replace(this.#config.slurpStart, this.#config.token.start)
394
+ .replace(this.#config.slurpEnd, this.#config.token.end);
372
395
  let source = `${BUFFER}('`;
373
- matchTokens(compiler.regex, content, (params, index, offset) => {
396
+ matchTokens(this.#config.regex, content, (params, index, offset) => {
374
397
  source += symbols(content.slice(index, offset));
375
398
  params.forEach((value, index) => {
376
399
  if (value) {
377
- source += compiler.formats[index](value);
400
+ source += this.#config.formats[index](value);
378
401
  }
379
402
  });
380
403
  });
381
404
  source += `');`;
382
405
  source = `try{${source}}catch(e){return ${BUFFER}.error(e)}`;
383
- if (compiler.withObject) {
406
+ if (this.#config.withObject) {
384
407
  source = `with(${SCOPE}){${source}}`;
385
408
  }
386
409
  source = `${BUFFER}.start();${source}return ${BUFFER}.end();`;
387
410
  source += `\n//# sourceURL=${path}`;
388
411
  let result = null;
389
- let params = [SCOPE, COMPONENT, BUFFER, SAFE].concat(GLOBALS);
412
+ let params = [SCOPE, BUFFER, SAFE, COMPONENT, ELEMENT].concat(GLOBALS);
390
413
  try {
391
414
  result = Function.apply(null, params.concat(source));
392
415
  result.source = `(function(${params.join(',')}){\n${source}\n});`;
@@ -396,57 +419,49 @@ function Compiler(config) {
396
419
  throw e
397
420
  }
398
421
  return result
399
- };
400
-
401
- this.configure(config);
422
+ }
402
423
  }
403
424
 
404
- function Template(config, cache, compiler) {
405
- if (instanceOf(this, Template) === false)
406
- return new Template(config, cache, compiler)
407
-
408
- if (instanceOf(cache, Cache) === false)
409
- throw new TypeError('cache is not instance of Cache')
410
-
411
- if (instanceOf(compiler, Compiler) === false)
412
- throw new TypeError('compiler is not instance of Compiler')
413
-
414
- const template = {};
415
-
416
- const result = (template, content) => {
417
- cache.set(template, content);
425
+ class Template {
426
+ #path
427
+ #cache
428
+ #compiler
429
+ #resolver
430
+ constructor(config, cache, compiler) {
431
+ assertInstanceOf(cache, Cache);
432
+ assertInstanceOf(compiler, Compiler);
433
+ this.#cache = cache;
434
+ this.#compiler = compiler;
435
+ this.configure(config);
436
+ }
437
+ #resolve(path) {
438
+ return this.#resolver(this.#path, path)
439
+ }
440
+ #result(template, content) {
441
+ this.#cache.set(template, content);
418
442
  return content
419
- };
420
-
421
- const resolve = (path) => {
422
- return template.resolver(template.path, path)
423
- };
424
-
425
- const compile = (content, template) => {
443
+ }
444
+ #compile(content, template) {
426
445
  if (isFunction(content)) {
427
446
  return content
428
447
  } else {
429
- return compiler.compile(content, template)
448
+ return this.#compiler.compile(content, template)
430
449
  }
431
- };
432
-
433
- this.configure = function (config) {
434
- template.path = config.path;
435
- template.cache = config.cache;
450
+ }
451
+ configure(config) {
452
+ this.#path = config.path;
436
453
  if (isFunction(config.resolver)) {
437
- template.resolver = config.resolver;
454
+ this.#resolver = config.resolver;
438
455
  }
439
- };
440
-
441
- this.get = function (template) {
442
- if (cache.exist(template)) {
443
- return cache.resolve(template)
456
+ }
457
+ get(template) {
458
+ if (this.#cache.exist(template)) {
459
+ return this.#cache.resolve(template)
444
460
  }
445
- return resolve(template).then((content) =>
446
- result(template, compile(content, template))
461
+ return this.#resolve(template).then((content) =>
462
+ this.#result(template, this.#compile(content, template))
447
463
  )
448
- };
449
- this.configure(config);
464
+ }
450
465
  }
451
466
 
452
467
  const selfClosed = [
@@ -494,542 +509,473 @@ const element = (tag, attrs, content) => {
494
509
  return result.join('')
495
510
  };
496
511
 
497
- /**
498
- * @extends Error
499
- * @property code
500
- * @param {string} message
501
- * @constructor
502
- */
503
- function TemplateError(message) {
504
- this.name = 'TemplateError';
505
- this.message = message;
506
- Error.call(this);
512
+ class TemplateError extends Error {
513
+ code = 0
514
+ constructor(message) {
515
+ super();
516
+ this.message = message;
517
+ }
518
+ getCode() {
519
+ return this.code
520
+ }
521
+ getMessage() {
522
+ return this.message
523
+ }
524
+ toString() {
525
+ return this.getMessage()
526
+ }
507
527
  }
508
528
 
509
- /**
510
- *
511
- */
512
- Object.setPrototypeOf(TemplateError.prototype, Error.prototype);
513
- Object.assign(TemplateError.prototype, { code: 1 });
514
- /**
515
- *
516
- * @return {number}
517
- */
518
- TemplateError.prototype.getCode = function() {
519
- return this.code
520
- };
521
- /**
522
- *
523
- * @return {string}
524
- */
525
- TemplateError.prototype.getMessage = function() {
526
- return this.message
527
- };
528
- /**
529
- * @return {string}
530
- */
531
- TemplateError.prototype.toString = function() {
532
- return this.getMessage()
533
- };
534
-
535
- /**
536
- * @extends TemplateError
537
- * @param {string} message
538
- * @constructor
539
- */
540
- function TemplateNotFound(message) {
541
- TemplateError.call(this);
542
- this.name = 'TemplateNotFound';
543
- this.message = message;
529
+ class TemplateNotFound extends TemplateError {
530
+ code = 404
544
531
  }
545
532
 
546
- /**
547
- *
548
- */
549
- Object.setPrototypeOf(TemplateNotFound.prototype, TemplateError.prototype);
550
- Object.assign(TemplateNotFound.prototype, { code: 404 });
551
- /**
552
- * @extends TemplateError
553
- * @param {string} message
554
- * @constructor
555
- */
556
- function TemplateSyntaxError(message) {
557
- TemplateError.call(this);
558
- this.name = 'TemplateSyntaxError';
559
- this.message = message;
533
+ class TemplateSyntaxError extends TemplateError {
534
+ code = 500
560
535
  }
561
536
 
562
- /**
563
- *
564
- */
565
- Object.setPrototypeOf(TemplateSyntaxError.prototype, TemplateError.prototype);
566
- Object.assign(TemplateSyntaxError.prototype, { code: 500 });
567
-
568
537
  function resolve(list) {
569
- return Promise.all(list || []).then((list) => list.join('')).catch((e) => e)
538
+ return Promise.all(list || [])
539
+ .then((list) => list.join(''))
540
+ .catch((e) => e)
570
541
  }
571
542
 
572
543
  function reject(error) {
573
544
  return Promise.reject(new TemplateSyntaxError(error.message))
574
545
  }
575
546
 
547
+ /**
548
+ *
549
+ * @return {buffer}
550
+ */
576
551
  function createBuffer() {
577
552
  let store = [],
578
553
  array = [];
579
554
 
580
- function buffer(value) {
555
+ const buffer = (value) => {
581
556
  array.push(value);
582
- }
557
+ };
583
558
 
584
- buffer.start = function() {
559
+ buffer.start = () => {
585
560
  array = [];
586
561
  };
587
- buffer.backup = function() {
562
+ buffer.backup = () => {
588
563
  store.push(array.concat());
589
564
  array = [];
590
565
  };
591
- buffer.restore = function() {
566
+ buffer.restore = () => {
592
567
  const result = array.concat();
593
568
  array = store.pop();
594
569
  return resolve(result)
595
570
  };
596
- buffer.error = function(e) {
571
+ buffer.error = (e) => {
597
572
  return reject(e)
598
573
  };
599
- buffer.end = function() {
574
+ buffer.end = () => {
600
575
  return resolve(array)
601
576
  };
602
577
  return buffer
603
578
  }
604
579
 
605
- function Context(config) {
606
- if (instanceOf(this, Context) === false) return new Context(config)
607
- this.configure = function (config, methods) {
608
- const { BLOCKS, MACRO, EXTEND, LAYOUT, BUFFER, COMPONENT } = config.vars;
609
-
610
- this.create = function (data) {
611
- return new Scope(data)
612
- };
613
-
614
- this.helpers = function (methods) {
615
- extend(Scope.prototype, methods || {});
616
- };
617
- /**
618
- * @name ContextScope
619
- * @param data
620
- * @constructor
621
- */
622
- function Scope(data) {
623
- this[BLOCKS] = {};
624
- this[MACRO] = {};
625
- extend(this, data || {});
626
- }
627
-
628
- Scope.prototype = extend({}, methods || {});
629
- Object.defineProperties(Scope.prototype, {
630
- [BUFFER]: {
631
- value: createBuffer(),
632
- writable: true,
633
- configurable: false,
634
- enumerable: false,
635
- },
636
- [BLOCKS]: {
637
- value: {},
638
- writable: true,
639
- configurable: false,
640
- enumerable: false,
641
- },
642
- [MACRO]: {
643
- value: {},
644
- writable: true,
645
- configurable: false,
646
- enumerable: false,
647
- },
648
- [LAYOUT]: {
649
- value: false,
650
- writable: true,
651
- configurable: false,
652
- enumerable: false,
653
- },
654
- [EXTEND]: {
655
- value: false,
656
- writable: true,
657
- configurable: false,
658
- enumerable: false,
580
+ const createContextScope = (config, methods) => {
581
+ const {
582
+ BLOCKS,
583
+ MACRO,
584
+ EXTEND,
585
+ LAYOUT,
586
+ BUFFER,
587
+ SAFE,
588
+ SCOPE,
589
+ COMPONENT,
590
+ ELEMENT,
591
+ } = config.vars;
592
+ /**
593
+ * @name ContextScope
594
+ * @param data
595
+ * @constructor
596
+ */
597
+ function ContextScope(data) {
598
+ this[BLOCKS] = {};
599
+ this[MACRO] = {};
600
+ Object.assign(
601
+ this,
602
+ omit(data, [SCOPE, BUFFER, SAFE, COMPONENT, ELEMENT])
603
+ );
604
+ }
605
+ Object.assign(ContextScope.prototype, methods);
606
+ Object.defineProperties(ContextScope.prototype, {
607
+ [BUFFER]: {
608
+ value: createBuffer(),
609
+ },
610
+ [BLOCKS]: {
611
+ value: {},
612
+ writable: true,
613
+ },
614
+ [MACRO]: {
615
+ value: {},
616
+ writable: true,
617
+ },
618
+ [LAYOUT]: {
619
+ value: false,
620
+ writable: true,
621
+ },
622
+ [EXTEND]: {
623
+ value: false,
624
+ writable: true,
625
+ },
626
+ /** @type {function} */
627
+ useSafeValue: {
628
+ get: () => safeValue,
629
+ },
630
+ /** @type {function} */
631
+ useComponent: {
632
+ get() {
633
+ if (isFunction(this[COMPONENT])) {
634
+ return this[COMPONENT].bind(this)
635
+ } else {
636
+ return () => {
637
+ throw new Error(`${COMPONENT} must be a function`)
638
+ }
639
+ }
659
640
  },
660
- getMacro: {
661
- value() {
662
- return this[MACRO]
663
- },
664
- writable: false,
665
- configurable: false,
666
- enumerable: false,
641
+ },
642
+ /** @type {function} */
643
+ useElement: {
644
+ get() {
645
+ if (isFunction(this[ELEMENT])) {
646
+ return this[ELEMENT].bind(this)
647
+ } else {
648
+ return () => {
649
+ throw new Error(`${ELEMENT} must be a function`)
650
+ }
651
+ }
667
652
  },
668
- getBuffer: {
669
- value() {
670
- return this[BUFFER]
671
- },
672
- writable: false,
673
- configurable: false,
674
- enumerable: false,
653
+ },
654
+ /** @type {()=>this[MACRO]} */
655
+ getMacro: {
656
+ value() {
657
+ return this[MACRO]
675
658
  },
676
- getComponent: {
677
- value() {
678
- const context = this;
679
- if (COMPONENT in context) {
680
- return function () {
681
- return context[COMPONENT].apply(context, arguments)
682
- }
683
- }
684
- return function () {
685
- console.log('%s function not defined', COMPONENT);
686
- }
687
- },
688
- writable: false,
689
- configurable: false,
690
- enumerable: false,
659
+ },
660
+ /** @type {function} */
661
+ getBuffer: {
662
+ value() {
663
+ return this[BUFFER]
691
664
  },
692
- getBlocks: {
693
- value() {
694
- return this[BLOCKS]
695
- },
696
- writable: false,
697
- configurable: false,
698
- enumerable: false,
665
+ },
666
+ /** @type {function} */
667
+ getBlocks: {
668
+ value() {
669
+ return this[BLOCKS]
699
670
  },
700
- setExtend: {
701
- value(value) {
702
- this[EXTEND] = value;
703
- },
704
- writable: false,
705
- configurable: false,
706
- enumerable: false,
671
+ },
672
+ /** @type {function} */
673
+ setExtend: {
674
+ value(value) {
675
+ this[EXTEND] = value;
707
676
  },
708
- getExtend: {
709
- value() {
710
- return this[EXTEND]
711
- },
712
- writable: false,
713
- configurable: false,
714
- enumerable: false,
677
+ },
678
+ /** @type {function} */
679
+ getExtend: {
680
+ value() {
681
+ return this[EXTEND]
715
682
  },
716
- setLayout: {
717
- value(layout) {
718
- this[LAYOUT] = layout;
719
- },
720
- writable: false,
721
- configurable: false,
722
- enumerable: false,
683
+ },
684
+ /** @type {function} */
685
+ setLayout: {
686
+ value(layout) {
687
+ this[LAYOUT] = layout;
723
688
  },
724
- getLayout: {
725
- value() {
726
- return this[LAYOUT]
727
- },
728
- writable: false,
729
- configurable: false,
730
- enumerable: false,
689
+ },
690
+ /** @type {function} */
691
+ getLayout: {
692
+ value() {
693
+ return this[LAYOUT]
731
694
  },
732
- clone: {
733
- value(exclude_blocks) {
734
- const filter = [LAYOUT, EXTEND, BUFFER];
735
- if (exclude_blocks === true) {
736
- filter.push(BLOCKS);
737
- }
738
- return omit(this, filter)
739
- },
740
- writable: false,
741
- configurable: false,
742
- enumerable: false,
695
+ },
696
+ /** @type {function} */
697
+ clone: {
698
+ value(exclude_blocks) {
699
+ const filter = [LAYOUT, EXTEND, BUFFER];
700
+ if (exclude_blocks === true) {
701
+ filter.push(BLOCKS);
702
+ }
703
+ return omit(this, filter)
743
704
  },
744
- extend: {
745
- value(layout) {
746
- this.setExtend(true);
747
- this.setLayout(layout);
748
- },
749
- writable: false,
750
- configurable: false,
751
- enumerable: false,
705
+ },
706
+ /** @type {function} */
707
+ extend: {
708
+ value(layout) {
709
+ this.setExtend(true);
710
+ this.setLayout(layout);
752
711
  },
753
- echo: {
754
- value(layout) {
755
- const buffer = this.getBuffer();
756
- const params = [].slice.call(arguments);
757
- params.forEach(buffer);
758
- },
759
- writable: false,
760
- configurable: false,
761
- enumerable: false,
712
+ },
713
+ /** @type {function} */
714
+ echo: {
715
+ value(layout) {
716
+ const buffer = this.getBuffer();
717
+ const params = [].slice.call(arguments);
718
+ params.forEach(buffer);
762
719
  },
763
- fn: {
764
- value(callback) {
765
- const buffer = this.getBuffer();
766
- const context = this;
767
- return function () {
720
+ },
721
+ /** @type {function} */
722
+ fn: {
723
+ value(callback) {
724
+ const buffer = this.getBuffer();
725
+ const context = this;
726
+ return function () {
727
+ if (isFunction(callback)) {
768
728
  buffer.backup();
769
- if (isFunction(callback)) {
770
- callback.apply(context, arguments);
771
- }
729
+ buffer(callback.apply(context, arguments));
772
730
  return buffer.restore()
773
731
  }
774
- },
775
- writable: false,
776
- configurable: false,
777
- enumerable: false,
778
- },
779
- get: {
780
- value(name, defaults) {
781
- const path = getPath(this, name, true);
782
- const result = path.shift();
783
- const prop = path.pop();
784
- return hasProp(result, prop) ? result[prop] : defaults
785
- },
786
- writable: true,
787
- configurable: true,
788
- enumerable: false,
789
- },
790
- set: {
791
- value(name, value) {
792
- const path = getPath(this, name, false);
793
- const result = path.shift();
794
- const prop = path.pop();
795
- if (this.getExtend() && hasProp(result, prop)) {
796
- return result[prop]
797
- }
798
- return (result[prop] = value)
799
- },
800
- writable: false,
801
- configurable: false,
802
- enumerable: false,
732
+ }
803
733
  },
804
- macro: {
805
- value(name, callback) {
806
- const list = this.getMacro();
807
- const macro = this.fn(callback);
808
- const context = this;
809
- list[name] = function () {
810
- return context.echo(macro.apply(undefined, arguments))
811
- };
812
- },
813
- writable: false,
814
- configurable: false,
815
- enumerable: false,
734
+ },
735
+ /** @type {function} */
736
+ macro: {
737
+ value(name, callback) {
738
+ const list = this.getMacro();
739
+ const macro = this.fn(callback);
740
+ const context = this;
741
+ list[name] = function () {
742
+ return context.echo(macro.apply(undefined, arguments))
743
+ };
816
744
  },
817
- call: {
818
- value(name) {
819
- const list = this.getMacro();
820
- const macro = list[name];
821
- const params = [].slice.call(arguments, 1);
822
- if (isFunction(macro)) {
823
- return macro.apply(macro, params)
824
- }
825
- },
826
- writable: false,
827
- configurable: false,
828
- enumerable: false,
745
+ },
746
+ /** @type {function} */
747
+ call: {
748
+ value(name) {
749
+ const list = this.getMacro();
750
+ const macro = list[name];
751
+ const params = [].slice.call(arguments, 1);
752
+ if (isFunction(macro)) {
753
+ return macro.apply(macro, params)
754
+ }
829
755
  },
830
- block: {
831
- value(name, callback) {
832
- const blocks = this.getBlocks();
833
- blocks[name] = blocks[name] || [];
834
- blocks[name].push(this.fn(callback));
835
- if (this.getExtend()) return
836
- const list = Object.assign([], blocks[name]);
837
- const current = function () {
838
- return list.shift()
839
- };
840
- const next = () => {
841
- const parent = current();
842
- if (parent) {
843
- return () => {
844
- this.echo(parent(next()));
845
- }
846
- } else {
847
- return noop
756
+ },
757
+ /** @type {function} */
758
+ block: {
759
+ value(name, callback) {
760
+ const blocks = this.getBlocks();
761
+ blocks[name] = blocks[name] || [];
762
+ blocks[name].push(this.fn(callback));
763
+ if (this.getExtend()) return
764
+ const list = Object.assign([], blocks[name]);
765
+ const current = () => {
766
+ return list.shift()
767
+ };
768
+ const next = () => {
769
+ const parent = current();
770
+ if (parent) {
771
+ return () => {
772
+ this.echo(parent(next()));
848
773
  }
849
- };
850
- this.echo(current()(next()));
851
- },
852
- writable: false,
853
- configurable: false,
854
- enumerable: false,
774
+ } else {
775
+ return noop
776
+ }
777
+ };
778
+ this.echo(current()(next()));
855
779
  },
856
- hasBlock: {
857
- value(name) {
858
- return this.getBlocks().hasOwnProperty(name)
859
- },
860
- writable: false,
861
- configurable: false,
862
- enumerable: false,
780
+ },
781
+ /** @type {function} */
782
+ hasBlock: {
783
+ value(name) {
784
+ return this.getBlocks().hasOwnProperty(name)
863
785
  },
864
- include: {
865
- value(path, data, cx) {
866
- const context = cx === false ? {} : this.clone(true);
867
- const params = extend(context, data || {});
868
- const promise = this.render(path, params);
869
- this.echo(promise);
870
- },
871
- writable: false,
872
- configurable: false,
873
- enumerable: false,
786
+ },
787
+ /** @type {function} */
788
+ include: {
789
+ value(path, data, cx) {
790
+ const context = cx === false ? {} : this.clone(true);
791
+ const params = extend(context, data || {});
792
+ const promise = this.render(path, params);
793
+ this.echo(promise);
874
794
  },
875
- promiseResolve: {
876
- value(value, callback) {
877
- return Promise.resolve(
878
- isFunction(value) ? this.fn(value)() : value
879
- ).then(callback.bind(this))
880
- },
881
- writable: false,
882
- configurable: false,
883
- enumerable: false,
795
+ },
796
+ /** @type {function} */
797
+ use: {
798
+ value(path, namespace) {
799
+ this.echo(
800
+ Promise.resolve(this.require(path)).then((exports) => {
801
+ const list = this.getMacro();
802
+ each(exports, function (macro, name) {
803
+ list[[namespace, name].join('.')] = macro;
804
+ });
805
+ })
806
+ );
884
807
  },
885
- use: {
886
- value(path, namespace) {
887
- this.echo(
888
- this.promiseResolve(
889
- this.require(path),
890
- function (exports) {
891
- const list = this.getMacro();
892
- each(exports, function (macro, name) {
893
- list[[namespace, name].join('.')] = macro;
894
- });
895
- }
896
- )
897
- );
898
- },
899
- writable: false,
900
- configurable: false,
901
- enumerable: false,
808
+ },
809
+ /** @type {function} */
810
+ async: {
811
+ value(promise, callback) {
812
+ this.echo(Promise.resolve(promise).then(callback));
902
813
  },
903
- async: {
904
- value(promise, callback) {
905
- this.echo(
906
- this.promiseResolve(promise, function (data) {
907
- return this.fn(callback)(data)
908
- })
909
- );
910
- },
911
- writable: false,
912
- configurable: false,
913
- enumerable: false,
814
+ },
815
+ /** @type {function} */
816
+ get: {
817
+ value(name, defaults) {
818
+ const path = getPath(this, name, true);
819
+ const result = path.shift();
820
+ const prop = path.pop();
821
+ return hasProp(result, prop) ? result[prop] : defaults
914
822
  },
915
- each: {
916
- value: function (object, callback) {
917
- if (isString(object)) {
918
- object = this.get(object, []);
919
- }
920
- each(object, callback);
921
- },
922
- writable: false,
923
- configurable: false,
924
- enumerable: false,
823
+ },
824
+ /** @type {function} */
825
+ set: {
826
+ value(name, value) {
827
+ const path = getPath(this, name, false);
828
+ const result = path.shift();
829
+ const prop = path.pop();
830
+ if (this.getExtend() && hasProp(result, prop)) {
831
+ return result[prop]
832
+ }
833
+ return (result[prop] = value)
925
834
  },
926
- element: {
927
- value(tag, attr, content) {
928
- return element(tag, attr, content)
929
- },
930
- writable: false,
931
- configurable: false,
932
- enumerable: false,
835
+ },
836
+ /** @type {function} */
837
+ each: {
838
+ value: function (object, callback) {
839
+ if (isString(object)) {
840
+ object = this.get(object, []);
841
+ }
842
+ each(object, callback);
933
843
  },
934
- el: {
935
- value(tag, attr, content) {
936
- this.echo(
937
- this.promiseResolve(content, function (content) {
938
- return this.element(tag, attr, content)
939
- })
940
- );
941
- },
942
- writable: false,
943
- configurable: false,
944
- enumerable: false,
844
+ writable: true,
845
+ },
846
+ /** @type {function} */
847
+ el: {
848
+ value(tag, attr, content) {
849
+ content = isFunction(content) ? this.fn(content)() : content;
850
+ this.echo(
851
+ Promise.resolve(content).then((content) =>
852
+ element(tag, attr, content)
853
+ )
854
+ );
945
855
  },
946
- });
947
- };
948
- this.configure(config);
949
- }
950
-
951
- function EJS(options) {
952
- if (instanceOf(this, EJS) === false) return new EJS(options)
953
-
954
- const scope = {};
955
- const config = {};
956
-
957
- configSchema(config, options || {});
856
+ writable: true,
857
+ },
858
+ /** @type {function} */
859
+ ui: {
860
+ value(layout) {},
861
+ writable: true,
862
+ },
863
+ });
864
+ return ContextScope
865
+ };
958
866
 
959
- const context = new Context(config);
960
- const compiler = new Compiler(config);
961
- const cache = new Cache();
962
- const template = new Template(config, cache, compiler);
867
+ class Context {
868
+ #scope
869
+ constructor(config, methods) {
870
+ this.configure(config, methods);
871
+ }
872
+ create(data) {
873
+ return new this.#scope(data)
874
+ }
875
+ configure(config, methods) {
876
+ this.#scope = createContextScope(config, methods);
877
+ }
878
+ helpers(methods) {
879
+ extend(this.#scope.prototype, methods || {});
880
+ }
881
+ }
963
882
 
964
- const output = (path, scope) => {
965
- const { globalHelpers } = config;
883
+ class EJS {
884
+ #config = {}
885
+ #extend = {}
886
+ #context
887
+ #compiler
888
+ #cache
889
+ #template
890
+ constructor(options) {
891
+ configSchema(this.#config, options || {});
892
+ this.#context = new Context(this.#config, this.#extend);
893
+ this.#compiler = new Compiler(this.#config);
894
+ this.#cache = new Cache(this.#config);
895
+ this.#template = new Template(this.#config, this.#cache, this.#compiler);
896
+ //
897
+ bindContext(this, [
898
+ 'configure',
899
+ 'create',
900
+ 'render',
901
+ 'require',
902
+ 'context',
903
+ 'preload',
904
+ 'compile',
905
+ 'helpers',
906
+ ]);
907
+ //
908
+ this.helpers({ require: this.require, render: this.render });
909
+ }
910
+ configure(options) {
911
+ configSchema(this.#config, options || {});
912
+ this.#context.configure(this.#config, this.#extend);
913
+ this.#compiler.configure(this.#config);
914
+ this.#cache.configure(this.#config);
915
+ this.#template.configure(this.#config);
916
+ return this.#config
917
+ }
918
+ render(name, data) {
919
+ const filepath = ext(name, this.#config.extension);
920
+ const scope = this.context(data);
921
+ return this.#output(filepath, scope).then((content) => {
922
+ if (scope.getExtend()) {
923
+ scope.setExtend(false);
924
+ const layout = scope.getLayout();
925
+ const data = scope.clone();
926
+ return this.render(layout, data)
927
+ }
928
+ return content
929
+ })
930
+ }
931
+ helpers(methods) {
932
+ this.#context.helpers(extend(this.#extend, methods));
933
+ }
934
+ context(data) {
935
+ return this.#context.create(data)
936
+ }
937
+ compile(content, path) {
938
+ return this.#compiler.compile(content, path)
939
+ }
940
+ preload(list) {
941
+ return this.#cache.load(list || {})
942
+ }
943
+ create(options) {
944
+ return new this.constructor(options)
945
+ }
946
+ require(name) {
947
+ const filepath = ext(name, this.#config.extension);
948
+ const scope = this.context({});
949
+ return this.#output(filepath, scope).then(() => scope.getMacro())
950
+ }
951
+ #output(path, scope) {
952
+ const { globalHelpers } = this.#config;
966
953
  const params = [
967
954
  scope,
968
- scope.getComponent(),
969
955
  scope.getBuffer(),
970
- safeValue,
956
+ scope.useSafeValue,
957
+ scope.useComponent,
958
+ scope.useElement,
971
959
  ].concat(
972
960
  globalHelpers
973
961
  .filter((name) => isFunction(scope[name]))
974
962
  .map((name) => scope[name].bind(scope))
975
963
  );
976
- return template
964
+ return this.#template
977
965
  .get(path)
978
966
  .then((callback) => callback.apply(scope, params))
979
- };
980
-
981
- const require = (name) => {
982
- const filepath = ext(name, config.extension);
983
- const scope = context.create({});
984
- return output(filepath, scope).then(() => scope.getMacro())
985
- };
986
- const render = (name, data) => {
987
- const filepath = ext(name, config.extension);
988
- const scope = context.create(data);
989
- return output(filepath, scope).then((content) => {
990
- if (scope.getExtend()) {
991
- scope.setExtend(false);
992
- const layout = scope.getLayout();
993
- const data = scope.clone();
994
- return render(layout, data)
995
- }
996
- return content
997
- })
998
- };
999
- this.configure = function (options) {
1000
- options = options || {};
1001
- configSchema(config, options);
1002
- context.configure(config, scope);
1003
- compiler.configure(config);
1004
- cache.configure(config);
1005
- template.configure(config);
1006
- return config
1007
- };
1008
- this.render = function (name, data) {
1009
- return render(name, data)
1010
- };
1011
- this.helpers = function (methods) {
1012
- context.helpers(extend(scope, methods));
1013
- };
1014
- this.preload = function (list) {
1015
- return cache.load(list || {})
1016
- };
1017
- this.create = function (options) {
1018
- return new EJS(options)
1019
- };
1020
- this.compile = function (content, path) {
1021
- return compiler.compile(content, path)
1022
- };
1023
- this.context = function (data) {
1024
- return context.create(data)
1025
- };
1026
- this.helpers({ require, render });
1027
- return this
967
+ }
1028
968
  }
1029
969
 
1030
- const hash = Math.floor(Math.random() * 1e12).toString(36);
1031
970
  const templates = {};
1032
- const ejs = new EJS({
971
+
972
+ const getOrigin = (url, secure) => {
973
+ url = new URL(url);
974
+ url.protocol = secure ? 'https:' : 'http:';
975
+ return url.origin
976
+ };
977
+
978
+ const { render, context, helpers, configure, create } = new EJS({
1033
979
  cache: false,
1034
980
  withObject: false,
1035
981
  resolver(path, name) {
@@ -1040,24 +986,19 @@ const ejs = new EJS({
1040
986
  reject(new TemplateNotFound(`template ${name} not found`));
1041
987
  }
1042
988
  })
1043
- }
989
+ },
1044
990
  });
1045
991
 
1046
- const { render, context, helpers, configure, create } = ejs;
1047
-
1048
- const getOrigin = (url, secure) => {
1049
- url = new URL(url);
1050
- if (secure) url.protocol = 'https:';
1051
- return url.origin
1052
- };
1053
-
1054
-
992
+ /**
993
+ *
994
+ * @param list
995
+ */
1055
996
  function setTemplates(list) {
1056
997
  Object.assign(templates, list || {});
1057
998
  }
1058
999
 
1059
1000
  /**
1060
- * @typedef {Object<string,any>} HonoContext
1001
+ * @typedef {{}} HonoContext
1061
1002
  * @property {function(*):Promise<Response>} html
1062
1003
  * @property {function():Promise<Response>} notFound
1063
1004
  * @property {function(methods:{}):void} helpers
@@ -1068,24 +1009,23 @@ function setTemplates(list) {
1068
1009
 
1069
1010
  /**
1070
1011
  * @param {Object<string,any>} options
1071
- * @return {(function(c:Context, next): Promise<any>)|*}
1012
+ * @return {(function(c:HonoContext, next): Promise<any>)|*}
1072
1013
  */
1073
- function setRenderer({ version = hash, secure = true } = {}) {
1014
+ function setRenderer({ version, secure = true } = {}) {
1074
1015
  return async (c, next) => {
1075
1016
  c.data = context({});
1076
1017
  c.data.set('version', version);
1077
1018
  c.data.set('origin', getOrigin(c.req.url, secure));
1078
1019
  c.data.set('path', c.req.path);
1079
1020
  c.data.set('query', c.req.query());
1080
- c.ejs = (name, data) => render(name, Object.assign({
1081
- param: c.req.param(),
1082
- }, c.data, data));
1021
+ c.ejs = (name, data) =>
1022
+ render(name, Object.assign({ param: c.req.param() }, c.data, data));
1083
1023
  c.helpers = (methods) => helpers(methods);
1084
1024
  c.render = (name, data) => c.html(c.ejs(name, data));
1085
1025
  await next();
1086
1026
  }
1087
1027
  }
1088
1028
 
1089
- const version = hash;
1029
+ //export { render, context, helpers, configure, create }
1090
1030
 
1091
- export { TemplateError, TemplateNotFound, TemplateSyntaxError, configure, context, create, helpers, render, setRenderer, setTemplates, version };
1031
+ export { TemplateError, TemplateNotFound, TemplateSyntaxError, configure, context, create, helpers, render, setRenderer, setTemplates };