@kosatyi/ejs 0.0.76 → 0.0.78

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,7 +11,7 @@ Embedded JavaScript templates with extend/block
11
11
  You can get EJS via [npm](http://npmjs.com).
12
12
 
13
13
  ```bash
14
- $ npm install @kosatyi/ejs --save
14
+ $ npm install @kosatyi/ejs
15
15
  ```
16
16
 
17
17
  ## Usage
package/bin/bundler.js ADDED
@@ -0,0 +1,43 @@
1
+ #! /usr/bin/env node
2
+
3
+ import argv from 'process.argv'
4
+
5
+ import { Bundler } from '../dist/esm/bundler.js'
6
+
7
+ const schema = argv(process.argv.slice(2))
8
+
9
+ const params = schema({
10
+ target: null,
11
+ transform: false,
12
+ timestamp: true,
13
+ minify: false,
14
+ withObject: false,
15
+ export: 'ejsPrecompiled',
16
+ path: 'views',
17
+ extension: 'ejs',
18
+ })
19
+
20
+ if (typeof params.target !== 'string') {
21
+ throw new Error('target is not a string')
22
+ }
23
+
24
+ const options = {
25
+ target: params.target,
26
+ transform: params.transform,
27
+ timestamp: params.timestamp,
28
+ minify: params.minify,
29
+ }
30
+ const config = {
31
+ withObject: params.withObject,
32
+ path: params.path,
33
+ export: params.export,
34
+ extension: params.extension,
35
+ }
36
+
37
+ const bundler = new Bundler(options, config)
38
+
39
+ await bundler.build()
40
+
41
+ if (params.watch && params.path) {
42
+ await bundler.watch()
43
+ }
@@ -308,6 +308,7 @@ function Compiler(config) {
308
308
  BUFFER = _compiler$vars.BUFFER,
309
309
  COMPONENT = _compiler$vars.COMPONENT;
310
310
  var GLOBALS = compiler.globalHelpers;
311
+ content = String(content);
311
312
  if (compiler.rmWhitespace) {
312
313
  content = content.replace(/[\r\n]+/g, '\n').replace(/^\s+|\s+$/gm, '');
313
314
  }
@@ -322,7 +323,7 @@ function Compiler(config) {
322
323
  });
323
324
  });
324
325
  source += "');";
325
- source = "try{".concat(source, "}catch(e){console.info(e)}");
326
+ source = "try{".concat(source, "}catch(e){return ").concat(BUFFER, ".error(e)}");
326
327
  if (compiler.withObject) {
327
328
  source = "with(".concat(SCOPE, "){").concat(source, "}");
328
329
  }
@@ -434,11 +435,36 @@ var element = function element(tag, attrs, content) {
434
435
  return result.join('');
435
436
  };
436
437
 
438
+ function TemplateError(message) {
439
+ this.code = 1;
440
+ this.name = 'TemplateError';
441
+ this.message = message;
442
+ Error.call(this);
443
+ }
444
+ Object.setPrototypeOf(TemplateNotFound.prototype, Error.prototype);
445
+ function TemplateNotFound(message) {
446
+ TemplateError.call(this);
447
+ this.code = 404;
448
+ this.name = 'TemplateNotFound';
449
+ this.message = message;
450
+ }
451
+ Object.setPrototypeOf(TemplateNotFound.prototype, TemplateError.prototype);
452
+ function TemplateSyntaxError(message) {
453
+ TemplateError.call(this);
454
+ this.code = 500;
455
+ this.name = 'TemplateSyntaxError';
456
+ this.message = message;
457
+ }
458
+ Object.setPrototypeOf(TemplateSyntaxError.prototype, TemplateError.prototype);
459
+
437
460
  function resolve(list) {
438
461
  return Promise.all(list || []).then(function (list) {
439
462
  return list.join('');
440
463
  });
441
464
  }
465
+ function reject(error) {
466
+ return Promise.reject(new TemplateSyntaxError(error.message));
467
+ }
442
468
  function createBuffer() {
443
469
  var store = [],
444
470
  array = [];
@@ -458,7 +484,7 @@ function createBuffer() {
458
484
  return resolve(result);
459
485
  };
460
486
  buffer.error = function (e) {
461
- throw e;
487
+ return reject(e);
462
488
  };
463
489
  buffer.end = function () {
464
490
  return resolve(array);
@@ -483,6 +509,11 @@ function Context(config) {
483
509
  this.helpers = function (methods) {
484
510
  extend(Scope.prototype, methods || {});
485
511
  };
512
+ /**
513
+ * @name ContextScope
514
+ * @param data
515
+ * @constructor
516
+ */
486
517
  function Scope(data) {
487
518
  this[BLOCKS] = {};
488
519
  this[MACRO] = {};
@@ -628,8 +659,8 @@ function Context(config) {
628
659
  var prop = path.pop();
629
660
  return hasProp(result, prop) ? result[prop] : defaults;
630
661
  },
631
- writable: false,
632
- configurable: false,
662
+ writable: true,
663
+ configurable: true,
633
664
  enumerable: false
634
665
  }), _defineProperty(_Object$definePropert, "set", {
635
666
  value: function value(name, _value2) {
@@ -769,13 +800,15 @@ function EJS(options) {
769
800
  var compiler = new Compiler(config);
770
801
  var cache = new Cache();
771
802
  var template = new Template(config, cache, compiler);
772
- var output = function output(path, context) {
773
- var params = [context, context.getComponent(), context.getBuffer(), safeValue];
774
- config.globalHelpers.forEach(function (name) {
775
- if (isFunction(context[name])) params.push(context[name].bind(context));
776
- });
803
+ var output = function output(path, scope) {
804
+ var globalHelpers = config.globalHelpers;
805
+ var params = [scope, scope.getComponent(), scope.getBuffer(), safeValue].concat(globalHelpers.filter(function (name) {
806
+ return isFunction(scope[name]);
807
+ }).map(function (name) {
808
+ return scope[name].bind(scope);
809
+ }));
777
810
  return template.get(path).then(function (callback) {
778
- return callback.apply(context, params);
811
+ return callback.apply(scope, params);
779
812
  });
780
813
  };
781
814
  var require = function require(name) {
@@ -836,7 +869,7 @@ var httpRequest = function httpRequest(path, template) {
836
869
  return fetch(joinPath(path, template)).then(function (response) {
837
870
  return response.text();
838
871
  }, function (reason) {
839
- return String(reason);
872
+ return new TemplateError(reason);
840
873
  });
841
874
  };
842
875
 
@@ -0,0 +1,171 @@
1
+ 'use strict';
2
+
3
+ var fs = require('fs');
4
+ var glob = require('glob');
5
+ var path = require('path');
6
+ var terser = require('terser');
7
+ var index_js = require('./index.js');
8
+ var babel = require('@babel/core');
9
+
10
+ const isPlainObject = function (obj) {
11
+ return Object.prototype.toString.call(obj) === '[object Object]'
12
+ };
13
+
14
+ const extend = (target, ...sources) => {
15
+ return Object.assign(target, ...sources.filter(isPlainObject))
16
+ };
17
+
18
+ class Bundler {
19
+ /**
20
+ * @type {BundlerOptions}
21
+ */
22
+ options = {
23
+ target: [],
24
+ transform: true,
25
+ minify: true,
26
+ timestamp: true,
27
+ }
28
+ /**
29
+ * @type {EjsConfig}
30
+ */
31
+ config = {}
32
+ constructor(options, config) {
33
+ extend(this.options, options || {});
34
+ this.config = index_js.configure(config || {});
35
+ this.templates = {};
36
+ }
37
+ stageRead(path$1) {
38
+ return fs.promises
39
+ .readFile(path.join(this.config.path, path$1))
40
+ .then((response) => response.toString())
41
+ }
42
+ stageCompile(content, name) {
43
+ return index_js.compile(content, name).source
44
+ }
45
+ async stageMinify(content) {
46
+ if (this.options.minify === false) return content
47
+ const config = {
48
+ compress: {
49
+ dead_code: false,
50
+ side_effects: false,
51
+ },
52
+ };
53
+ const response = await terser.minify(content, config);
54
+ return response.code
55
+ }
56
+ async stageTransform(content) {
57
+ if (this.options.transform === false) return content
58
+ const config = {
59
+ presets: [['@babel/preset-env']],
60
+ sourceType: 'script',
61
+ };
62
+ const response = await babel.transformAsync(content, config);
63
+ return response.code
64
+ }
65
+ getBundle() {
66
+ const transform = this.options.transform;
67
+ const moduleId = this.config.export;
68
+ const useStrict = this.config.withObject === false;
69
+ const timestamp = this.options.timestamp;
70
+ const out = [];
71
+ if (transform) {
72
+ out.push('(function(global,factory){');
73
+ out.push(
74
+ 'typeof exports === "object" && typeof module !== "undefined" ?'
75
+ );
76
+ out.push('module.exports = factory():');
77
+ out.push(
78
+ 'typeof define === "function" && define.amd ? define(factory):'
79
+ );
80
+ out.push(
81
+ '(global = typeof globalThis !== "undefined" ? globalThis:'
82
+ );
83
+ out.push('global || self,global["' + moduleId + '"] = factory())');
84
+ out.push('})(this,(function(){');
85
+ }
86
+ if (useStrict) out.push("'use strict'");
87
+ if (timestamp) out.push('const timestamp = '.concat(String(Date.now())));
88
+ out.push('const templates = {}');
89
+ Object.entries(this.templates).forEach(([name, content]) => {
90
+ name = JSON.stringify(name);
91
+ content = String(content);
92
+ out.push(`templates[${name}] = ${content}`);
93
+ });
94
+ if (transform) {
95
+ out.push('return templates');
96
+ out.push('}))');
97
+ } else {
98
+ out.push('export default templates');
99
+ }
100
+ return out.join('\n')
101
+ }
102
+ async watch() {
103
+ console.log(`ejs-bundle: watching directory - ${this.config.path}`);
104
+ try {
105
+ const watcher = fs.promises.watch(this.config.path, { recursive: true });
106
+ for await (const { filename } of watcher) {
107
+ if (path.extname(filename).slice(1) === this.config.extension) {
108
+ console.log(`ejs-bundle: file is changed - ${filename}`);
109
+ await this.build();
110
+ }
111
+ }
112
+ } catch (err) {
113
+ throw err
114
+ }
115
+ }
116
+ async build() {
117
+ if (this.buildInProgress === true) return false
118
+ this.buildInProgress = true;
119
+ await this.concat().catch(console.error);
120
+ await this.output().catch(console.error);
121
+ console.log(`ejs-bundle: bundle complete - ${this.options.target}`);
122
+ this.buildInProgress = false;
123
+ }
124
+ async concat() {
125
+ const pattern = '**/*.'.concat(this.config.extension);
126
+ const list = await glob.glob(pattern, { cwd: this.config.path });
127
+ for (let template of list) {
128
+ let content = '';
129
+ content = await this.stageRead(template);
130
+ content = await this.stageCompile(content, template);
131
+ this.templates[template] = content;
132
+ }
133
+ }
134
+ async output() {
135
+ const target = [].concat(this.options.target);
136
+ let content = this.getBundle();
137
+ if (this.options.transform) {
138
+ content = await this.stageTransform(content);
139
+ }
140
+ if (this.options.minify) {
141
+ content = await this.stageMinify(content);
142
+ }
143
+ for (let file of target) {
144
+ const folderPath = path.dirname(file);
145
+ const folderExists = await fs.promises
146
+ .stat(folderPath)
147
+ .then(() => true)
148
+ .catch(() => false);
149
+ if (folderExists === false) {
150
+ await fs.promises.mkdir(folderPath, { recursive: true });
151
+ }
152
+ await fs.promises.writeFile(file, content);
153
+ }
154
+ }
155
+ }
156
+
157
+ const ejsBundle = (options, config) => {
158
+ const bundler = new Bundler(options, config);
159
+ return {
160
+ name: 'ejs-bundle',
161
+ async buildStart() {
162
+ await bundler.concat();
163
+ },
164
+ async buildEnd() {
165
+ await bundler.output();
166
+ },
167
+ }
168
+ };
169
+
170
+ exports.Bundler = Bundler;
171
+ exports.ejsBundle = ejsBundle;
package/dist/cjs/index.js CHANGED
@@ -311,6 +311,7 @@ function Compiler(config) {
311
311
  BUFFER = _compiler$vars.BUFFER,
312
312
  COMPONENT = _compiler$vars.COMPONENT;
313
313
  var GLOBALS = compiler.globalHelpers;
314
+ content = String(content);
314
315
  if (compiler.rmWhitespace) {
315
316
  content = content.replace(/[\r\n]+/g, '\n').replace(/^\s+|\s+$/gm, '');
316
317
  }
@@ -325,7 +326,7 @@ function Compiler(config) {
325
326
  });
326
327
  });
327
328
  source += "');";
328
- source = "try{".concat(source, "}catch(e){console.info(e)}");
329
+ source = "try{".concat(source, "}catch(e){return ").concat(BUFFER, ".error(e)}");
329
330
  if (compiler.withObject) {
330
331
  source = "with(".concat(SCOPE, "){").concat(source, "}");
331
332
  }
@@ -437,11 +438,36 @@ var element = function element(tag, attrs, content) {
437
438
  return result.join('');
438
439
  };
439
440
 
441
+ function TemplateError(message) {
442
+ this.code = 1;
443
+ this.name = 'TemplateError';
444
+ this.message = message;
445
+ Error.call(this);
446
+ }
447
+ Object.setPrototypeOf(TemplateNotFound.prototype, Error.prototype);
448
+ function TemplateNotFound(message) {
449
+ TemplateError.call(this);
450
+ this.code = 404;
451
+ this.name = 'TemplateNotFound';
452
+ this.message = message;
453
+ }
454
+ Object.setPrototypeOf(TemplateNotFound.prototype, TemplateError.prototype);
455
+ function TemplateSyntaxError(message) {
456
+ TemplateError.call(this);
457
+ this.code = 500;
458
+ this.name = 'TemplateSyntaxError';
459
+ this.message = message;
460
+ }
461
+ Object.setPrototypeOf(TemplateSyntaxError.prototype, TemplateError.prototype);
462
+
440
463
  function resolve(list) {
441
464
  return Promise.all(list || []).then(function (list) {
442
465
  return list.join('');
443
466
  });
444
467
  }
468
+ function reject(error) {
469
+ return Promise.reject(new TemplateSyntaxError(error.message));
470
+ }
445
471
  function createBuffer() {
446
472
  var store = [],
447
473
  array = [];
@@ -461,7 +487,7 @@ function createBuffer() {
461
487
  return resolve(result);
462
488
  };
463
489
  buffer.error = function (e) {
464
- throw e;
490
+ return reject(e);
465
491
  };
466
492
  buffer.end = function () {
467
493
  return resolve(array);
@@ -486,6 +512,11 @@ function Context(config) {
486
512
  this.helpers = function (methods) {
487
513
  extend(Scope.prototype, methods || {});
488
514
  };
515
+ /**
516
+ * @name ContextScope
517
+ * @param data
518
+ * @constructor
519
+ */
489
520
  function Scope(data) {
490
521
  this[BLOCKS] = {};
491
522
  this[MACRO] = {};
@@ -631,8 +662,8 @@ function Context(config) {
631
662
  var prop = path.pop();
632
663
  return hasProp(result, prop) ? result[prop] : defaults;
633
664
  },
634
- writable: false,
635
- configurable: false,
665
+ writable: true,
666
+ configurable: true,
636
667
  enumerable: false
637
668
  }), _defineProperty(_Object$definePropert, "set", {
638
669
  value: function value(name, _value2) {
@@ -772,13 +803,15 @@ function EJS(options) {
772
803
  var compiler = new Compiler(config);
773
804
  var cache = new Cache();
774
805
  var template = new Template(config, cache, compiler);
775
- var output = function output(path, context) {
776
- var params = [context, context.getComponent(), context.getBuffer(), safeValue];
777
- config.globalHelpers.forEach(function (name) {
778
- if (isFunction(context[name])) params.push(context[name].bind(context));
779
- });
806
+ var output = function output(path, scope) {
807
+ var globalHelpers = config.globalHelpers;
808
+ var params = [scope, scope.getComponent(), scope.getBuffer(), safeValue].concat(globalHelpers.filter(function (name) {
809
+ return isFunction(scope[name]);
810
+ }).map(function (name) {
811
+ return scope[name].bind(scope);
812
+ }));
780
813
  return template.get(path).then(function (callback) {
781
- return callback.apply(context, params);
814
+ return callback.apply(scope, params);
782
815
  });
783
816
  };
784
817
  var require = function require(name) {
@@ -839,7 +872,7 @@ function readFile(path, template) {
839
872
  return new Promise(function (resolve, reject) {
840
873
  fs.readFile(joinPath(path, template), function (error, data) {
841
874
  if (error) {
842
- reject(error);
875
+ reject(new TemplateError(error));
843
876
  } else {
844
877
  resolve(data.toString());
845
878
  }