node-tao 0.0.5 → 1.0.1

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/tao.js CHANGED
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.Tao = void 0;
7
7
  const default_config_1 = require("./default-config");
8
- const checks_1 = require("./checks");
8
+ const validations_1 = require("./validations");
9
9
  const templates_access_1 = require("./templates-access");
10
10
  const node_fs_1 = __importDefault(require("node:fs"));
11
11
  const utils_1 = require("./utils");
@@ -16,38 +16,40 @@ const node_path_1 = __importDefault(require("node:path"));
16
16
  const node_perf_hooks_1 = require("node:perf_hooks");
17
17
  const metrics_1 = require("./metrics");
18
18
  const init_1 = require("./init");
19
- const parsing_helpers_1 = require("./parsing-helpers");
20
19
  class Tao {
20
+ config;
21
+ templatePaths = [];
22
+ /**
23
+ * Stores already compiled templates.
24
+ */
25
+ compiledStore = new store_1.Store();
26
+ /**
27
+ * Stores dynamically loaded templates.
28
+ */
29
+ dynamictemplatesStore = new store_1.Store();
30
+ /**
31
+ * Stores global helpers.
32
+ */
33
+ helpersStore = new store_1.Store();
34
+ /**
35
+ * Metrics - DX
36
+ */
37
+ parentTemplate = '';
38
+ /**
39
+ * Metrics - DX
40
+ */
41
+ childrenStore = new store_1.Store();
21
42
  constructor(customConfig = {}) {
22
- this.templatePaths = [];
23
- this.prefixBuild = '';
24
- /**
25
- * Stores already compiled templates.
26
- */
27
- this.compiledStore = new store_1.Store();
28
- /**
29
- * Stores dynamically loaded templates.
30
- */
31
- this.dynamictemplatesStore = new store_1.Store();
32
- /**
33
- * Stores global helpers.
34
- */
35
- this.helpersStore = new store_1.Store();
36
- // Metrics - DX
37
- this.parentTemplate = '';
38
- // Metrics - DX
39
- this.childrenStore = new store_1.Store();
40
- this.config = Object.assign(Object.assign({}, default_config_1.defaultConfig), customConfig);
43
+ this.config = { ...default_config_1.defaultConfig, ...customConfig };
41
44
  this.initializeConfig();
42
45
  }
43
46
  initializeConfig() {
44
47
  const { views, extension, tags, parse } = this.config;
45
48
  this.config.tags = (0, init_1.assignTags)(tags);
46
49
  this.config.parse = (0, init_1.assignParse)(parse);
47
- this.config.extension = (0, checks_1.trimDotFromExtension)(extension);
48
- (0, checks_1.checkOpeningAndClosingTag)(this.config.tags);
49
- (0, checks_1.checkPrefixTemplateTags)(this.config.parse);
50
- this.prefixBuild = (0, utils_1.buildPrefixRegex)(this.config.parse);
50
+ this.config.extension = (0, validations_1.trimDotFromExtension)(extension);
51
+ (0, validations_1.checkOpeningAndClosingTag)(this.config.tags);
52
+ (0, validations_1.checkPrefixTemplateTags)(this.config.parse);
51
53
  this.templatePaths = (0, templates_access_1.getFilesFromDirectory)(views, this.config.extension);
52
54
  }
53
55
  /**
@@ -66,8 +68,8 @@ class Tao {
66
68
  };
67
69
  return metricsData;
68
70
  }
69
- compileChild(content, debugData) {
70
- const compiledAST = this.parse(content, debugData);
71
+ compileChild(content) {
72
+ const compiledAST = this.templateLexer(content);
71
73
  const result = `
72
74
  ${(0, utils_1.includeFn)()}
73
75
 
@@ -82,9 +84,9 @@ class Tao {
82
84
  `;
83
85
  return result;
84
86
  }
85
- compile(content, filename, debugData) {
87
+ compile(content, filename) {
86
88
  const { development } = this.config;
87
- const compiledAST = this.parse(content, debugData);
89
+ const compiledAST = this.templateLexer(content);
88
90
  this.childrenStore.set(this.parentTemplate, []);
89
91
  const metricsData = this.getMetrics(filename);
90
92
  const result = `
@@ -106,82 +108,201 @@ class Tao {
106
108
  `;
107
109
  return result;
108
110
  }
109
- parse(expression, debugData) {
111
+ /**
112
+ * A basic lexer covering most of the edge cases (quotes, comments, template literals, nested templates, etc.) to parse the template into an array of TemplateData containing the line information, start and end positions.
113
+ */
114
+ templateLexer(rawExpression) {
110
115
  const { parse, tags } = this.config;
111
- const { closing, opening } = tags;
112
- let openingResult = null;
113
- const compiledData = [];
114
- let lastIndex = 0;
115
- const parseOpenReg = new RegExp((0, utils_1.escapeRegExp)(opening) + '\\s*(' + this.prefixBuild + ')?\\s*', 'g');
116
- const parseCloseReg = new RegExp('\'|"|`|(\\s*' + (0, utils_1.escapeRegExp)(closing) + ')', 'g');
117
- while ((openingResult = parseOpenReg.exec(expression))) {
118
- // openingPrefix by default either ~, =, or empty
119
- const [originalOpen, openingPrefix = ''] = openingResult;
120
- let closeResult = null;
121
- let templateData = undefined;
122
- const precedingExpression = expression.slice(lastIndex, openingResult.index);
123
- lastIndex = originalOpen.length + openingResult.index;
124
- const escapedExpression = (0, utils_1.escapeJSLiteral)(precedingExpression);
125
- compiledData.push(escapedExpression);
126
- parseCloseReg.lastIndex = lastIndex;
127
- while ((closeResult = parseCloseReg.exec(expression))) {
128
- const [originalClose, closePrefix] = closeResult;
129
- if (closePrefix) {
130
- const content = expression.slice(lastIndex, closeResult.index);
131
- lastIndex = parseCloseReg.lastIndex;
132
- parseOpenReg.lastIndex = lastIndex;
133
- const currentType = (0, utils_1.getCurrentPrefixType)(openingPrefix, parse);
134
- templateData = { type: currentType, content };
135
- compiledData.push(templateData);
116
+ const { opening, closing } = tags;
117
+ const errorType = 'Parse Error';
118
+ const tokens = [];
119
+ let index = 0;
120
+ let line = 1;
121
+ const openingLength = opening.length;
122
+ const closingLength = closing.length;
123
+ const updatePosition = (char) => {
124
+ if (char === '\n')
125
+ line++;
126
+ };
127
+ while (index < rawExpression.length) {
128
+ const openIndex = rawExpression.indexOf(opening, index);
129
+ // Text after the last opening tag
130
+ if (openIndex === -1) {
131
+ const text = rawExpression.slice(index);
132
+ tokens.push({
133
+ type: null,
134
+ value: (0, utils_1.escapeJSLiteral)(text),
135
+ line,
136
+ startPos: index,
137
+ endPos: rawExpression.length,
138
+ });
139
+ break;
140
+ }
141
+ // Text before an opening tag
142
+ if (openIndex > index) {
143
+ const text = rawExpression.slice(index, openIndex);
144
+ if (text.length > 0) {
145
+ tokens.push({
146
+ type: null,
147
+ value: (0, utils_1.escapeJSLiteral)(text),
148
+ line,
149
+ startPos: index,
150
+ endPos: openIndex,
151
+ });
152
+ }
153
+ }
154
+ // advance position until openIndex
155
+ while (index < openIndex) {
156
+ updatePosition(rawExpression[index]);
157
+ index++;
158
+ }
159
+ const blockLine = line;
160
+ let cursor = openIndex + openingLength;
161
+ const mode = (0, utils_1.getCurrentPrefixType)(rawExpression[cursor].trim(), parse);
162
+ if (mode !== null) {
163
+ cursor++;
164
+ }
165
+ const contentStart = cursor;
166
+ let inSingle = false;
167
+ let inDouble = false;
168
+ let inBacktick = false;
169
+ let inLineComment = false;
170
+ let inBlockComment = false;
171
+ let escaped = false;
172
+ let singleQuoteStart = null;
173
+ let doubleQuoteStart = null;
174
+ let backtickStart = null;
175
+ let blockCommentStart = null;
176
+ while (cursor < rawExpression.length) {
177
+ const char = rawExpression[cursor];
178
+ const next = rawExpression[cursor + 1];
179
+ updatePosition(char);
180
+ if (escaped) {
181
+ escaped = false;
182
+ cursor++;
183
+ continue;
184
+ }
185
+ if (char === '\\') {
186
+ escaped = true;
187
+ cursor++;
188
+ continue;
189
+ }
190
+ if (inLineComment) {
191
+ if (char === '\n')
192
+ inLineComment = false;
193
+ cursor++;
194
+ continue;
195
+ }
196
+ if (inBlockComment) {
197
+ if (char === '*' && next === '/') {
198
+ inBlockComment = false;
199
+ blockCommentStart = null;
200
+ cursor += 2;
201
+ continue;
202
+ }
203
+ cursor++;
204
+ continue;
205
+ }
206
+ if (!inSingle && !inDouble && !inBacktick) {
207
+ if (char === '/' && next === '/') {
208
+ inLineComment = true;
209
+ cursor += 2;
210
+ continue;
211
+ }
212
+ if (char === '/' && next === '*') {
213
+ inBlockComment = true;
214
+ blockCommentStart = { line };
215
+ cursor += 2;
216
+ continue;
217
+ }
218
+ }
219
+ if (!inDouble && !inBacktick && char === "'") {
220
+ inSingle = !inSingle;
221
+ singleQuoteStart = inSingle ? { line } : null;
222
+ cursor++;
223
+ continue;
224
+ }
225
+ if (!inSingle && !inBacktick && char === '"') {
226
+ inDouble = !inDouble;
227
+ doubleQuoteStart = inDouble ? { line } : null;
228
+ cursor++;
229
+ continue;
230
+ }
231
+ if (!inSingle && !inDouble && char === '`') {
232
+ inBacktick = !inBacktick;
233
+ backtickStart = inBacktick ? { line } : null;
234
+ cursor++;
235
+ continue;
236
+ }
237
+ if (!inSingle &&
238
+ !inDouble &&
239
+ !inBacktick &&
240
+ !inLineComment &&
241
+ !inBlockComment &&
242
+ rawExpression.startsWith(closing, cursor)) {
136
243
  break;
137
244
  }
138
- parseCloseReg.lastIndex = (0, parsing_helpers_1.handleQuotes)(expression, originalClose, closeResult.index, debugData.fileContent);
245
+ cursor++;
246
+ }
247
+ if (inSingle) {
248
+ const error = (0, error_utils_1.buildErrorData)('Unclosed single quote', singleQuoteStart.line, rawExpression, errorType);
249
+ throw error;
139
250
  }
140
- (0, parsing_helpers_1.checkForUnclosedPrefix)(templateData, expression, originalOpen, openingResult.index, debugData.fileContent);
251
+ if (inDouble) {
252
+ const error = (0, error_utils_1.buildErrorData)('Unclosed double quote', doubleQuoteStart.line, rawExpression, errorType);
253
+ throw error;
254
+ }
255
+ if (inBacktick) {
256
+ const error = (0, error_utils_1.buildErrorData)('Unclosed backtick', backtickStart.line, rawExpression, errorType);
257
+ throw error;
258
+ }
259
+ if (inBlockComment) {
260
+ const error = (0, error_utils_1.buildErrorData)('Unclosed block comment', blockCommentStart.line, rawExpression, errorType);
261
+ throw error;
262
+ }
263
+ if (cursor >= rawExpression.length) {
264
+ const error = (0, error_utils_1.buildErrorData)(`Unclosed template block ${closing}`, line, rawExpression, errorType);
265
+ throw error;
266
+ }
267
+ const content = rawExpression.slice(contentStart, cursor).trim();
268
+ tokens.push({
269
+ type: mode,
270
+ value: content,
271
+ line: blockLine,
272
+ startPos: contentStart,
273
+ endPos: cursor,
274
+ });
275
+ index = cursor + closingLength;
141
276
  }
142
- const endOfTemplate = expression.slice(lastIndex);
143
- const escapedEndOfTemplate = (0, utils_1.escapeJSLiteral)(endOfTemplate);
144
- compiledData.push(escapedEndOfTemplate);
145
- return compiledData;
277
+ return tokens;
146
278
  }
147
279
  /**
148
280
  * Render a template with data and helpers.
149
281
  * @param template The path of your template to render.
150
- * @param data The variables to inject.
151
- * @param helpers The helpers functions to inject.
282
+ * @param dataOrHelpers The variables and helpers to inject.
152
283
  */
153
- render(template, data = {}, helpers = {}) {
284
+ render(template, dataOrHelpers = {}) {
154
285
  const debugData = (0, init_1.initDebugData)();
155
286
  if (typeof template !== 'string') {
156
287
  const error = (0, error_utils_1.handleWrongTypeOfTemplate)(template);
157
288
  const { errorHTML } = this.manageError(error, template, debugData);
158
289
  return errorHTML;
159
290
  }
160
- const { views, extension, fileResolution, development } = this.config;
291
+ const { views, extension, fileResolution } = this.config;
161
292
  const ɵɵstart = node_perf_hooks_1.performance.now();
162
293
  let ɵɵcacheHit = false;
163
- const pathWithExtension = (0, checks_1.getPathWithExtension)(template, extension);
294
+ const pathWithExtension = (0, validations_1.getPathWithExtension)(template, extension);
164
295
  const filename = (0, utils_1.getFileName)(pathWithExtension);
165
296
  const fullPath = (0, utils_1.getResolvedPath)(views, pathWithExtension, fileResolution);
166
297
  this.parentTemplate = filename;
167
298
  this.childrenStore.remove(this.parentTemplate);
168
- const injectedData = {
169
- development,
170
- fullPath,
171
- data,
172
- helpers,
173
- helpersStore: this.helpersStore,
174
- templatePaths: this.templatePaths,
175
- };
176
- (0, utils_1.injectUserDataForVSCodeExtension)(injectedData);
177
- if ((0, checks_1.isTemplateDynamicallyDefined)(template)) {
299
+ if ((0, validations_1.isTemplateDynamicallyDefined)(template)) {
178
300
  const cachedTemplate = this.compiledStore.get(template);
179
301
  if (cachedTemplate) {
180
302
  ɵɵcacheHit = true;
181
303
  const executeData = {
182
304
  compiledContent: cachedTemplate,
183
- data,
184
- helpers,
305
+ dataOrHelpers,
185
306
  ɵɵstart,
186
307
  filename: template,
187
308
  ɵɵcacheHit,
@@ -196,8 +317,7 @@ class Tao {
196
317
  }
197
318
  const templateData = {
198
319
  templateLoaded,
199
- data,
200
- helpers,
320
+ dataOrHelpers,
201
321
  ɵɵstart,
202
322
  filename: template,
203
323
  ɵɵcacheHit,
@@ -210,7 +330,7 @@ class Tao {
210
330
  return errorHTML;
211
331
  }
212
332
  const files = (0, templates_access_1.checkAccessPermission)(this.templatePaths, fullPath);
213
- if (!(0, templates_access_1.fileIsUnique)(files)) {
333
+ if (files.length !== 1) {
214
334
  const error = (0, error_utils_1.handleNonUniqueFile)(files, filename);
215
335
  const { errorHTML } = this.manageError(error, filename, debugData);
216
336
  return errorHTML;
@@ -220,8 +340,7 @@ class Tao {
220
340
  ɵɵcacheHit = true;
221
341
  const executeData = {
222
342
  compiledContent: cachedTemplate,
223
- data,
224
- helpers,
343
+ dataOrHelpers,
225
344
  ɵɵstart,
226
345
  filename,
227
346
  ɵɵcacheHit,
@@ -233,8 +352,7 @@ class Tao {
233
352
  const compileData = {
234
353
  filename,
235
354
  fullPath: file,
236
- data,
237
- helpers,
355
+ dataOrHelpers,
238
356
  ɵɵstart,
239
357
  ɵɵcacheHit,
240
358
  };
@@ -243,34 +361,24 @@ class Tao {
243
361
  /**
244
362
  * Render a child component. Called inside the parent template.
245
363
  */
246
- renderChild(template, data = {}, helpers = {}) {
364
+ renderChild(template, dataOrHelpers = {}) {
247
365
  const debugData = (0, init_1.initDebugData)();
248
366
  if (typeof template !== 'string') {
249
367
  const error = (0, error_utils_1.handleWrongTypeOfTemplate)(template);
250
368
  const errorData = this.handleChildError(error, template, debugData);
251
369
  return errorData;
252
370
  }
253
- const { views, extension, fileResolution, development } = this.config;
254
- const pathWithExtension = (0, checks_1.getPathWithExtension)(template, extension);
371
+ const { views, extension, fileResolution } = this.config;
372
+ const pathWithExtension = (0, validations_1.getPathWithExtension)(template, extension);
255
373
  const filename = (0, utils_1.getFileName)(pathWithExtension);
256
374
  const fullPath = (0, utils_1.getResolvedPath)(views, pathWithExtension, fileResolution);
257
375
  (0, metrics_1.updateChildrenStore)(this.childrenStore, filename, this.parentTemplate, this.config.development);
258
- const injectedData = {
259
- development,
260
- fullPath,
261
- data,
262
- helpers,
263
- helpersStore: this.helpersStore,
264
- templatePaths: this.templatePaths,
265
- };
266
- (0, utils_1.injectUserDataForVSCodeExtension)(injectedData);
267
- if ((0, checks_1.isTemplateDynamicallyDefined)(template)) {
376
+ if ((0, validations_1.isTemplateDynamicallyDefined)(template)) {
268
377
  const cachedTemplate = this.compiledStore.get(template);
269
378
  if (cachedTemplate) {
270
379
  const executeData = {
271
380
  compiledContent: cachedTemplate,
272
- data,
273
- helpers,
381
+ dataOrHelpers,
274
382
  filename: template,
275
383
  };
276
384
  return this.executeChildFunction(executeData, debugData);
@@ -283,14 +391,13 @@ class Tao {
283
391
  }
284
392
  const templateData = {
285
393
  templateLoaded,
286
- data,
287
- helpers,
394
+ dataOrHelpers,
288
395
  filename: template,
289
396
  };
290
397
  return this.handleLoadedChildTemplate(templateData, debugData);
291
398
  }
292
399
  const files = (0, templates_access_1.checkAccessPermission)(this.templatePaths, fullPath);
293
- if (!(0, templates_access_1.fileIsUnique)(files)) {
400
+ if (files.length !== 1) {
294
401
  const error = (0, error_utils_1.handleNonUniqueFile)(files, filename);
295
402
  const errorData = this.handleChildError(error, filename, debugData);
296
403
  return errorData;
@@ -299,8 +406,7 @@ class Tao {
299
406
  if (cachedTemplate) {
300
407
  const executeData = {
301
408
  compiledContent: cachedTemplate,
302
- data,
303
- helpers,
409
+ dataOrHelpers,
304
410
  filename,
305
411
  };
306
412
  return this.executeChildFunction(executeData, debugData);
@@ -309,17 +415,16 @@ class Tao {
309
415
  const compileData = {
310
416
  filename,
311
417
  fullPath: file,
312
- data,
313
- helpers,
418
+ dataOrHelpers,
314
419
  };
315
420
  return this.compileAndExecuteChild(compileData, debugData);
316
421
  }
317
422
  compileAndExecuteChild(compileData, debugData) {
318
- const { data, filename, fullPath, helpers } = compileData;
423
+ const { dataOrHelpers, filename, fullPath } = compileData;
319
424
  try {
320
- const templateFn = this.readChildFileAndGetCompiledFn(fullPath, data, helpers, filename, debugData);
321
- const immutableData = structuredClone(data);
322
- const html = templateFn.call(this, immutableData, helpers);
425
+ const templateFn = this.readChildFileAndGetCompiledFn(fullPath, dataOrHelpers, filename, debugData);
426
+ const { data, helpers } = (0, utils_1.cloneData)(dataOrHelpers);
427
+ const html = templateFn.call(this, data, helpers);
323
428
  return html;
324
429
  }
325
430
  catch (error) {
@@ -328,11 +433,11 @@ class Tao {
328
433
  }
329
434
  }
330
435
  compileAndExecute(compileData, debugData) {
331
- const { data, filename, fullPath, helpers, ɵɵstart, ɵɵcacheHit } = compileData;
436
+ const { dataOrHelpers, filename, fullPath, ɵɵstart, ɵɵcacheHit } = compileData;
332
437
  try {
333
- const templateFn = this.readFileAndGetCompiledFn(fullPath, data, helpers, filename, debugData);
334
- const immutableData = structuredClone(data);
335
- const html = templateFn.call(this, immutableData, helpers, ɵɵstart, ɵɵcacheHit);
438
+ const templateFn = this.readFileAndGetCompiledFn(fullPath, dataOrHelpers, filename, debugData);
439
+ const { data, helpers } = (0, utils_1.cloneData)(dataOrHelpers);
440
+ const html = templateFn.call(this, data, helpers, ɵɵstart, ɵɵcacheHit);
336
441
  return html;
337
442
  }
338
443
  catch (error) {
@@ -344,22 +449,21 @@ class Tao {
344
449
  }
345
450
  }
346
451
  manageError(error, filename, debugData) {
347
- // this.compiledStore.remove(filename); => pourquoi ?
348
452
  error.filename = filename;
349
453
  const errorData = this.handleErrorMessage(error, debugData);
350
- console.error(new Error(`Error in ${filename}: ${errorData.message}`));
351
454
  const errorHTML = this.initErrorTemplate(errorData);
352
455
  errorData.errorHTML = errorHTML;
456
+ (0, error_utils_1.logger)('error', `Error in ${filename}: ${errorData.message} at line ${errorData.lineNumber}`);
353
457
  return errorData;
354
458
  }
355
459
  executeChildFunction(executeData, debugData) {
356
- const { data, filename, helpers, compiledContent } = executeData;
460
+ const { dataOrHelpers, filename, compiledContent } = executeData;
357
461
  try {
358
- const immutableData = structuredClone(data);
359
- const contentReplaced = (0, utils_1.injectDataAndHelpersInTemplate)(data, helpers, this.helpersStore, compiledContent);
462
+ const contentReplaced = (0, utils_1.injectDataAndHelpersInTemplate)(dataOrHelpers, this.helpersStore, compiledContent);
360
463
  debugData.compiledAnonymousFnContent = contentReplaced;
361
464
  const templateFn = (0, utils_1.compileChildToFunction)(contentReplaced);
362
- const html = templateFn.call(this, immutableData, helpers);
465
+ const { data, helpers } = (0, utils_1.cloneData)(dataOrHelpers);
466
+ const html = templateFn.call(this, data, helpers);
363
467
  return html;
364
468
  }
365
469
  catch (error) {
@@ -377,13 +481,13 @@ class Tao {
377
481
  return errorData;
378
482
  }
379
483
  executeFunction(executeData, debugData) {
380
- const { data, filename, helpers, ɵɵstart, compiledContent, ɵɵcacheHit } = executeData;
484
+ const { dataOrHelpers, filename, ɵɵstart, compiledContent, ɵɵcacheHit } = executeData;
381
485
  try {
382
- const immutableData = structuredClone(data);
383
- const contentReplaced = (0, utils_1.injectDataAndHelpersInTemplate)(data, helpers, this.helpersStore, compiledContent);
486
+ const { data, helpers } = (0, utils_1.cloneData)(dataOrHelpers);
487
+ const contentReplaced = (0, utils_1.injectDataAndHelpersInTemplate)(dataOrHelpers, this.helpersStore, compiledContent);
384
488
  debugData.compiledAnonymousFnContent = contentReplaced;
385
489
  const templateFn = (0, utils_1.compileToFunction)(contentReplaced);
386
- const html = templateFn.call(this, immutableData, helpers, ɵɵstart, ɵɵcacheHit);
490
+ const html = templateFn.call(this, data, helpers, ɵɵstart, ɵɵcacheHit);
387
491
  return html;
388
492
  }
389
493
  catch (error) {
@@ -395,7 +499,6 @@ class Tao {
395
499
  }
396
500
  }
397
501
  handleErrorMessage(error, debugData) {
398
- var _a;
399
502
  const [finalMessage, fileContentPerLine, correctedLineNumber] = (0, error_utils_1.findOriginalLineNumberWithMessage)(error, debugData.compiledAnonymousFnContent, debugData.fileContent);
400
503
  const errorData = {
401
504
  filename: error.filename,
@@ -403,7 +506,7 @@ class Tao {
403
506
  message: finalMessage,
404
507
  lineNumber: correctedLineNumber,
405
508
  // Execution error is the last possible error
406
- type: (_a = error.type) !== null && _a !== void 0 ? _a : 'Execution Error',
509
+ type: error.type ?? 'Execution Error',
407
510
  isAChildError: false,
408
511
  errorHTML: '',
409
512
  };
@@ -412,38 +515,38 @@ class Tao {
412
515
  initErrorTemplate(errorData) {
413
516
  if (!this.config.development)
414
517
  return '';
415
- const templatesPath = node_path_1.default.join(__dirname, 'error');
518
+ const templatesPath = node_path_1.default.join(__dirname);
416
519
  const tao = new Tao({ views: templatesPath });
417
520
  return tao.render('error', errorData);
418
521
  }
419
- compileChildAndCache(content, filename, debugData) {
420
- const compiledContent = this.compileChild(content, debugData);
522
+ compileChildAndCache(content, filename) {
523
+ const compiledContent = this.compileChild(content);
421
524
  if (this.config.cache) {
422
525
  this.compiledStore.set(filename, compiledContent);
423
526
  }
424
527
  return compiledContent;
425
528
  }
426
- compileAndCache(content, filename, debugData) {
427
- const compiledContent = this.compile(content, filename, debugData);
529
+ compileAndCache(content, filename) {
530
+ const compiledContent = this.compile(content, filename);
428
531
  if (this.config.cache) {
429
532
  this.compiledStore.set(filename, compiledContent);
430
533
  }
431
534
  return compiledContent;
432
535
  }
433
- readChildFileAndGetCompiledFn(resolvedPath, data, helpers, filename, debugData) {
536
+ readChildFileAndGetCompiledFn(resolvedPath, dataOrHelpers, filename, debugData) {
434
537
  const content = this.readFile(resolvedPath);
435
538
  debugData.fileContent = content;
436
- const compiledContent = this.compileChildAndCache(content, filename, debugData);
437
- const contentReplaced = (0, utils_1.injectDataAndHelpersInTemplate)(data, helpers, this.helpersStore, compiledContent);
539
+ const compiledContent = this.compileChildAndCache(content, filename);
540
+ const contentReplaced = (0, utils_1.injectDataAndHelpersInTemplate)(dataOrHelpers, this.helpersStore, compiledContent);
438
541
  debugData.compiledAnonymousFnContent = contentReplaced;
439
542
  const templateFn = (0, utils_1.compileChildToFunction)(contentReplaced);
440
543
  return templateFn;
441
544
  }
442
- readFileAndGetCompiledFn(resolvedPath, data, helpers, filename, debugData) {
545
+ readFileAndGetCompiledFn(resolvedPath, dataOrHelpers, filename, debugData) {
443
546
  const content = this.readFile(resolvedPath);
444
547
  debugData.fileContent = content;
445
- const compiledContent = this.compileAndCache(content, filename, debugData);
446
- const contentReplaced = (0, utils_1.injectDataAndHelpersInTemplate)(data, helpers, this.helpersStore, compiledContent);
548
+ const compiledContent = this.compileAndCache(content, filename);
549
+ const contentReplaced = (0, utils_1.injectDataAndHelpersInTemplate)(dataOrHelpers, this.helpersStore, compiledContent);
447
550
  debugData.compiledAnonymousFnContent = contentReplaced;
448
551
  const templateFn = (0, utils_1.compileToFunction)(contentReplaced);
449
552
  return templateFn;
@@ -467,12 +570,12 @@ class Tao {
467
570
  * Handle dynamically defined templates
468
571
  */
469
572
  handleLoadedTemplate(templateData, debugData) {
470
- const { data, filename, helpers, ɵɵstart, ɵɵcacheHit } = templateData;
573
+ const { dataOrHelpers, filename, ɵɵstart, ɵɵcacheHit } = templateData;
471
574
  try {
575
+ const { data, helpers } = (0, utils_1.cloneData)(dataOrHelpers);
472
576
  const contentReplaced = this.compileLoadedTemplate(templateData, debugData);
473
577
  const templateFn = (0, utils_1.compileToFunction)(contentReplaced);
474
- const immutableData = structuredClone(data);
475
- const html = templateFn.call(this, immutableData, helpers, ɵɵstart, ɵɵcacheHit);
578
+ const html = templateFn.call(this, data, helpers, ɵɵstart, ɵɵcacheHit);
476
579
  return html;
477
580
  }
478
581
  catch (error) {
@@ -484,12 +587,12 @@ class Tao {
484
587
  }
485
588
  }
486
589
  handleLoadedChildTemplate(templateData, debugData) {
487
- const { data, filename, helpers } = templateData;
590
+ const { dataOrHelpers, filename } = templateData;
488
591
  try {
489
592
  const contentReplaced = this.compileLoadedChildTemplate(templateData, debugData);
490
593
  const templateFn = (0, utils_1.compileChildToFunction)(contentReplaced);
491
- const immutableData = structuredClone(data);
492
- const html = templateFn.call(this, immutableData, helpers);
594
+ const { data, helpers } = (0, utils_1.cloneData)(dataOrHelpers);
595
+ const html = templateFn.call(this, data, helpers);
493
596
  return html;
494
597
  }
495
598
  catch (error) {
@@ -501,16 +604,16 @@ class Tao {
501
604
  * Handle dynamically defined templates
502
605
  */
503
606
  compileLoadedTemplate(templateData, debugData) {
504
- const { data, filename, helpers, templateLoaded: content } = templateData;
505
- const compiledContent = this.compileAndCache(content, filename, debugData);
506
- const contentReplaced = (0, utils_1.injectDataAndHelpersInTemplate)(data, helpers, this.helpersStore, compiledContent);
607
+ const { dataOrHelpers, filename, templateLoaded: content } = templateData;
608
+ const compiledContent = this.compileAndCache(content, filename);
609
+ const contentReplaced = (0, utils_1.injectDataAndHelpersInTemplate)(dataOrHelpers, this.helpersStore, compiledContent);
507
610
  debugData.compiledAnonymousFnContent = contentReplaced;
508
611
  return contentReplaced;
509
612
  }
510
613
  compileLoadedChildTemplate(templateData, debugData) {
511
- const { data, filename, helpers, templateLoaded: content } = templateData;
512
- const compiledContent = this.compileChildAndCache(content, filename, debugData);
513
- const contentReplaced = (0, utils_1.injectDataAndHelpersInTemplate)(data, helpers, this.helpersStore, compiledContent);
614
+ const { dataOrHelpers, filename, templateLoaded: content } = templateData;
615
+ const compiledContent = this.compileChildAndCache(content, filename);
616
+ const contentReplaced = (0, utils_1.injectDataAndHelpersInTemplate)(dataOrHelpers, this.helpersStore, compiledContent);
514
617
  debugData.compiledAnonymousFnContent = contentReplaced;
515
618
  return contentReplaced;
516
619
  }
@@ -536,11 +639,11 @@ class Tao {
536
639
  */
537
640
  loadTemplate(name, template) {
538
641
  const duplicate = this.dynamictemplatesStore.get(name);
539
- if (!(0, checks_1.isTemplateDynamicallyDefined)(name)) {
642
+ if (!(0, validations_1.isTemplateDynamicallyDefined)(name)) {
540
643
  throw new Error(`Dynamically loaded template ${name} should start with a '@'`);
541
644
  }
542
645
  if (duplicate) {
543
- console.warn(`⚠️ Duplicate template name ${name} provided. Template content has been erased.`);
646
+ (0, error_utils_1.logger)('warn', `Duplicate template name ${name} provided. Template content has been erased.`);
544
647
  }
545
648
  this.dynamictemplatesStore.set(name, template);
546
649
  }