@kosatyi/ejs 0.0.77 → 0.0.79

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.
@@ -388,7 +388,7 @@ function Compiler(config) {
388
388
  });
389
389
  });
390
390
  source += `');`;
391
- source = `try{${source}}catch(e){console.info(e)}`;
391
+ source = `try{${source}}catch(e){return ${BUFFER}.error(e)}`;
392
392
  if (compiler.withObject) {
393
393
  source = `with(${SCOPE}){${source}}`;
394
394
  }
@@ -503,10 +503,40 @@ const element = (tag, attrs, content) => {
503
503
  return result.join('')
504
504
  };
505
505
 
506
+ function TemplateError(message) {
507
+ this.code = 1;
508
+ this.name = 'TemplateError';
509
+ this.message = message;
510
+ Error.call(this);
511
+ }
512
+ Object.setPrototypeOf(TemplateNotFound.prototype, Error.prototype);
513
+
514
+ function TemplateNotFound(message) {
515
+ TemplateError.call(this);
516
+ this.code = 404;
517
+ this.name = 'TemplateNotFound';
518
+ this.message = message;
519
+ }
520
+
521
+ Object.setPrototypeOf(TemplateNotFound.prototype, TemplateError.prototype);
522
+
523
+ function TemplateSyntaxError(message) {
524
+ TemplateError.call(this);
525
+ this.code = 500;
526
+ this.name = 'TemplateSyntaxError';
527
+ this.message = message;
528
+ }
529
+
530
+ Object.setPrototypeOf(TemplateSyntaxError.prototype, TemplateError.prototype);
531
+
506
532
  function resolve(list) {
507
533
  return Promise.all(list || []).then((list) => list.join(''))
508
534
  }
509
535
 
536
+ function reject(error) {
537
+ return Promise.reject(new TemplateSyntaxError(error.message))
538
+ }
539
+
510
540
  function createBuffer() {
511
541
  let store = [],
512
542
  array = [];
@@ -526,7 +556,7 @@ function createBuffer() {
526
556
  return resolve(result)
527
557
  };
528
558
  buffer.error = function (e) {
529
- throw e
559
+ return reject(e)
530
560
  };
531
561
  buffer.end = function () {
532
562
  return resolve(array)
@@ -546,7 +576,11 @@ function Context(config) {
546
576
  this.helpers = function (methods) {
547
577
  extend(Scope.prototype, methods || {});
548
578
  };
549
-
579
+ /**
580
+ * @name ContextScope
581
+ * @param data
582
+ * @constructor
583
+ */
550
584
  function Scope(data) {
551
585
  this[BLOCKS] = {};
552
586
  this[MACRO] = {};
@@ -712,8 +746,8 @@ function Context(config) {
712
746
  const prop = path.pop();
713
747
  return hasProp(result, prop) ? result[prop] : defaults
714
748
  },
715
- writable: false,
716
- configurable: false,
749
+ writable: true,
750
+ configurable: true,
717
751
  enumerable: false,
718
752
  },
719
753
  set: {
@@ -782,6 +816,14 @@ function Context(config) {
782
816
  configurable: false,
783
817
  enumerable: false,
784
818
  },
819
+ hasBlock: {
820
+ value(name) {
821
+ return this.getBlocks().hasOwnProperty(name)
822
+ },
823
+ writable: false,
824
+ configurable: false,
825
+ enumerable: false,
826
+ },
785
827
  include: {
786
828
  value(path, data, cx) {
787
829
  const context = cx === false ? {} : this.clone(true);
@@ -885,27 +927,27 @@ function EJS(options) {
885
927
  const cache = new Cache();
886
928
  const template = new Template(config, cache, compiler);
887
929
 
888
- const output = (path, context) => {
930
+ const output = (path, scope) => {
931
+ const { globalHelpers } = config;
889
932
  const params = [
890
- context,
891
- context.getComponent(),
892
- context.getBuffer(),
933
+ scope,
934
+ scope.getComponent(),
935
+ scope.getBuffer(),
893
936
  safeValue,
894
- ];
895
- config.globalHelpers.forEach((name) => {
896
- if (isFunction(context[name]))
897
- params.push(context[name].bind(context));
898
- });
899
- return template.get(path).then(function (callback) {
900
- return callback.apply(context, params)
901
- })
937
+ ].concat(
938
+ globalHelpers
939
+ .filter((name) => isFunction(scope[name]))
940
+ .map((name) => scope[name].bind(scope))
941
+ );
942
+ return template
943
+ .get(path)
944
+ .then((callback) => callback.apply(scope, params))
902
945
  };
946
+
903
947
  const require = (name) => {
904
948
  const filepath = ext(name, config.extension);
905
949
  const scope = context.create({});
906
- return output(filepath, scope).then(() => {
907
- return scope.getMacro()
908
- })
950
+ return output(filepath, scope).then(() => scope.getMacro())
909
951
  };
910
952
  const render = (name, data) => {
911
953
  const filepath = ext(name, config.extension);
@@ -954,7 +996,7 @@ function EJS(options) {
954
996
  const httpRequest = (path, template) => {
955
997
  return fetch(joinPath(path, template)).then(
956
998
  (response) => response.text(),
957
- (reason) => String(reason)
999
+ (reason) => new TemplateError(reason)
958
1000
  )
959
1001
  };
960
1002
 
@@ -0,0 +1,168 @@
1
+ import { promises } from 'fs';
2
+ import { glob } from 'glob';
3
+ import { join, extname, dirname } from 'path';
4
+ import { minify } from 'terser';
5
+ import { configure, compile } from './index.js';
6
+ import babel from '@babel/core';
7
+
8
+ const isPlainObject = function (obj) {
9
+ return Object.prototype.toString.call(obj) === '[object Object]'
10
+ };
11
+
12
+ const extend = (target, ...sources) => {
13
+ return Object.assign(target, ...sources.filter(isPlainObject))
14
+ };
15
+
16
+ class Bundler {
17
+ /**
18
+ * @type {BundlerOptions}
19
+ */
20
+ options = {
21
+ target: [],
22
+ transform: true,
23
+ minify: true,
24
+ timestamp: true,
25
+ }
26
+ /**
27
+ * @type {EjsConfig}
28
+ */
29
+ config = {}
30
+ constructor(options, config) {
31
+ extend(this.options, options || {});
32
+ this.config = configure(config || {});
33
+ this.templates = {};
34
+ }
35
+ stageRead(path) {
36
+ return promises
37
+ .readFile(join(this.config.path, path))
38
+ .then((response) => response.toString())
39
+ }
40
+ stageCompile(content, name) {
41
+ return compile(content, name).source
42
+ }
43
+ async stageMinify(content) {
44
+ if (this.options.minify === false) return content
45
+ const config = {
46
+ compress: {
47
+ dead_code: false,
48
+ side_effects: false,
49
+ },
50
+ };
51
+ const response = await minify(content, config);
52
+ return response.code
53
+ }
54
+ async stageTransform(content) {
55
+ if (this.options.transform === false) return content
56
+ const config = {
57
+ presets: [['@babel/preset-env']],
58
+ sourceType: 'script',
59
+ };
60
+ const response = await babel.transformAsync(content, config);
61
+ return response.code
62
+ }
63
+ getBundle() {
64
+ const transform = this.options.transform;
65
+ const moduleId = this.config.export;
66
+ const useStrict = this.config.withObject === false;
67
+ const timestamp = this.options.timestamp;
68
+ const out = [];
69
+ if (transform) {
70
+ out.push('(function(global,factory){');
71
+ out.push(
72
+ 'typeof exports === "object" && typeof module !== "undefined" ?'
73
+ );
74
+ out.push('module.exports = factory():');
75
+ out.push(
76
+ 'typeof define === "function" && define.amd ? define(factory):'
77
+ );
78
+ out.push(
79
+ '(global = typeof globalThis !== "undefined" ? globalThis:'
80
+ );
81
+ out.push('global || self,global["' + moduleId + '"] = factory())');
82
+ out.push('})(this,(function(){');
83
+ }
84
+ if (useStrict) out.push("'use strict'");
85
+ if (timestamp) out.push('const timestamp = '.concat(String(Date.now())));
86
+ out.push('const templates = {}');
87
+ Object.entries(this.templates).forEach(([name, content]) => {
88
+ name = JSON.stringify(name);
89
+ content = String(content);
90
+ out.push(`templates[${name}] = ${content}`);
91
+ });
92
+ if (transform) {
93
+ out.push('return templates');
94
+ out.push('}))');
95
+ } else {
96
+ out.push('export default templates');
97
+ }
98
+ return out.join('\n')
99
+ }
100
+ async watch() {
101
+ console.log(`ejs-bundle: watching directory - ${this.config.path}`);
102
+ try {
103
+ const watcher = promises.watch(this.config.path, { recursive: true });
104
+ for await (const { filename } of watcher) {
105
+ if (extname(filename).slice(1) === this.config.extension) {
106
+ console.log(`ejs-bundle: file is changed - ${filename}`);
107
+ await this.build();
108
+ }
109
+ }
110
+ } catch (err) {
111
+ throw err
112
+ }
113
+ }
114
+ async build() {
115
+ if (this.buildInProgress === true) return false
116
+ this.buildInProgress = true;
117
+ await this.concat().catch(console.error);
118
+ await this.output().catch(console.error);
119
+ console.log(`ejs-bundle: bundle complete - ${this.options.target}`);
120
+ this.buildInProgress = false;
121
+ }
122
+ async concat() {
123
+ const pattern = '**/*.'.concat(this.config.extension);
124
+ const list = await glob(pattern, { cwd: this.config.path });
125
+ for (let template of list) {
126
+ let content = '';
127
+ content = await this.stageRead(template);
128
+ content = await this.stageCompile(content, template);
129
+ this.templates[template] = content;
130
+ }
131
+ }
132
+ async output() {
133
+ const target = [].concat(this.options.target);
134
+ let content = this.getBundle();
135
+ if (this.options.transform) {
136
+ content = await this.stageTransform(content);
137
+ }
138
+ if (this.options.minify) {
139
+ content = await this.stageMinify(content);
140
+ }
141
+ for (let file of target) {
142
+ const folderPath = dirname(file);
143
+ const folderExists = await promises
144
+ .stat(folderPath)
145
+ .then(() => true)
146
+ .catch(() => false);
147
+ if (folderExists === false) {
148
+ await promises.mkdir(folderPath, { recursive: true });
149
+ }
150
+ await promises.writeFile(file, content);
151
+ }
152
+ }
153
+ }
154
+
155
+ const ejsBundle = (options, config) => {
156
+ const bundler = new Bundler(options, config);
157
+ return {
158
+ name: 'ejs-bundle',
159
+ async buildStart() {
160
+ await bundler.concat();
161
+ },
162
+ async buildEnd() {
163
+ await bundler.output();
164
+ },
165
+ }
166
+ };
167
+
168
+ export { Bundler, ejsBundle };
package/dist/esm/index.js CHANGED
@@ -391,7 +391,7 @@ function Compiler(config) {
391
391
  });
392
392
  });
393
393
  source += `');`;
394
- source = `try{${source}}catch(e){console.info(e)}`;
394
+ source = `try{${source}}catch(e){return ${BUFFER}.error(e)}`;
395
395
  if (compiler.withObject) {
396
396
  source = `with(${SCOPE}){${source}}`;
397
397
  }
@@ -506,10 +506,40 @@ const element = (tag, attrs, content) => {
506
506
  return result.join('')
507
507
  };
508
508
 
509
+ function TemplateError(message) {
510
+ this.code = 1;
511
+ this.name = 'TemplateError';
512
+ this.message = message;
513
+ Error.call(this);
514
+ }
515
+ Object.setPrototypeOf(TemplateNotFound.prototype, Error.prototype);
516
+
517
+ function TemplateNotFound(message) {
518
+ TemplateError.call(this);
519
+ this.code = 404;
520
+ this.name = 'TemplateNotFound';
521
+ this.message = message;
522
+ }
523
+
524
+ Object.setPrototypeOf(TemplateNotFound.prototype, TemplateError.prototype);
525
+
526
+ function TemplateSyntaxError(message) {
527
+ TemplateError.call(this);
528
+ this.code = 500;
529
+ this.name = 'TemplateSyntaxError';
530
+ this.message = message;
531
+ }
532
+
533
+ Object.setPrototypeOf(TemplateSyntaxError.prototype, TemplateError.prototype);
534
+
509
535
  function resolve(list) {
510
536
  return Promise.all(list || []).then((list) => list.join(''))
511
537
  }
512
538
 
539
+ function reject(error) {
540
+ return Promise.reject(new TemplateSyntaxError(error.message))
541
+ }
542
+
513
543
  function createBuffer() {
514
544
  let store = [],
515
545
  array = [];
@@ -529,7 +559,7 @@ function createBuffer() {
529
559
  return resolve(result)
530
560
  };
531
561
  buffer.error = function (e) {
532
- throw e
562
+ return reject(e)
533
563
  };
534
564
  buffer.end = function () {
535
565
  return resolve(array)
@@ -549,7 +579,11 @@ function Context(config) {
549
579
  this.helpers = function (methods) {
550
580
  extend(Scope.prototype, methods || {});
551
581
  };
552
-
582
+ /**
583
+ * @name ContextScope
584
+ * @param data
585
+ * @constructor
586
+ */
553
587
  function Scope(data) {
554
588
  this[BLOCKS] = {};
555
589
  this[MACRO] = {};
@@ -715,8 +749,8 @@ function Context(config) {
715
749
  const prop = path.pop();
716
750
  return hasProp(result, prop) ? result[prop] : defaults
717
751
  },
718
- writable: false,
719
- configurable: false,
752
+ writable: true,
753
+ configurable: true,
720
754
  enumerable: false,
721
755
  },
722
756
  set: {
@@ -785,6 +819,14 @@ function Context(config) {
785
819
  configurable: false,
786
820
  enumerable: false,
787
821
  },
822
+ hasBlock: {
823
+ value(name) {
824
+ return this.getBlocks().hasOwnProperty(name)
825
+ },
826
+ writable: false,
827
+ configurable: false,
828
+ enumerable: false,
829
+ },
788
830
  include: {
789
831
  value(path, data, cx) {
790
832
  const context = cx === false ? {} : this.clone(true);
@@ -888,27 +930,27 @@ function EJS(options) {
888
930
  const cache = new Cache();
889
931
  const template = new Template(config, cache, compiler);
890
932
 
891
- const output = (path, context) => {
933
+ const output = (path, scope) => {
934
+ const { globalHelpers } = config;
892
935
  const params = [
893
- context,
894
- context.getComponent(),
895
- context.getBuffer(),
936
+ scope,
937
+ scope.getComponent(),
938
+ scope.getBuffer(),
896
939
  safeValue,
897
- ];
898
- config.globalHelpers.forEach((name) => {
899
- if (isFunction(context[name]))
900
- params.push(context[name].bind(context));
901
- });
902
- return template.get(path).then(function (callback) {
903
- return callback.apply(context, params)
904
- })
940
+ ].concat(
941
+ globalHelpers
942
+ .filter((name) => isFunction(scope[name]))
943
+ .map((name) => scope[name].bind(scope))
944
+ );
945
+ return template
946
+ .get(path)
947
+ .then((callback) => callback.apply(scope, params))
905
948
  };
949
+
906
950
  const require = (name) => {
907
951
  const filepath = ext(name, config.extension);
908
952
  const scope = context.create({});
909
- return output(filepath, scope).then(() => {
910
- return scope.getMacro()
911
- })
953
+ return output(filepath, scope).then(() => scope.getMacro())
912
954
  };
913
955
  const render = (name, data) => {
914
956
  const filepath = ext(name, config.extension);
@@ -958,7 +1000,7 @@ function readFile(path, template) {
958
1000
  return new Promise((resolve, reject) => {
959
1001
  fs.readFile(joinPath(path, template), (error, data) => {
960
1002
  if (error) {
961
- reject(error);
1003
+ reject(new TemplateError(error));
962
1004
  } else {
963
1005
  resolve(data.toString());
964
1006
  }
@@ -382,7 +382,7 @@ function Compiler(config) {
382
382
  });
383
383
  });
384
384
  source += `');`;
385
- source = `try{${source}}catch(e){console.info(e)}`;
385
+ source = `try{${source}}catch(e){return ${BUFFER}.error(e)}`;
386
386
  if (compiler.withObject) {
387
387
  source = `with(${SCOPE}){${source}}`;
388
388
  }
@@ -497,10 +497,40 @@ const element = (tag, attrs, content) => {
497
497
  return result.join('')
498
498
  };
499
499
 
500
+ function TemplateError(message) {
501
+ this.code = 1;
502
+ this.name = 'TemplateError';
503
+ this.message = message;
504
+ Error.call(this);
505
+ }
506
+ Object.setPrototypeOf(TemplateNotFound.prototype, Error.prototype);
507
+
508
+ function TemplateNotFound(message) {
509
+ TemplateError.call(this);
510
+ this.code = 404;
511
+ this.name = 'TemplateNotFound';
512
+ this.message = message;
513
+ }
514
+
515
+ Object.setPrototypeOf(TemplateNotFound.prototype, TemplateError.prototype);
516
+
517
+ function TemplateSyntaxError(message) {
518
+ TemplateError.call(this);
519
+ this.code = 500;
520
+ this.name = 'TemplateSyntaxError';
521
+ this.message = message;
522
+ }
523
+
524
+ Object.setPrototypeOf(TemplateSyntaxError.prototype, TemplateError.prototype);
525
+
500
526
  function resolve(list) {
501
527
  return Promise.all(list || []).then((list) => list.join(''))
502
528
  }
503
529
 
530
+ function reject(error) {
531
+ return Promise.reject(new TemplateSyntaxError(error.message))
532
+ }
533
+
504
534
  function createBuffer() {
505
535
  let store = [],
506
536
  array = [];
@@ -520,7 +550,7 @@ function createBuffer() {
520
550
  return resolve(result)
521
551
  };
522
552
  buffer.error = function (e) {
523
- throw e
553
+ return reject(e)
524
554
  };
525
555
  buffer.end = function () {
526
556
  return resolve(array)
@@ -540,7 +570,11 @@ function Context(config) {
540
570
  this.helpers = function (methods) {
541
571
  extend(Scope.prototype, methods || {});
542
572
  };
543
-
573
+ /**
574
+ * @name ContextScope
575
+ * @param data
576
+ * @constructor
577
+ */
544
578
  function Scope(data) {
545
579
  this[BLOCKS] = {};
546
580
  this[MACRO] = {};
@@ -706,8 +740,8 @@ function Context(config) {
706
740
  const prop = path.pop();
707
741
  return hasProp(result, prop) ? result[prop] : defaults
708
742
  },
709
- writable: false,
710
- configurable: false,
743
+ writable: true,
744
+ configurable: true,
711
745
  enumerable: false,
712
746
  },
713
747
  set: {
@@ -776,6 +810,14 @@ function Context(config) {
776
810
  configurable: false,
777
811
  enumerable: false,
778
812
  },
813
+ hasBlock: {
814
+ value(name) {
815
+ return this.getBlocks().hasOwnProperty(name)
816
+ },
817
+ writable: false,
818
+ configurable: false,
819
+ enumerable: false,
820
+ },
779
821
  include: {
780
822
  value(path, data, cx) {
781
823
  const context = cx === false ? {} : this.clone(true);
@@ -879,27 +921,27 @@ function EJS(options) {
879
921
  const cache = new Cache();
880
922
  const template = new Template(config, cache, compiler);
881
923
 
882
- const output = (path, context) => {
924
+ const output = (path, scope) => {
925
+ const { globalHelpers } = config;
883
926
  const params = [
884
- context,
885
- context.getComponent(),
886
- context.getBuffer(),
927
+ scope,
928
+ scope.getComponent(),
929
+ scope.getBuffer(),
887
930
  safeValue,
888
- ];
889
- config.globalHelpers.forEach((name) => {
890
- if (isFunction(context[name]))
891
- params.push(context[name].bind(context));
892
- });
893
- return template.get(path).then(function (callback) {
894
- return callback.apply(context, params)
895
- })
931
+ ].concat(
932
+ globalHelpers
933
+ .filter((name) => isFunction(scope[name]))
934
+ .map((name) => scope[name].bind(scope))
935
+ );
936
+ return template
937
+ .get(path)
938
+ .then((callback) => callback.apply(scope, params))
896
939
  };
940
+
897
941
  const require = (name) => {
898
942
  const filepath = ext(name, config.extension);
899
943
  const scope = context.create({});
900
- return output(filepath, scope).then(() => {
901
- return scope.getMacro()
902
- })
944
+ return output(filepath, scope).then(() => scope.getMacro())
903
945
  };
904
946
  const render = (name, data) => {
905
947
  const filepath = ext(name, config.extension);
@@ -945,22 +987,56 @@ function EJS(options) {
945
987
  return this
946
988
  }
947
989
 
948
- const templates = {};
990
+ const templateCache = {};
991
+
949
992
  const ejs = new EJS({
950
993
  cache: false,
951
994
  withObject: false,
952
995
  resolver(path, name) {
953
- if (name in templates) {
954
- return Promise.resolve(templates[name])
955
- }
956
- return Promise.resolve(['template not found', name])
996
+ return new Promise((resolve, reject) => {
997
+ if (templateCache.hasOwnProperty(name)) {
998
+ resolve(templateCache[name]);
999
+ } else {
1000
+ reject(new TemplateNotFound(`template ${name} not found`));
1001
+ }
1002
+ })
957
1003
  },
958
1004
  });
959
1005
 
960
- async function useTemplates(list) {
961
- Object.assign(templates, list || {});
1006
+ const getOrigin = (url, secure) => {
1007
+ url = new URL(url);
1008
+ if (secure) url.protocol = 'https:';
1009
+ return url.origin
1010
+ };
1011
+
1012
+ function setTemplates(list) {
1013
+ Object.assign(templateCache, list || {});
1014
+ }
1015
+
1016
+ /**
1017
+ * @typedef {Object<string,any>} HonoContext
1018
+ * @property {function(*):Promise<Response>} html
1019
+ * @property {function(name:string,data:{}):Promise<string>} render
1020
+ * @property {function(name:string,data:{}):Promise<string>} ejs
1021
+ * @property {ContextScope} data
1022
+ */
1023
+
1024
+ /**
1025
+ *
1026
+ * @param {Object<string,any>} options
1027
+ * @return {(function(c:Context, next): Promise<any>)|*}
1028
+ */
1029
+ function setRenderer({ secure = true, version = '1.0' }) {
1030
+ return async (c, next) => {
1031
+ c.data = context({});
1032
+ c.data.set('version', version);
1033
+ c.data.set('origin', getOrigin(c.req.url, secure));
1034
+ c.ejs = (name, data) => render(name, Object.assign({}, c.data, data));
1035
+ c.render = (name, data) => c.html(c.ejs(name, data));
1036
+ await next();
1037
+ }
962
1038
  }
963
1039
 
964
1040
  const { render, context, compile, helpers, preload, configure, create } = ejs;
965
1041
 
966
- export { compile, configure, context, create, helpers, preload, render, useTemplates };
1042
+ export { compile, configure, context, create, helpers, preload, render, setRenderer, setTemplates };