@kosatyi/ejs 0.0.96 → 0.0.98

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';
@@ -234,153 +269,142 @@ const configSchema = (config, options) => {
234
269
 
235
270
  const global = typeof globalThis !== 'undefined' ? globalThis : window || self;
236
271
 
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 || {});
272
+ class Cache {
273
+ #enabled = true
274
+ #list = {}
275
+ constructor(config) {
276
+ bindContext(this, ['configure']);
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
+ bindContext(this, ['configure', 'compile']);
344
+ this.configure(config);
345
+ }
346
+ configure(config) {
347
+ this.#config.withObject = config.withObject;
348
+ this.#config.rmWhitespace = config.rmWhitespace;
349
+ this.#config.token = config.token;
350
+ this.#config.vars = config.vars;
351
+ this.#config.globalHelpers = config.globalHelpers;
352
+ this.#config.matches = [];
353
+ this.#config.formats = [];
354
+ this.#config.slurp = {
355
+ match: '[s\t\n]*',
356
+ start: [this.#config.token.start, '_'],
357
+ end: ['_', this.#config.token.end],
336
358
  };
337
- tagList.forEach((item) => {
338
- compiler.matches.push(
339
- compiler.token.start
359
+ this.#symbols.forEach((item) => {
360
+ this.#config.matches.push(
361
+ this.#config.token.start
340
362
  .concat(item.symbol)
341
- .concat(compiler.token.regex)
342
- .concat(compiler.token.end)
363
+ .concat(this.#config.token.regex)
364
+ .concat(this.#config.token.end)
343
365
  );
344
- compiler.formats.push(item.format.bind(compiler.vars));
366
+ this.#config.formats.push(item.format.bind(this.#config.vars));
345
367
  });
346
- compiler.regex = new RegExp(
347
- compiler.matches.join('|').concat('|$'),
368
+ this.#config.regex = new RegExp(
369
+ this.#config.matches.join('|').concat('|$'),
348
370
  'g'
349
371
  );
350
- compiler.slurpStart = new RegExp(
351
- [compiler.slurp.match, compiler.slurp.start.join('')].join(''),
372
+ this.#config.slurpStart = new RegExp(
373
+ [this.#config.slurp.match, this.#config.slurp.start.join('')].join(
374
+ ''
375
+ ),
352
376
  'gm'
353
377
  );
354
- compiler.slurpEnd = new RegExp(
355
- [compiler.slurp.end.join(''), compiler.slurp.match].join(''),
378
+ this.#config.slurpEnd = new RegExp(
379
+ [this.#config.slurp.end.join(''), this.#config.slurp.match].join(
380
+ ''
381
+ ),
356
382
  'gm'
357
383
  );
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
384
+ }
385
+ compile(content, path) {
386
+ const { SCOPE, SAFE, BUFFER, COMPONENT } = this.#config.vars;
387
+ const GLOBALS = this.#config.globalHelpers;
388
+ if (this.#config.rmWhitespace) {
389
+ content = String(content)
366
390
  .replace(/[\r\n]+/g, '\n')
367
391
  .replace(/^\s+|\s+$/gm, '');
368
392
  }
369
- content = content
370
- .replace(compiler.slurpStart, compiler.token.start)
371
- .replace(compiler.slurpEnd, compiler.token.end);
393
+ content = String(content)
394
+ .replace(this.#config.slurpStart, this.#config.token.start)
395
+ .replace(this.#config.slurpEnd, this.#config.token.end);
372
396
  let source = `${BUFFER}('`;
373
- matchTokens(compiler.regex, content, (params, index, offset) => {
397
+ matchTokens(this.#config.regex, content, (params, index, offset) => {
374
398
  source += symbols(content.slice(index, offset));
375
399
  params.forEach((value, index) => {
376
400
  if (value) {
377
- source += compiler.formats[index](value);
401
+ source += this.#config.formats[index](value);
378
402
  }
379
403
  });
380
404
  });
381
405
  source += `');`;
382
406
  source = `try{${source}}catch(e){return ${BUFFER}.error(e)}`;
383
- if (compiler.withObject) {
407
+ if (this.#config.withObject) {
384
408
  source = `with(${SCOPE}){${source}}`;
385
409
  }
386
410
  source = `${BUFFER}.start();${source}return ${BUFFER}.end();`;
@@ -396,57 +420,50 @@ function Compiler(config) {
396
420
  throw e
397
421
  }
398
422
  return result
399
- };
400
-
401
- this.configure(config);
423
+ }
402
424
  }
403
425
 
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);
426
+ class Template {
427
+ #path
428
+ #cache
429
+ #compiler
430
+ #resolver
431
+ constructor(config, cache, compiler) {
432
+ assertInstanceOf(cache, Cache);
433
+ assertInstanceOf(compiler, Compiler);
434
+ this.#cache = cache;
435
+ this.#compiler = compiler;
436
+ bindContext(this, ['configure', 'get']);
437
+ this.configure(config);
438
+ }
439
+ #resolve(path) {
440
+ return this.#resolver(this.#path, path)
441
+ }
442
+ #result(template, content) {
443
+ this.#cache.set(template, content);
418
444
  return content
419
- };
420
-
421
- const resolve = (path) => {
422
- return template.resolver(template.path, path)
423
- };
424
-
425
- const compile = (content, template) => {
445
+ }
446
+ #compile(content, template) {
426
447
  if (isFunction(content)) {
427
448
  return content
428
449
  } else {
429
- return compiler.compile(content, template)
450
+ return this.#compiler.compile(content, template)
430
451
  }
431
- };
432
-
433
- this.configure = function (config) {
434
- template.path = config.path;
435
- template.cache = config.cache;
452
+ }
453
+ configure(config) {
454
+ this.#path = config.path;
436
455
  if (isFunction(config.resolver)) {
437
- template.resolver = config.resolver;
456
+ this.#resolver = config.resolver;
438
457
  }
439
- };
440
-
441
- this.get = function (template) {
442
- if (cache.exist(template)) {
443
- return cache.resolve(template)
458
+ }
459
+ get(template) {
460
+ if (this.#cache.exist(template)) {
461
+ return this.#cache.resolve(template)
444
462
  }
445
- return resolve(template).then((content) =>
446
- result(template, compile(content, template))
463
+ return this.#resolve(template).then((content) =>
464
+ this.#result(template, this.#compile(content, template))
447
465
  )
448
- };
449
- this.configure(config);
466
+ }
450
467
  }
451
468
 
452
469
  const selfClosed = [
@@ -485,7 +502,7 @@ const element = (tag, attrs, content) => {
485
502
  }
486
503
  }).join(space);
487
504
  result.push([lt, tag, space, attributes, gt].join(''));
488
- if (content) {
505
+ if (content && hasClosedTag) {
489
506
  result.push(content instanceof Array ? content.join('') : content);
490
507
  }
491
508
  if (hasClosedTag) {
@@ -494,475 +511,431 @@ const element = (tag, attrs, content) => {
494
511
  return result.join('')
495
512
  };
496
513
 
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);
514
+ class TemplateError extends Error {
515
+ code = 0
516
+ constructor(message) {
517
+ super();
518
+ this.message = message;
519
+ }
520
+ getCode() {
521
+ return this.code
522
+ }
523
+ getMessage() {
524
+ return this.message
525
+ }
526
+ toString() {
527
+ return this.getMessage()
528
+ }
507
529
  }
508
530
 
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;
531
+ class TemplateNotFound extends TemplateError {
532
+ code = 404
544
533
  }
545
534
 
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;
535
+ class TemplateSyntaxError extends TemplateError {
536
+ code = 500
560
537
  }
561
538
 
562
- /**
563
- *
564
- */
565
- Object.setPrototypeOf(TemplateSyntaxError.prototype, TemplateError.prototype);
566
- Object.assign(TemplateSyntaxError.prototype, { code: 500 });
567
-
568
539
  function resolve(list) {
569
- return Promise.all(list || []).then((list) => list.join('')).catch((e) => e)
540
+ return Promise.all(list || [])
541
+ .then((list) => list.join(''))
542
+ .catch((e) => e)
570
543
  }
571
544
 
572
545
  function reject(error) {
573
546
  return Promise.reject(new TemplateSyntaxError(error.message))
574
547
  }
575
548
 
549
+ /**
550
+ *
551
+ * @return {buffer}
552
+ */
576
553
  function createBuffer() {
577
554
  let store = [],
578
555
  array = [];
579
556
 
580
- function buffer(value) {
557
+ const buffer = (value) => {
581
558
  array.push(value);
582
- }
559
+ };
583
560
 
584
- buffer.start = function() {
561
+ buffer.start = () => {
585
562
  array = [];
586
563
  };
587
- buffer.backup = function() {
564
+ buffer.backup = () => {
588
565
  store.push(array.concat());
589
566
  array = [];
590
567
  };
591
- buffer.restore = function() {
568
+ buffer.restore = () => {
592
569
  const result = array.concat();
593
570
  array = store.pop();
594
571
  return resolve(result)
595
572
  };
596
- buffer.error = function(e) {
573
+ buffer.error = (e) => {
597
574
  return reject(e)
598
575
  };
599
- buffer.end = function() {
576
+ buffer.end = () => {
600
577
  return resolve(array)
601
578
  };
602
579
  return buffer
603
580
  }
604
581
 
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
- }
582
+ const createScope = (config, methods) => {
583
+ const { BLOCKS, MACRO, EXTEND, LAYOUT, BUFFER, COMPONENT, SAFE, SCOPE } =
584
+ config.vars;
585
+ /**
586
+ * @name ContextScope
587
+ * @param data
588
+ * @constructor
589
+ */
590
+ function ContextScope(data) {
591
+ this[BLOCKS] = {};
592
+ this[MACRO] = {};
593
+ Object.assign(this, omit(data, [SCOPE, BUFFER, SAFE, COMPONENT]));
594
+ }
627
595
 
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,
659
- },
660
- getMacro: {
661
- value() {
662
- return this[MACRO]
663
- },
664
- writable: false,
665
- configurable: false,
666
- enumerable: false,
596
+ Object.assign(ContextScope.prototype, methods);
597
+ Object.defineProperties(ContextScope.prototype, {
598
+ [BUFFER]: {
599
+ value: createBuffer(),
600
+ },
601
+ [BLOCKS]: {
602
+ value: {},
603
+ writable: true,
604
+ },
605
+ [MACRO]: {
606
+ value: {},
607
+ writable: true,
608
+ },
609
+ [LAYOUT]: {
610
+ value: false,
611
+ writable: true,
612
+ },
613
+ [EXTEND]: {
614
+ value: false,
615
+ writable: true,
616
+ },
617
+ /** @type {()=>this[MACRO]} */
618
+ getMacro: {
619
+ value() {
620
+ return this[MACRO]
667
621
  },
668
- getBuffer: {
669
- value() {
670
- return this[BUFFER]
671
- },
672
- writable: false,
673
- configurable: false,
674
- enumerable: false,
622
+ },
623
+ /** @type {function} */
624
+ getBuffer: {
625
+ value() {
626
+ return this[BUFFER]
675
627
  },
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
- }
628
+ },
629
+ /** @type {function} */
630
+ getComponent: {
631
+ value() {
632
+ const context = this;
633
+ if (COMPONENT in context) {
684
634
  return function () {
685
- console.log('%s function not defined', COMPONENT);
635
+ return context[COMPONENT].apply(context, arguments)
686
636
  }
687
- },
688
- writable: false,
689
- configurable: false,
690
- enumerable: false,
637
+ }
638
+ return function () {
639
+ console.log('%s function not defined', COMPONENT);
640
+ }
691
641
  },
692
- getBlocks: {
693
- value() {
694
- return this[BLOCKS]
695
- },
696
- writable: false,
697
- configurable: false,
698
- enumerable: false,
642
+ },
643
+ /** @type {function} */
644
+ getBlocks: {
645
+ value() {
646
+ return this[BLOCKS]
699
647
  },
700
- setExtend: {
701
- value(value) {
702
- this[EXTEND] = value;
703
- },
704
- writable: false,
705
- configurable: false,
706
- enumerable: false,
648
+ },
649
+ /** @type {function} */
650
+ setExtend: {
651
+ value(value) {
652
+ this[EXTEND] = value;
707
653
  },
708
- getExtend: {
709
- value() {
710
- return this[EXTEND]
711
- },
712
- writable: false,
713
- configurable: false,
714
- enumerable: false,
654
+ },
655
+ /** @type {function} */
656
+ getExtend: {
657
+ value() {
658
+ return this[EXTEND]
715
659
  },
716
- setLayout: {
717
- value(layout) {
718
- this[LAYOUT] = layout;
719
- },
720
- writable: false,
721
- configurable: false,
722
- enumerable: false,
660
+ },
661
+ /** @type {function} */
662
+ setLayout: {
663
+ value(layout) {
664
+ this[LAYOUT] = layout;
723
665
  },
724
- getLayout: {
725
- value() {
726
- return this[LAYOUT]
727
- },
728
- writable: false,
729
- configurable: false,
730
- enumerable: false,
666
+ },
667
+ /** @type {function} */
668
+ getLayout: {
669
+ value() {
670
+ return this[LAYOUT]
731
671
  },
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,
672
+ },
673
+ /** @type {function} */
674
+ clone: {
675
+ value(exclude_blocks) {
676
+ const filter = [LAYOUT, EXTEND, BUFFER];
677
+ if (exclude_blocks === true) {
678
+ filter.push(BLOCKS);
679
+ }
680
+ return omit(this, filter)
743
681
  },
744
- extend: {
745
- value(layout) {
746
- this.setExtend(true);
747
- this.setLayout(layout);
748
- },
749
- writable: false,
750
- configurable: false,
751
- enumerable: false,
682
+ },
683
+ /** @type {function} */
684
+ extend: {
685
+ value(layout) {
686
+ this.setExtend(true);
687
+ this.setLayout(layout);
752
688
  },
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,
689
+ },
690
+ /** @type {function} */
691
+ echo: {
692
+ value(layout) {
693
+ const buffer = this.getBuffer();
694
+ const params = [].slice.call(arguments);
695
+ params.forEach(buffer);
762
696
  },
763
- fn: {
764
- value(callback) {
765
- const buffer = this.getBuffer();
766
- const context = this;
767
- return function () {
768
- buffer.backup();
769
- if (isFunction(callback)) {
770
- callback.apply(context, arguments);
771
- }
772
- return buffer.restore()
697
+ },
698
+ /** @type {function} */
699
+ fn: {
700
+ value(callback) {
701
+ const buffer = this.getBuffer();
702
+ const context = this;
703
+ return function () {
704
+ buffer.backup();
705
+ if (isFunction(callback)) {
706
+ callback.apply(context, arguments);
773
707
  }
774
- },
775
- writable: false,
776
- configurable: false,
777
- enumerable: false,
708
+ return buffer.restore()
709
+ }
778
710
  },
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,
711
+ },
712
+ /** @type {function} */
713
+ get: {
714
+ value(name, defaults) {
715
+ const path = getPath(this, name, true);
716
+ const result = path.shift();
717
+ const prop = path.pop();
718
+ return hasProp(result, prop) ? result[prop] : defaults
789
719
  },
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,
720
+ },
721
+ /** @type {function} */
722
+ set: {
723
+ value(name, value) {
724
+ const path = getPath(this, name, false);
725
+ const result = path.shift();
726
+ const prop = path.pop();
727
+ if (this.getExtend() && hasProp(result, prop)) {
728
+ return result[prop]
729
+ }
730
+ return (result[prop] = value)
803
731
  },
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,
732
+ },
733
+ /** @type {function} */
734
+ macro: {
735
+ value(name, callback) {
736
+ const list = this.getMacro();
737
+ const macro = this.fn(callback);
738
+ const context = this;
739
+ list[name] = function () {
740
+ return context.echo(macro.apply(undefined, arguments))
741
+ };
816
742
  },
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,
743
+ },
744
+ /** @type {function} */
745
+ call: {
746
+ value(name) {
747
+ const list = this.getMacro();
748
+ const macro = list[name];
749
+ const params = [].slice.call(arguments, 1);
750
+ if (isFunction(macro)) {
751
+ return macro.apply(macro, params)
752
+ }
829
753
  },
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
754
+ },
755
+ /** @type {function} */
756
+ block: {
757
+ value(name, callback) {
758
+ const blocks = this.getBlocks();
759
+ blocks[name] = blocks[name] || [];
760
+ blocks[name].push(this.fn(callback));
761
+ if (this.getExtend()) return
762
+ const list = Object.assign([], blocks[name]);
763
+ const current = function () {
764
+ return list.shift()
765
+ };
766
+ const next = () => {
767
+ const parent = current();
768
+ if (parent) {
769
+ return () => {
770
+ this.echo(parent(next()));
848
771
  }
849
- };
850
- this.echo(current()(next()));
851
- },
852
- writable: false,
853
- configurable: false,
854
- enumerable: false,
772
+ } else {
773
+ return noop
774
+ }
775
+ };
776
+ this.echo(current()(next()));
855
777
  },
856
- hasBlock: {
857
- value(name) {
858
- return this.getBlocks().hasOwnProperty(name)
859
- },
860
- writable: false,
861
- configurable: false,
862
- enumerable: false,
778
+ },
779
+ /** @type {function} */
780
+ hasBlock: {
781
+ value(name) {
782
+ return this.getBlocks().hasOwnProperty(name)
863
783
  },
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,
784
+ },
785
+ /** @type {function} */
786
+ include: {
787
+ value(path, data, cx) {
788
+ const context = cx === false ? {} : this.clone(true);
789
+ const params = extend(context, data || {});
790
+ const promise = this.render(path, params);
791
+ this.echo(promise);
874
792
  },
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,
793
+ },
794
+ /** @type {function} */
795
+ promiseResolve: {
796
+ value(value, callback) {
797
+ return Promise.resolve(
798
+ isFunction(value) ? this.fn(value)() : value
799
+ ).then(callback.bind(this))
884
800
  },
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,
801
+ },
802
+ /** @type {function} */
803
+ use: {
804
+ value(path, namespace) {
805
+ this.echo(
806
+ this.promiseResolve(this.require(path), function (exports) {
807
+ const list = this.getMacro();
808
+ each(exports, function (macro, name) {
809
+ list[[namespace, name].join('.')] = macro;
810
+ });
811
+ })
812
+ );
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
+ async: {
817
+ value(promise, callback) {
818
+ this.echo(
819
+ this.promiseResolve(promise, function (data) {
820
+ return this.fn(callback)(data)
821
+ })
822
+ );
914
823
  },
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,
824
+ },
825
+ /** @type {function} */
826
+ each: {
827
+ value: function (object, callback) {
828
+ if (isString(object)) {
829
+ object = this.get(object, []);
830
+ }
831
+ each(object, callback);
925
832
  },
926
- element: {
927
- value(tag, attr, content) {
928
- return element(tag, attr, content)
929
- },
930
- writable: false,
931
- configurable: false,
932
- enumerable: false,
833
+ },
834
+ /** @type {function} */
835
+ element: {
836
+ value(tag, attr, content) {
837
+ return element(tag, attr, content)
933
838
  },
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,
839
+ },
840
+ /** @type {function} */
841
+ el: {
842
+ value(tag, attr, content) {
843
+ this.echo(
844
+ this.promiseResolve(content, function (content) {
845
+ return this.element(tag, attr, content)
846
+ })
847
+ );
945
848
  },
946
- });
947
- };
948
- this.configure(config);
949
- }
849
+ },
850
+ });
851
+ return ContextScope
852
+ };
853
+
854
+ class Context {
855
+ #scope
950
856
 
951
- function EJS(options) {
952
- if (instanceOf(this, EJS) === false) return new EJS(options)
857
+ constructor(config, methods) {
858
+ bindContext(this, ['create', 'helpers', 'configure']);
859
+ this.configure(config, methods);
860
+ }
953
861
 
954
- const scope = {};
955
- const config = {};
862
+ create(data) {
863
+ return new this.#scope(data)
864
+ }
956
865
 
957
- configSchema(config, options || {});
866
+ configure(config, methods) {
867
+ this.#scope = createScope(config, methods);
868
+ }
958
869
 
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);
870
+ helpers(methods) {
871
+ extend(this.#scope.prototype, methods || {});
872
+ }
873
+ }
963
874
 
964
- const output = (path, scope) => {
965
- const { globalHelpers } = config;
875
+ class EJS {
876
+ #config = {}
877
+ #extend = {}
878
+ #context
879
+ #compiler
880
+ #cache
881
+ #template
882
+ constructor(options) {
883
+ configSchema(this.#config, options || {});
884
+ this.#context = new Context(this.#config, this.#extend);
885
+ this.#compiler = new Compiler(this.#config);
886
+ this.#cache = new Cache(this.#config);
887
+ this.#template = new Template(this.#config, this.#cache, this.#compiler);
888
+ //
889
+ bindContext(this, [
890
+ 'configure',
891
+ 'create',
892
+ 'render',
893
+ 'context',
894
+ 'preload',
895
+ 'compile',
896
+ 'helpers',
897
+ ]);
898
+ //
899
+ this.helpers({ require: this.#require, render: this.render });
900
+ }
901
+ configure(options) {
902
+ configSchema(this.#config, options || {});
903
+ this.#context.configure(this.#config, this.#extend);
904
+ this.#compiler.configure(this.#config);
905
+ this.#cache.configure(this.#config);
906
+ this.#template.configure(this.#config);
907
+ return this.#config
908
+ }
909
+ render(name, data) {
910
+ const filepath = ext(name, this.#config.extension);
911
+ const scope = this.context(data);
912
+ return this.#output(filepath, scope).then((content) => {
913
+ if (scope.getExtend()) {
914
+ scope.setExtend(false);
915
+ const layout = scope.getLayout();
916
+ const data = scope.clone();
917
+ return this.render(layout, data)
918
+ }
919
+ return content
920
+ })
921
+ }
922
+ helpers(methods) {
923
+ this.#context.helpers(extend(this.#extend, methods));
924
+ }
925
+ context(data) {
926
+ return this.#context.create(data)
927
+ }
928
+ compile(content, path) {
929
+ return this.#compiler.compile(content, path)
930
+ }
931
+ preload(list) {
932
+ return this.#cache.load(list || {})
933
+ }
934
+ create(options) {
935
+ return new this.constructor(options)
936
+ }
937
+ #output(path, scope) {
938
+ const { globalHelpers } = this.#config;
966
939
  const params = [
967
940
  scope,
968
941
  scope.getComponent(),
@@ -973,63 +946,177 @@ function EJS(options) {
973
946
  .filter((name) => isFunction(scope[name]))
974
947
  .map((name) => scope[name].bind(scope))
975
948
  );
976
- return template
949
+ return this.#template
977
950
  .get(path)
978
951
  .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
952
+ }
953
+ #require(name) {
954
+ const filepath = ext(name, this.#config.extension);
955
+ const scope = this.context({});
956
+ return this.#output(filepath, scope).then(() => scope.getMacro())
957
+ }
1028
958
  }
1029
959
 
1030
- const hash = Math.floor(Math.random() * 1e12).toString(36);
960
+ // export function EJS2(options) {
961
+ // const self = {
962
+ // config: {},
963
+ // helpers: {},
964
+ // /**
965
+ // * @type {Context}
966
+ // */
967
+ // context: null,
968
+ // /**
969
+ // * @type {Compiler}
970
+ // */
971
+ // compiler: null,
972
+ // /**
973
+ // * @type {Template}
974
+ // */
975
+ // template: null,
976
+ // /**
977
+ // * @type {Cache}
978
+ // */
979
+ // cache: null,
980
+ // }
981
+ // /**
982
+ // *
983
+ // */
984
+ // configSchema(self.config, options || {})
985
+ // self.context = useContext(self.config, self.helpers)
986
+ // self.compiler = useCompiler(self.config)
987
+ // self.cache = useCache(self.config)
988
+ // self.template = useTemplate(self.config, self.cache, self.compiler)
989
+ // /**
990
+ // *
991
+ // * @param {string} path
992
+ // * @param {ContextScope} scope
993
+ // * @return {Promise<string>}
994
+ // */
995
+ // const output = (path, scope) => {
996
+ // const { globalHelpers } = self.config
997
+ // const params = [
998
+ // scope,
999
+ // scope.getComponent(),
1000
+ // scope.getBuffer(),
1001
+ // safeValue,
1002
+ // ].concat(
1003
+ // globalHelpers
1004
+ // .filter((name) => isFunction(scope[name]))
1005
+ // .map((name) => scope[name].bind(scope))
1006
+ // )
1007
+ // return self.template
1008
+ // .get(path)
1009
+ // .then((callback) => callback.apply(scope, params))
1010
+ // }
1011
+ // /**
1012
+ // *
1013
+ // * @param name
1014
+ // * @return {Promise<string>}
1015
+ // */
1016
+ // const require = (name) => {
1017
+ // const filepath = ext(name, self.config.extension)
1018
+ // const scope = context({})
1019
+ // return output(filepath, scope).then(() => scope.getMacro())
1020
+ // }
1021
+ // /**
1022
+ // *
1023
+ // * @param {string} name
1024
+ // * @param {{}} [data]
1025
+ // * @return {Promise<string>}
1026
+ // */
1027
+ // const render = (name, data) => {
1028
+ // const filepath = ext(name, self.config.extension)
1029
+ // const scope = context(data)
1030
+ // return output(filepath, scope).then((content) => {
1031
+ // if (scope.getExtend()) {
1032
+ // scope.setExtend(false)
1033
+ // const layout = scope.getLayout()
1034
+ // const data = scope.clone()
1035
+ // return render(layout, data)
1036
+ // }
1037
+ // return content
1038
+ // })
1039
+ // }
1040
+ // /**
1041
+ // *
1042
+ // * @param options
1043
+ // * @return {{}}
1044
+ // */
1045
+ // const configure = (options = {}) => {
1046
+ // configSchema(self.config, options || {})
1047
+ // self.context.configure(self.config, self.helpers)
1048
+ // self.compiler.configure(self.config)
1049
+ // self.cache.configure(self.config)
1050
+ // self.template.configure(self.config)
1051
+ // return self.config
1052
+ // }
1053
+ // /**
1054
+ // *
1055
+ // * @param methods
1056
+ // */
1057
+ // const helpers = (methods) => {
1058
+ // self.context.helpers(extend(self.helpers, methods))
1059
+ // }
1060
+ // /**
1061
+ // *
1062
+ // * @param list
1063
+ // * @return {*}
1064
+ // */
1065
+ // const preload = (list) => {
1066
+ // return self.cache.load(list || {})
1067
+ // }
1068
+ // /**
1069
+ // *
1070
+ // * @param options
1071
+ // * @return {any}
1072
+ // */
1073
+ // const create = (options) => {
1074
+ // return EJS(options)
1075
+ // }
1076
+ // /**
1077
+ // *
1078
+ // * @param content
1079
+ // * @param path
1080
+ // * @return {Function}
1081
+ // */
1082
+ // const compile = (content, path) => {
1083
+ // return self.compiler.compile(content, path)
1084
+ // }
1085
+ // /**
1086
+ // *
1087
+ // * @param data
1088
+ // * @return {ContextScope}
1089
+ // */
1090
+ // const context = (data = {}) => {
1091
+ // return self.context.create(data)
1092
+ // }
1093
+ // /**
1094
+ // *
1095
+ // */
1096
+ // helpers({ require, render })
1097
+ // /**
1098
+ // *
1099
+ // */
1100
+ // return {
1101
+ // configure,
1102
+ // helpers,
1103
+ // preload,
1104
+ // context,
1105
+ // compile,
1106
+ // create,
1107
+ // render,
1108
+ // }
1109
+ // }
1110
+
1031
1111
  const templates = {};
1032
- const ejs = new EJS({
1112
+
1113
+ const getOrigin = (url, secure) => {
1114
+ url = new URL(url);
1115
+ url.protocol = secure ? 'https:' : 'http:';
1116
+ return url.origin
1117
+ };
1118
+
1119
+ const { render, context, helpers, configure, create } = new EJS({
1033
1120
  cache: false,
1034
1121
  withObject: false,
1035
1122
  resolver(path, name) {
@@ -1040,24 +1127,19 @@ const ejs = new EJS({
1040
1127
  reject(new TemplateNotFound(`template ${name} not found`));
1041
1128
  }
1042
1129
  })
1043
- }
1130
+ },
1044
1131
  });
1045
1132
 
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
-
1133
+ /**
1134
+ *
1135
+ * @param list
1136
+ */
1055
1137
  function setTemplates(list) {
1056
1138
  Object.assign(templates, list || {});
1057
1139
  }
1058
1140
 
1059
1141
  /**
1060
- * @typedef {Object<string,any>} HonoContext
1142
+ * @typedef {{}} HonoContext
1061
1143
  * @property {function(*):Promise<Response>} html
1062
1144
  * @property {function():Promise<Response>} notFound
1063
1145
  * @property {function(methods:{}):void} helpers
@@ -1068,24 +1150,23 @@ function setTemplates(list) {
1068
1150
 
1069
1151
  /**
1070
1152
  * @param {Object<string,any>} options
1071
- * @return {(function(c:Context, next): Promise<any>)|*}
1153
+ * @return {(function(c:HonoContext, next): Promise<any>)|*}
1072
1154
  */
1073
- function setRenderer({ version = hash, secure = true } = {}) {
1155
+ function setRenderer({ version, secure = true } = {}) {
1074
1156
  return async (c, next) => {
1075
1157
  c.data = context({});
1076
1158
  c.data.set('version', version);
1077
1159
  c.data.set('origin', getOrigin(c.req.url, secure));
1078
1160
  c.data.set('path', c.req.path);
1079
1161
  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));
1162
+ c.ejs = (name, data) =>
1163
+ render(name, Object.assign({ param: c.req.param() }, c.data, data));
1083
1164
  c.helpers = (methods) => helpers(methods);
1084
1165
  c.render = (name, data) => c.html(c.ejs(name, data));
1085
1166
  await next();
1086
1167
  }
1087
1168
  }
1088
1169
 
1089
- const version = hash;
1170
+ //export { render, context, helpers, configure, create }
1090
1171
 
1091
- export { TemplateError, TemplateNotFound, TemplateSyntaxError, configure, context, create, helpers, render, setRenderer, setTemplates, version };
1172
+ export { TemplateError, TemplateNotFound, TemplateSyntaxError, configure, context, create, helpers, render, setRenderer, setTemplates };