@itrocks/template 0.0.24 → 0.0.26

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
@@ -377,13 +377,27 @@ Result:
377
377
 
378
378
  ### Including Another Template
379
379
 
380
- Any expression starting with `./` or `../` is considered a template include:
380
+ Any expression starting with `/`, `./` or `../` is considered a template include:
381
381
  ```html
382
382
  <div>
383
383
  {./another-template.html}
384
384
  </div>
385
385
  ```
386
386
 
387
+ The default contextual data is the one in the current scope.
388
+
389
+ You can pass parent or sub-data to your included template as an alternative context:
390
+ ```html
391
+ <div>
392
+ <!--subData-->
393
+ {./another-template.html-}
394
+ {./another-template.html(-)}
395
+ <!--end-->
396
+ {./another-template.html(subData)}
397
+ </div>
398
+ ```
399
+ In this example, `-` refers to the parent block context. Parentheses are optional in this specific case.
400
+
387
401
  #### Delimiting Rendered Content in an Included Template
388
402
 
389
403
  To keep templates W3C-compliant and browser-viewable, each HTML template may contain full HTML structure.
package/cjs/template.d.ts CHANGED
@@ -31,6 +31,7 @@ export default class Template {
31
31
  literalParts: string[];
32
32
  literalPartStack: string[][];
33
33
  lockLiteral: boolean;
34
+ addLinks: SortedArray<string>;
34
35
  doHeadLinks: boolean;
35
36
  doneLinks: SortedArray<string>;
36
37
  headLinks: SortedArray<string>;
@@ -54,6 +55,7 @@ export default class Template {
54
55
  combineLiterals(text: string, parts?: string[]): string;
55
56
  debugEvents(): void;
56
57
  getCleanContext(): {
58
+ addLinks: SortedArray<string>;
57
59
  doHeadLinks: boolean;
58
60
  doneLinks: SortedArray<string>;
59
61
  headLinks: SortedArray<string>;
@@ -73,6 +75,7 @@ export default class Template {
73
75
  target: string;
74
76
  };
75
77
  getContext(): {
78
+ addLinks: SortedArray<string>;
76
79
  doHeadLinks: boolean;
77
80
  doneLinks: SortedArray<string>;
78
81
  headLinks: SortedArray<string>;
package/cjs/template.js CHANGED
@@ -34,6 +34,7 @@ class Template {
34
34
  literalPartStack = [];
35
35
  lockLiteral = false;
36
36
  // html head
37
+ addLinks = new sorted_array_1.SortedArray();
37
38
  doHeadLinks = false;
38
39
  doneLinks = new sorted_array_1.SortedArray();
39
40
  headLinks = new sorted_array_1.SortedArray();
@@ -61,6 +62,7 @@ class Template {
61
62
  constructor(data, containerData) {
62
63
  this.data = data;
63
64
  this.containerData = containerData;
65
+ this.addLinks.distinct = true;
64
66
  this.doneLinks.distinct = true;
65
67
  this.headLinks.distinct = true;
66
68
  this.blockStack = [];
@@ -112,11 +114,14 @@ class Template {
112
114
  this.onTagClose = (name) => console.log('tag.closed =', name);
113
115
  }
114
116
  getCleanContext() {
117
+ const addLinks = new sorted_array_1.SortedArray;
115
118
  const doneLinks = new sorted_array_1.SortedArray;
116
119
  const headLinks = new sorted_array_1.SortedArray;
120
+ addLinks.distinct = true;
117
121
  doneLinks.distinct = true;
118
122
  headLinks.distinct = true;
119
123
  return {
124
+ addLinks: addLinks,
120
125
  doHeadLinks: false,
121
126
  doneLinks: doneLinks,
122
127
  headLinks: headLinks,
@@ -136,6 +141,7 @@ class Template {
136
141
  }
137
142
  getContext() {
138
143
  return {
144
+ addLinks: this.addLinks,
139
145
  doHeadLinks: this.doHeadLinks,
140
146
  doneLinks: this.doneLinks,
141
147
  headLinks: this.headLinks,
@@ -166,14 +172,23 @@ class Template {
166
172
  const parsed = await template.parseFile(((path[0] === node_path_1.sep) || (path[1] === ':'))
167
173
  ? path
168
174
  : (this.filePath + node_path_1.sep + path));
175
+ if (!this.doHeadLinks) {
176
+ this.addLinks.push(...template.headLinks);
177
+ }
169
178
  this.headLinks.push(...template.headLinks);
170
179
  this.headTitle = template.headTitle;
171
- return parsed.substring(parsed.indexOf('<!--BEGIN-->') + 12, parsed.indexOf('<!--END-->'));
180
+ const beginPosition = parsed.indexOf('<!--BEGIN-->');
181
+ const endPosition = parsed.indexOf('<!--END-->');
182
+ return (beginPosition > -1)
183
+ ? parsed.slice(beginPosition + 12, (endPosition > -1) ? endPosition : parsed.length)
184
+ : parsed;
172
185
  }
173
186
  isContextClean() {
174
187
  const clean = this.getCleanContext();
175
188
  const context = this.getContext();
176
189
  return context.doHeadLinks === clean.doHeadLinks
190
+ && context.addLinks.distinct === clean.addLinks.distinct
191
+ && context.addLinks.length === clean.addLinks.length
177
192
  && context.doneLinks.distinct === clean.doneLinks.distinct
178
193
  && context.doneLinks.length === clean.doneLinks.length
179
194
  && context.headLinks.distinct === clean.headLinks.distinct
@@ -210,9 +225,9 @@ class Template {
210
225
  if (this.doHeadLinks) {
211
226
  return this.target;
212
227
  }
213
- if (this.headLinks.length) {
228
+ if (this.addLinks.length) {
214
229
  const position = this.target.lastIndexOf('>', this.target.indexOf('</head>')) + 1;
215
- this.target = this.target.slice(0, position) + '\n\t' + this.headLinks.join('\n\t') + this.target.slice(position);
230
+ this.target = this.target.slice(0, position) + '\n\t' + this.addLinks.join('\n\t') + this.target.slice(position);
216
231
  }
217
232
  if (this.headTitle && !this.included) {
218
233
  const position = this.target.indexOf('>', this.target.indexOf('<title') + 6) + 1;
@@ -290,7 +305,7 @@ class Template {
290
305
  if (conditional && !parsed) {
291
306
  if ((typeof this.target)[0] === 's') {
292
307
  this.target = this.target.substring(0, this.target.lastIndexOf(' '));
293
- while ((this.index < this.length) && !' \n\r\t\f'.includes(this.source[this.index])) {
308
+ while ((this.index < this.length) && !' >\n\r\t\f'.includes(this.source[this.index])) {
294
309
  this.index++;
295
310
  this.start++;
296
311
  }
@@ -333,7 +348,23 @@ class Template {
333
348
  if (expression === '') {
334
349
  return undefined;
335
350
  }
336
- if ((expression[0] === '.') && (expression.startsWith('./') || expression.startsWith('../'))) {
351
+ if (((expression[0] === '.') && ((expression[1] === '/') || ((expression[1] === '.') && (expression[2] === '/'))))
352
+ || (expression[0] === '/')) {
353
+ let expressionEnd = expression.length - 1;
354
+ if (expression[expressionEnd] === '-') {
355
+ let blockBack = 1;
356
+ expressionEnd--;
357
+ while (expression[expressionEnd] === '-') {
358
+ blockBack++;
359
+ expressionEnd--;
360
+ }
361
+ const blockStack = this.blockStack;
362
+ return this.include(expression.slice(0, expressionEnd), blockStack[blockStack.length - blockBack].data);
363
+ }
364
+ if (expression[expressionEnd] === ')') {
365
+ const openPosition = expression.lastIndexOf('(');
366
+ return this.include(expression.slice(0, openPosition), await this.parsePath(expression.slice(openPosition + 1, expression.length - 1), data));
367
+ }
337
368
  return this.include(expression, data);
338
369
  }
339
370
  this.blockBack = 0;
@@ -344,7 +375,7 @@ class Template {
344
375
  }
345
376
  async parseVariable(variable, data) {
346
377
  if (variable === '') {
347
- return (typeof data === 'function')
378
+ return (((typeof data)[0] === 'f') && ((data + '')[0] !== 'c'))
348
379
  ? data.call()
349
380
  : data;
350
381
  }
@@ -372,7 +403,7 @@ class Template {
372
403
  data = new rename_1.default(data);
373
404
  }
374
405
  let value = data[variable];
375
- return ((typeof value === 'function') && !value.prototype)
406
+ return (((typeof value)[0] === 'f') && ((value + '')[0] !== 'c'))
376
407
  ? value.call(data)
377
408
  : value;
378
409
  }
@@ -446,7 +477,6 @@ class Template {
446
477
  continue;
447
478
  }
448
479
  // begin condition / loop block
449
- this.blockStack.push({ blockStart, collection, data, iteration, iterations });
450
480
  if (tagIndex > this.start) {
451
481
  this.target += this.trimEndLine(this.source.substring(this.start, tagIndex));
452
482
  this.start = tagIndex;
@@ -457,6 +487,7 @@ class Template {
457
487
  this.target = '';
458
488
  this.inLiteral = false;
459
489
  const condition = await this.parseExpression(data, '}', '-->');
490
+ this.blockStack.push({ blockStart, collection, data, iteration, iterations });
460
491
  let blockData = condition ? (this.target ? data : undefined) : this.target;
461
492
  blockStart = this.index;
462
493
  iteration = 0;
package/esm/template.d.ts CHANGED
@@ -31,6 +31,7 @@ export default class Template {
31
31
  literalParts: string[];
32
32
  literalPartStack: string[][];
33
33
  lockLiteral: boolean;
34
+ addLinks: SortedArray<string>;
34
35
  doHeadLinks: boolean;
35
36
  doneLinks: SortedArray<string>;
36
37
  headLinks: SortedArray<string>;
@@ -54,6 +55,7 @@ export default class Template {
54
55
  combineLiterals(text: string, parts?: string[]): string;
55
56
  debugEvents(): void;
56
57
  getCleanContext(): {
58
+ addLinks: SortedArray<string>;
57
59
  doHeadLinks: boolean;
58
60
  doneLinks: SortedArray<string>;
59
61
  headLinks: SortedArray<string>;
@@ -73,6 +75,7 @@ export default class Template {
73
75
  target: string;
74
76
  };
75
77
  getContext(): {
78
+ addLinks: SortedArray<string>;
76
79
  doHeadLinks: boolean;
77
80
  doneLinks: SortedArray<string>;
78
81
  headLinks: SortedArray<string>;
package/esm/template.js CHANGED
@@ -29,6 +29,7 @@ export default class Template {
29
29
  literalPartStack = [];
30
30
  lockLiteral = false;
31
31
  // html head
32
+ addLinks = new SortedArray();
32
33
  doHeadLinks = false;
33
34
  doneLinks = new SortedArray();
34
35
  headLinks = new SortedArray();
@@ -56,6 +57,7 @@ export default class Template {
56
57
  constructor(data, containerData) {
57
58
  this.data = data;
58
59
  this.containerData = containerData;
60
+ this.addLinks.distinct = true;
59
61
  this.doneLinks.distinct = true;
60
62
  this.headLinks.distinct = true;
61
63
  this.blockStack = [];
@@ -107,11 +109,14 @@ export default class Template {
107
109
  this.onTagClose = (name) => console.log('tag.closed =', name);
108
110
  }
109
111
  getCleanContext() {
112
+ const addLinks = new SortedArray;
110
113
  const doneLinks = new SortedArray;
111
114
  const headLinks = new SortedArray;
115
+ addLinks.distinct = true;
112
116
  doneLinks.distinct = true;
113
117
  headLinks.distinct = true;
114
118
  return {
119
+ addLinks: addLinks,
115
120
  doHeadLinks: false,
116
121
  doneLinks: doneLinks,
117
122
  headLinks: headLinks,
@@ -131,6 +136,7 @@ export default class Template {
131
136
  }
132
137
  getContext() {
133
138
  return {
139
+ addLinks: this.addLinks,
134
140
  doHeadLinks: this.doHeadLinks,
135
141
  doneLinks: this.doneLinks,
136
142
  headLinks: this.headLinks,
@@ -161,14 +167,23 @@ export default class Template {
161
167
  const parsed = await template.parseFile(((path[0] === sep) || (path[1] === ':'))
162
168
  ? path
163
169
  : (this.filePath + sep + path));
170
+ if (!this.doHeadLinks) {
171
+ this.addLinks.push(...template.headLinks);
172
+ }
164
173
  this.headLinks.push(...template.headLinks);
165
174
  this.headTitle = template.headTitle;
166
- return parsed.substring(parsed.indexOf('<!--BEGIN-->') + 12, parsed.indexOf('<!--END-->'));
175
+ const beginPosition = parsed.indexOf('<!--BEGIN-->');
176
+ const endPosition = parsed.indexOf('<!--END-->');
177
+ return (beginPosition > -1)
178
+ ? parsed.slice(beginPosition + 12, (endPosition > -1) ? endPosition : parsed.length)
179
+ : parsed;
167
180
  }
168
181
  isContextClean() {
169
182
  const clean = this.getCleanContext();
170
183
  const context = this.getContext();
171
184
  return context.doHeadLinks === clean.doHeadLinks
185
+ && context.addLinks.distinct === clean.addLinks.distinct
186
+ && context.addLinks.length === clean.addLinks.length
172
187
  && context.doneLinks.distinct === clean.doneLinks.distinct
173
188
  && context.doneLinks.length === clean.doneLinks.length
174
189
  && context.headLinks.distinct === clean.headLinks.distinct
@@ -205,9 +220,9 @@ export default class Template {
205
220
  if (this.doHeadLinks) {
206
221
  return this.target;
207
222
  }
208
- if (this.headLinks.length) {
223
+ if (this.addLinks.length) {
209
224
  const position = this.target.lastIndexOf('>', this.target.indexOf('</head>')) + 1;
210
- this.target = this.target.slice(0, position) + '\n\t' + this.headLinks.join('\n\t') + this.target.slice(position);
225
+ this.target = this.target.slice(0, position) + '\n\t' + this.addLinks.join('\n\t') + this.target.slice(position);
211
226
  }
212
227
  if (this.headTitle && !this.included) {
213
228
  const position = this.target.indexOf('>', this.target.indexOf('<title') + 6) + 1;
@@ -285,7 +300,7 @@ export default class Template {
285
300
  if (conditional && !parsed) {
286
301
  if ((typeof this.target)[0] === 's') {
287
302
  this.target = this.target.substring(0, this.target.lastIndexOf(' '));
288
- while ((this.index < this.length) && !' \n\r\t\f'.includes(this.source[this.index])) {
303
+ while ((this.index < this.length) && !' >\n\r\t\f'.includes(this.source[this.index])) {
289
304
  this.index++;
290
305
  this.start++;
291
306
  }
@@ -328,7 +343,23 @@ export default class Template {
328
343
  if (expression === '') {
329
344
  return undefined;
330
345
  }
331
- if ((expression[0] === '.') && (expression.startsWith('./') || expression.startsWith('../'))) {
346
+ if (((expression[0] === '.') && ((expression[1] === '/') || ((expression[1] === '.') && (expression[2] === '/'))))
347
+ || (expression[0] === '/')) {
348
+ let expressionEnd = expression.length - 1;
349
+ if (expression[expressionEnd] === '-') {
350
+ let blockBack = 1;
351
+ expressionEnd--;
352
+ while (expression[expressionEnd] === '-') {
353
+ blockBack++;
354
+ expressionEnd--;
355
+ }
356
+ const blockStack = this.blockStack;
357
+ return this.include(expression.slice(0, expressionEnd), blockStack[blockStack.length - blockBack].data);
358
+ }
359
+ if (expression[expressionEnd] === ')') {
360
+ const openPosition = expression.lastIndexOf('(');
361
+ return this.include(expression.slice(0, openPosition), await this.parsePath(expression.slice(openPosition + 1, expression.length - 1), data));
362
+ }
332
363
  return this.include(expression, data);
333
364
  }
334
365
  this.blockBack = 0;
@@ -339,7 +370,7 @@ export default class Template {
339
370
  }
340
371
  async parseVariable(variable, data) {
341
372
  if (variable === '') {
342
- return (typeof data === 'function')
373
+ return (((typeof data)[0] === 'f') && ((data + '')[0] !== 'c'))
343
374
  ? data.call()
344
375
  : data;
345
376
  }
@@ -367,7 +398,7 @@ export default class Template {
367
398
  data = new Str(data);
368
399
  }
369
400
  let value = data[variable];
370
- return ((typeof value === 'function') && !value.prototype)
401
+ return (((typeof value)[0] === 'f') && ((value + '')[0] !== 'c'))
371
402
  ? value.call(data)
372
403
  : value;
373
404
  }
@@ -441,7 +472,6 @@ export default class Template {
441
472
  continue;
442
473
  }
443
474
  // begin condition / loop block
444
- this.blockStack.push({ blockStart, collection, data, iteration, iterations });
445
475
  if (tagIndex > this.start) {
446
476
  this.target += this.trimEndLine(this.source.substring(this.start, tagIndex));
447
477
  this.start = tagIndex;
@@ -452,6 +482,7 @@ export default class Template {
452
482
  this.target = '';
453
483
  this.inLiteral = false;
454
484
  const condition = await this.parseExpression(data, '}', '-->');
485
+ this.blockStack.push({ blockStart, collection, data, iteration, iterations });
455
486
  let blockData = condition ? (this.target ? data : undefined) : this.target;
456
487
  blockStart = this.index;
457
488
  iteration = 0;
package/package.json CHANGED
@@ -67,5 +67,5 @@
67
67
  "test": "jest"
68
68
  },
69
69
  "types": "./esm/template.d.ts",
70
- "version": "0.0.24"
70
+ "version": "0.0.26"
71
71
  }