@itrocks/template 0.0.17 → 0.0.18

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/cjs/template.js CHANGED
@@ -9,33 +9,36 @@ const app_dir_1 = __importDefault(require("@itrocks/app-dir"));
9
9
  const sorted_array_1 = require("@itrocks/sorted-array");
10
10
  const promises_1 = require("node:fs/promises");
11
11
  const node_path_1 = require("node:path");
12
- let blockBack;
13
- let blockStack;
14
- let doHeadLinks = false;
15
- let index;
16
- let length;
17
- let source;
18
- let start;
19
- let tagName;
20
- let tagStack;
21
- let target;
22
- let targetStack;
23
- let lockLiteral;
24
- let literalPartStack;
25
- let literalParts;
26
- let inLiteral;
27
12
  exports.frontScripts = new sorted_array_1.SortedArray();
28
13
  exports.frontScripts.distinct = true;
29
- let doneLinks = new sorted_array_1.SortedArray();
30
- let headLinks = new sorted_array_1.SortedArray();
31
- let headTitle = undefined;
32
- doneLinks.distinct = true;
33
- headLinks.distinct = true;
34
14
  class Template {
35
15
  data;
36
16
  containerData;
17
+ // block stack
18
+ blockBack = 0;
19
+ blockStack;
20
+ // parser
37
21
  doExpression = true;
22
+ index = 0;
23
+ length = 0;
24
+ source = '';
25
+ start = 0;
26
+ tagName = '';
27
+ tagStack = [];
28
+ target = '';
29
+ targetStack = [];
30
+ // literal
38
31
  doLiteral = false;
32
+ inLiteral = false;
33
+ literalParts = [];
34
+ literalPartStack = [];
35
+ lockLiteral = false;
36
+ // html head
37
+ doHeadLinks = false;
38
+ doneLinks = new sorted_array_1.SortedArray();
39
+ headLinks = new sorted_array_1.SortedArray();
40
+ headTitle;
41
+ // file
39
42
  fileName;
40
43
  filePath;
41
44
  included = false;
@@ -45,42 +48,45 @@ class Template {
45
48
  literalAttributes = new sorted_array_1.SortedArray('alt', 'enterkeyhint', 'label', 'lang', 'placeholder', 'srcdoc', 'title');
46
49
  // These element contents are literals.
47
50
  literalElements = new sorted_array_1.SortedArray('a', 'abbr', 'acronym', 'article', 'aside', 'b', 'bdi', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'caption', 'center', 'cite', 'data', 'datalist', 'dd', 'del', 'desc', 'details', 'dfn', 'dialog', 'div', 'dt', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hr', 'i', 'iframe', 'ins', 'keygen', 'label', 'legend', 'li', 'main', 'mark', 'menuitem', 'meter', 'nav', 'noframes', 'noscript', 'optgroup', 'option', 'p', 'pre', 'q', 'rb', 's', 'section', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'summary', 'sup', 'td', 'template', 'text', 'textarea', 'textpath', 'th', 'time', 'title', 'tspan', 'u', 'wbr');
51
+ // These elements have no closing tag.
52
+ unclosingTags = new sorted_array_1.SortedArray('area', 'base', 'basefont', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track');
53
+ // Event hooks
48
54
  onAttribute;
49
55
  onTagOpen;
50
56
  onTagOpened;
51
57
  onTagClose;
58
+ // Additional parsers
52
59
  parsers = [];
53
- prefixes;
54
- // These elements have no closing tag.
55
- unclosingTags = new sorted_array_1.SortedArray('area', 'base', 'basefont', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track');
60
+ prefixes = '';
56
61
  constructor(data, containerData) {
57
62
  this.data = data;
58
63
  this.containerData = containerData;
59
- blockStack = [];
64
+ this.doneLinks.distinct = true;
65
+ this.headLinks.distinct = true;
66
+ this.blockStack = [];
60
67
  if (containerData) {
61
- blockStack.push({ blockStart: 0, collection: [], data: containerData, iteration: 0, iterations: 1 });
68
+ this.blockStack.push({ blockStart: 0, collection: [], data: containerData, iteration: 0, iterations: 1 });
62
69
  }
63
- this.prefixes = this.parsers.map(([prefix]) => prefix).join('');
64
70
  }
65
71
  applyLiterals(text, parts = []) {
66
72
  return text.replace(/\$([0-9]+)/g, (_, index) => parts[+index]);
67
73
  }
68
74
  closeTag(shouldInLiteral, targetIndex) {
69
- shouldInLiteral ||= inLiteral;
70
- ({ tagName, inLiteral } = tagStack.pop() ?? { tagName: '', inLiteral: false });
75
+ shouldInLiteral ||= this.inLiteral;
76
+ Object.assign(this, this.tagStack.pop() ?? { tagName: '', inLiteral: false });
71
77
  if (this.onTagClose)
72
- this.onTagClose.call(this, tagName);
73
- if ((tagName[0] === 'a') && (tagName === 'address')) {
74
- lockLiteral = false;
78
+ this.onTagClose.call(this, this.tagName);
79
+ if ((this.tagName[0] === 'a') && (this.tagName === 'address')) {
80
+ this.lockLiteral = false;
75
81
  }
76
- if (inLiteral && this.inlineElements.includes(tagName)) {
77
- if (this.literalElements.includes(tagName)) {
82
+ if (this.inLiteral && this.inlineElements.includes(this.tagName)) {
83
+ if (this.literalElements.includes(this.tagName)) {
78
84
  this.literalTarget(targetIndex);
79
85
  }
80
- literalParts = literalPartStack.pop();
81
- literalParts.push(target + source.substring(start, index));
82
- start = index;
83
- target = targetStack.pop() + '$' + literalParts.length;
86
+ this.literalParts = this.literalPartStack.pop();
87
+ this.literalParts.push(this.target + this.source.substring(this.start, this.index));
88
+ this.start = this.index;
89
+ this.target = this.targetStack.pop() + '$' + this.literalParts.length;
84
90
  shouldInLiteral = false;
85
91
  }
86
92
  return shouldInLiteral;
@@ -114,46 +120,51 @@ class Template {
114
120
  doHeadLinks: false,
115
121
  doneLinks: doneLinks,
116
122
  headLinks: headLinks,
117
- index: length,
118
- length: source.length,
119
- source: source,
120
- start: length,
121
- target: target,
122
- targetStack: [],
123
+ index: this.length,
124
+ inLiteral: this.doLiteral,
125
+ length: this.source.length,
123
126
  literalPartStack: [],
124
127
  literalParts: [],
125
- inLiteral: this.doLiteral
128
+ source: this.source,
129
+ start: this.length,
130
+ target: this.target,
131
+ targetStack: []
126
132
  };
127
133
  }
128
134
  getPosition() {
129
- return { index, start, target };
135
+ return { index: this.index, start: this.start, target: this.target };
130
136
  }
131
137
  getContext() {
132
138
  return {
133
- doHeadLinks, doneLinks, headLinks, index, length, source, start, target, targetStack,
134
- literalPartStack, literalParts, inLiteral
139
+ doHeadLinks: this.doHeadLinks,
140
+ doneLinks: this.doneLinks,
141
+ headLinks: this.headLinks,
142
+ index: this.index,
143
+ inLiteral: this.inLiteral,
144
+ length: this.length,
145
+ literalParts: this.literalParts,
146
+ literalPartStack: this.literalPartStack,
147
+ source: this.source,
148
+ start: this.start,
149
+ target: this.target,
150
+ targetStack: this.targetStack,
135
151
  };
136
152
  }
137
153
  async include(path, data) {
138
- const back = {
139
- doHeadLinks, index, length, source, start, tagName, tagStack, target, targetStack,
140
- literalParts, literalPartStack, inLiteral, lockLiteral
141
- };
142
- doHeadLinks = true;
143
- const template = new (Object.getPrototypeOf(this).constructor)(data, blockStack[0]?.data);
144
- template.included = true;
154
+ const template = new (Object.getPrototypeOf(this).constructor)(data, this.blockStack[0]?.data);
145
155
  template.doExpression = this.doExpression;
156
+ template.doHeadLinks = true;
146
157
  template.doLiteral = this.doLiteral;
158
+ template.included = true;
147
159
  template.onAttribute = this.onAttribute;
148
160
  template.onTagClose = this.onTagClose;
149
161
  template.onTagOpen = this.onTagOpen;
150
162
  template.onTagOpened = this.onTagOpened;
151
163
  template.parsers = this.parsers;
152
- const parsed = await template.parseFile(((path[0] === node_path_1.sep) || (path[1] === ':')) ? path : (this.filePath + node_path_1.sep + path));
153
- ({
154
- doHeadLinks, index, length, source, start, tagName, tagStack, target, targetStack,
155
- literalParts, literalPartStack, inLiteral, lockLiteral
156
- } = back);
164
+ template.prefixes = this.prefixes;
165
+ const parsed = await template.parseFile(((path[0] === node_path_1.sep) || (path[1] === ':'))
166
+ ? path
167
+ : (this.filePath + node_path_1.sep + path));
157
168
  return parsed.substring(parsed.indexOf('<!--BEGIN-->') + 12, parsed.indexOf('<!--END-->'));
158
169
  }
159
170
  isContextClean() {
@@ -165,151 +176,154 @@ class Template {
165
176
  && context.headLinks.distinct === clean.headLinks.distinct
166
177
  && context.headLinks.length === clean.headLinks.length
167
178
  && context.index === clean.index
168
- && context.length === clean.length
169
- && context.start === clean.start
170
- && context.targetStack.length === clean.targetStack.length
179
+ && context.inLiteral === clean.inLiteral
171
180
  && context.literalPartStack.length === clean.literalPartStack.length
172
181
  && context.literalParts.length === clean.literalParts.length
173
- && context.inLiteral === clean.inLiteral;
182
+ && context.length === clean.length
183
+ && context.start === clean.start
184
+ && context.targetStack.length === clean.targetStack.length;
174
185
  }
175
186
  literalTarget(index, isTitle = false) {
176
187
  let combined;
177
- if (literalParts.length) {
178
- target += source.substring(start, index);
179
- combined = this.combineLiterals(target, literalParts);
180
- target = (targetStack.pop() ?? '') + combined;
181
- literalParts = [];
188
+ if (this.literalParts.length) {
189
+ this.target += this.source.substring(this.start, index);
190
+ combined = this.combineLiterals(this.target, this.literalParts);
191
+ this.target = (this.targetStack.pop() ?? '') + combined;
192
+ this.literalParts = [];
182
193
  }
183
194
  else {
184
- combined = this.combineLiterals(source.substring(start, index));
185
- target += combined;
195
+ combined = this.combineLiterals(this.source.substring(this.start, index));
196
+ this.target += combined;
186
197
  }
187
- if (isTitle && doHeadLinks) {
188
- headTitle = combined;
198
+ if (isTitle && this.doHeadLinks) {
199
+ this.headTitle = combined;
189
200
  }
190
- start = index;
201
+ this.start = index;
191
202
  }
192
203
  async parseBuffer(buffer) {
204
+ this.prefixes = this.parsers.map(([prefix]) => prefix).join('');
193
205
  this.setSource(buffer);
194
206
  await this.parseVars();
195
- if (doHeadLinks) {
196
- return target;
197
- }
198
- if (headLinks.length) {
199
- const position = target.lastIndexOf('>', target.indexOf('</head>')) + 1;
200
- target = target.slice(0, position) + '\n\t' + headLinks.join('\n\t') + target.slice(position);
201
- doneLinks = new sorted_array_1.SortedArray;
202
- doneLinks.distinct = true;
203
- headLinks = new sorted_array_1.SortedArray;
204
- headLinks.distinct = true;
205
- }
206
- if (headTitle && !this.included) {
207
- const position = target.indexOf('>', target.indexOf('<title') + 6) + 1;
208
- target = target.slice(0, position) + headTitle + target.slice(target.indexOf('</title>', position));
209
- }
210
- return target;
207
+ if (this.doHeadLinks) {
208
+ return this.target;
209
+ }
210
+ if (this.headLinks.length) {
211
+ const position = this.target.lastIndexOf('>', this.target.indexOf('</head>')) + 1;
212
+ this.target = this.target.slice(0, position) + '\n\t' + this.headLinks.join('\n\t') + this.target.slice(position);
213
+ this.doneLinks = new sorted_array_1.SortedArray;
214
+ this.headLinks = new sorted_array_1.SortedArray;
215
+ this.doneLinks.distinct = true;
216
+ this.headLinks.distinct = true;
217
+ }
218
+ if (this.headTitle && !this.included) {
219
+ const position = this.target.indexOf('>', this.target.indexOf('<title') + 6) + 1;
220
+ this.target = this.target.slice(0, position)
221
+ + this.headTitle
222
+ + this.target.slice(this.target.indexOf('</title>', position));
223
+ }
224
+ return this.target;
211
225
  }
212
226
  async parseExpression(data, close, finalClose = '') {
213
- const indexOut = index;
214
- let open = source[index];
215
- if (inLiteral && !literalParts.length) {
216
- targetStack.push(target);
217
- target = '';
227
+ const indexOut = this.index;
228
+ let open = this.source[this.index];
229
+ if (this.inLiteral && !this.literalParts.length) {
230
+ this.targetStack.push(this.target);
231
+ this.target = '';
218
232
  }
219
233
  if (open === '<') {
220
- index += 3;
234
+ this.index += 3;
221
235
  open = '{';
222
236
  }
223
- index++;
224
- const firstChar = source[index];
225
- if ((index >= length) || !this.startsExpression(firstChar, open, close)) {
237
+ this.index++;
238
+ const firstChar = this.source[this.index];
239
+ if ((this.index >= this.length) || !this.startsExpression(firstChar, open, close)) {
226
240
  return;
227
241
  }
228
242
  let conditional = (firstChar === '?');
229
243
  const finalChar = finalClose.length ? finalClose[0] : '';
230
- let stackPos = targetStack.length;
244
+ let stackPos = this.targetStack.length;
231
245
  if (conditional) {
232
- index++;
246
+ this.index++;
233
247
  }
234
- targetStack.push(target + source.substring(start, indexOut));
235
- start = index;
236
- target = '';
237
- while (index < length) {
238
- const char = source[index];
248
+ this.targetStack.push(this.target + this.source.substring(this.start, indexOut));
249
+ this.start = this.index;
250
+ this.target = '';
251
+ while (this.index < this.length) {
252
+ const char = this.source[this.index];
239
253
  if (char === open) {
240
- targetStack.push(target + source.substring(start, index));
241
- index++;
242
- start = index;
243
- target = '';
254
+ this.targetStack.push(this.target + this.source.substring(this.start, this.index));
255
+ this.index++;
256
+ this.start = this.index;
257
+ this.target = '';
244
258
  continue;
245
259
  }
246
260
  if ((char === close)
247
- || ((char === finalChar) && (source.substring(index, index + finalClose.length) === finalClose))) {
261
+ || ((char === finalChar) && (this.source.substring(this.index, this.index + finalClose.length) === finalClose))) {
248
262
  let minus = 0;
249
- if (source[index - 1] === '?') {
263
+ if (this.source[this.index - 1] === '?') {
250
264
  conditional = true;
251
265
  minus = 1;
252
266
  }
253
- const expression = target + source.substring(start, index - minus);
254
- const lastTarget = targetStack.pop();
267
+ const expression = this.target + this.source.substring(this.start, this.index - minus);
268
+ const lastTarget = this.targetStack.pop();
255
269
  const parsed = await this.parsePath(expression, data);
256
- index += (char === close) ? 1 : finalClose.length;
257
- start = index;
258
- target = '';
270
+ this.index += (char === close) ? 1 : finalClose.length;
271
+ this.start = this.index;
272
+ this.target = '';
259
273
  if (char === finalChar)
260
- while (targetStack.length > stackPos) {
261
- target += targetStack.shift();
274
+ while (this.targetStack.length > stackPos) {
275
+ this.target += this.targetStack.shift();
262
276
  }
263
- if (inLiteral && (targetStack.length === stackPos)) {
264
- literalParts.push(parsed);
265
- target += lastTarget + '$' + literalParts.length;
277
+ if (this.inLiteral && (this.targetStack.length === stackPos)) {
278
+ this.literalParts.push(parsed);
279
+ this.target += lastTarget + '$' + this.literalParts.length;
266
280
  return conditional;
267
281
  }
268
- if (lastTarget.length || target.length) {
269
- target += lastTarget + parsed;
282
+ if (lastTarget.length || this.target.length) {
283
+ this.target += lastTarget + parsed;
270
284
  }
271
285
  else {
272
- target = parsed;
286
+ this.target = parsed;
273
287
  }
274
- if (targetStack.length === stackPos) {
275
- if (conditional && !parsed) {
276
- if ((typeof target)[0] === 's') {
277
- target = target.substring(0, target.lastIndexOf(' '));
278
- while ((index < length) && !' \n\r\t\f'.includes(source[index])) {
279
- index++;
280
- start++;
281
- }
282
- index--;
288
+ if (this.targetStack.length !== stackPos) {
289
+ continue;
290
+ }
291
+ if (conditional && !parsed) {
292
+ if ((typeof this.target)[0] === 's') {
293
+ this.target = this.target.substring(0, this.target.lastIndexOf(' '));
294
+ while ((this.index < this.length) && !' \n\r\t\f'.includes(this.source[this.index])) {
295
+ this.index++;
296
+ this.start++;
283
297
  }
284
- return conditional;
298
+ this.index--;
285
299
  }
286
300
  return conditional;
287
301
  }
288
- continue;
302
+ return conditional;
289
303
  }
290
304
  if ((char === '"') || (char === "'")) {
291
- index++;
305
+ this.index++;
292
306
  let c;
293
- while ((index < length) && ((c = source[index]) !== char)) {
307
+ while ((this.index < this.length) && ((c = this.source[this.index]) !== char)) {
294
308
  if (c === '\\')
295
- index++;
296
- index++;
309
+ this.index++;
310
+ this.index++;
297
311
  }
298
312
  }
299
- index++;
313
+ this.index++;
300
314
  }
301
315
  // bad close
302
316
  stackPos++;
303
- while (targetStack.length > stackPos) {
304
- target = targetStack.pop() + open + target;
317
+ while (this.targetStack.length > stackPos) {
318
+ this.target = this.targetStack.pop() + open + this.target;
305
319
  }
306
- target = targetStack.pop() + (finalClose.length ? '<!--' : open) + target;
320
+ this.target = this.targetStack.pop() + (finalClose.length ? '<!--' : open) + this.target;
307
321
  return conditional;
308
322
  }
309
323
  async parseFile(fileName, containerFileName) {
310
324
  if (containerFileName && !this.included) {
311
325
  const data = this.data;
312
- this.data = Object.assign({ content: () => this.include(fileName, data) }, blockStack[0]?.data);
326
+ this.data = Object.assign({ content: () => this.include(fileName, data) }, this.blockStack[0]?.data);
313
327
  return this.parseFile((0, node_path_1.normalize)(containerFileName));
314
328
  }
315
329
  this.fileName = fileName.substring(fileName.lastIndexOf(node_path_1.sep) + 1);
@@ -323,7 +337,7 @@ class Template {
323
337
  if ((expression[0] === '.') && (expression.startsWith('./') || expression.startsWith('../'))) {
324
338
  return this.include(expression, data);
325
339
  }
326
- blockBack = 0;
340
+ this.blockBack = 0;
327
341
  for (const variable of expression.split('.')) {
328
342
  data = await this.parseVariable(variable, data);
329
343
  }
@@ -347,8 +361,8 @@ class Template {
347
361
  return variable.substring(1, variable.length - 1);
348
362
  }
349
363
  if (firstChar === '-') {
350
- blockBack++;
351
- return blockStack[blockStack.length - blockBack].data;
364
+ this.blockBack++;
365
+ return this.blockStack[this.blockStack.length - this.blockBack].data;
352
366
  }
353
367
  for (const [prefix, callback] of this.parsers) {
354
368
  if (firstChar === prefix) {
@@ -370,8 +384,8 @@ class Template {
370
384
  let inHead = false;
371
385
  let iteration = 0;
372
386
  let iterations = 0;
373
- while (index < length) {
374
- let char = source[index];
387
+ while (this.index < this.length) {
388
+ let char = this.source[this.index];
375
389
  // expression
376
390
  if ((char === '{') && this.doExpression) {
377
391
  await this.parseExpression(data, '}');
@@ -379,70 +393,76 @@ class Template {
379
393
  }
380
394
  // tag ?
381
395
  if (char !== '<') {
382
- index++;
396
+ this.index++;
383
397
  continue;
384
398
  }
385
- const tagIndex = index;
386
- char = source[++index];
399
+ const tagIndex = this.index;
400
+ char = this.source[++this.index];
387
401
  if (char === '!') {
388
- if (inLiteral) {
402
+ if (this.inLiteral) {
389
403
  this.literalTarget(tagIndex);
390
404
  }
391
- char = source[++index];
392
- index++;
405
+ char = this.source[++this.index];
406
+ this.index++;
393
407
  // comment tag
394
- if ((char === '-') && (source[index] === '-')) {
395
- index++;
408
+ if ((char === '-') && (this.source[this.index] === '-')) {
409
+ this.index++;
410
+ const firstChar = this.source[this.index];
396
411
  if (!this.doExpression
397
- || !this.startsExpression(source[index])
398
- || ((source[index] === 'B') && this.included && (source.substring(index, index + 8) === 'BEGIN-->'))
399
- || ((source[index] === 'E') && this.included && (source.substring(index, index + 6) === 'END-->'))) {
400
- index = source.indexOf('-->', index) + 3;
401
- if (index === 2)
412
+ || !this.startsExpression(firstChar)
413
+ || ((firstChar === 'B')
414
+ && this.included
415
+ && (this.source.substring(this.index, this.index + 8) === 'BEGIN-->'))
416
+ || ((firstChar === 'E')
417
+ && this.included
418
+ && (this.source.substring(this.index, this.index + 6) === 'END-->'))) {
419
+ this.index = this.source.indexOf('-->', this.index) + 3;
420
+ if (this.index === 2)
402
421
  break;
403
- if (inLiteral && (index > start)) {
422
+ if (this.inLiteral && (this.index > this.start)) {
404
423
  this.sourceToTarget();
405
424
  }
406
425
  continue;
407
426
  }
408
427
  // end condition / loop block
409
- if ('eE'.includes(source[index]) && ['end-->', 'END-->'].includes(source.substring(index, index + 6))) {
410
- target += this.trimEndLine(source.substring(start, tagIndex));
428
+ if ('eE'.includes(firstChar)
429
+ && ['end-->', 'END-->'].includes(this.source.substring(this.index, this.index + 6))) {
430
+ this.target += this.trimEndLine(this.source.substring(this.start, tagIndex));
411
431
  iteration++;
412
432
  if (iteration < iterations) {
413
433
  data = collection[iteration];
414
- index = start = blockStart;
415
- if (inLiteral && (index > start)) {
434
+ this.index = this.start = blockStart;
435
+ if (this.inLiteral && (this.index > this.start)) {
416
436
  this.sourceToTarget();
417
437
  }
418
438
  continue;
419
439
  }
420
- ({ blockStart, collection, data, iteration, iterations } = blockStack.pop()
440
+ ({ blockStart, collection, data, iteration, iterations } = this.blockStack.pop()
421
441
  ?? { blockStart: 0, collection: [], data: undefined, iteration: 0, iterations: 0 });
422
- index += 6;
423
- start = index;
424
- if (inLiteral && (index > start)) {
442
+ this.index += 6;
443
+ this.start = this.index;
444
+ if (this.inLiteral && (this.index > this.start)) {
425
445
  this.sourceToTarget();
426
446
  }
427
447
  continue;
428
448
  }
429
449
  // begin condition / loop block
430
- blockStack.push({ blockStart, collection, data, iteration, iterations });
431
- if (tagIndex > start) {
432
- target += this.trimEndLine(source.substring(start, tagIndex));
433
- start = tagIndex;
450
+ this.blockStack.push({ blockStart, collection, data, iteration, iterations });
451
+ if (tagIndex > this.start) {
452
+ this.target += this.trimEndLine(this.source.substring(this.start, tagIndex));
453
+ this.start = tagIndex;
434
454
  }
435
- const backTarget = target;
436
- const backInLiteral = inLiteral;
437
- index = tagIndex;
438
- target = '';
439
- inLiteral = false;
455
+ const backTarget = this.target;
456
+ const backInLiteral = this.inLiteral;
457
+ this.index = tagIndex;
458
+ this.target = '';
459
+ this.inLiteral = false;
440
460
  const condition = await this.parseExpression(data, '}', '-->');
441
- let blockData = condition ? (target ? data : undefined) : target;
442
- blockStart = index;
461
+ let blockData = condition ? (this.target ? data : undefined) : this.target;
462
+ blockStart = this.index;
443
463
  iteration = 0;
444
- target = backTarget;
445
- inLiteral = backInLiteral;
464
+ this.target = backTarget;
465
+ this.inLiteral = backInLiteral;
446
466
  if (Array.isArray(blockData)) {
447
467
  collection = blockData;
448
468
  data = collection[0];
@@ -457,86 +477,86 @@ class Template {
457
477
  this.skipBlock();
458
478
  continue;
459
479
  }
460
- if (inLiteral && (index > start)) {
480
+ if (this.inLiteral && (this.index > this.start)) {
461
481
  this.sourceToTarget();
462
482
  }
463
483
  continue;
464
484
  }
465
485
  // cdata section
466
- if ((char === '[') && (source.substring(index, index + 6) === 'CDATA[')) {
467
- index = source.indexOf(']]>', index + 6) + 3;
468
- if (index === 2)
486
+ if ((char === '[') && (this.source.substring(this.index, this.index + 6) === 'CDATA[')) {
487
+ this.index = this.source.indexOf(']]>', this.index + 6) + 3;
488
+ if (this.index === 2)
469
489
  break;
470
490
  }
471
491
  // DOCTYPE
472
492
  else {
473
- index = source.indexOf('>', index) + 1;
493
+ this.index = this.source.indexOf('>', this.index) + 1;
474
494
  }
475
- if (inLiteral) {
495
+ if (this.inLiteral) {
476
496
  this.sourceToTarget();
477
497
  }
478
498
  continue;
479
499
  }
480
500
  // tag close
481
501
  if (char === '/') {
482
- index++;
483
- const closeTagName = source.substring(index, source.indexOf('>', index));
484
- index += closeTagName.length + 1;
502
+ this.index++;
503
+ const closeTagName = this.source.substring(this.index, this.source.indexOf('>', this.index));
504
+ this.index += closeTagName.length + 1;
485
505
  if (inHead && (closeTagName[0] === 'h') && (closeTagName === 'head')) {
486
506
  inHead = false;
487
- if (!doHeadLinks) {
488
- doneLinks = headLinks;
489
- headLinks = new sorted_array_1.SortedArray;
490
- headLinks.distinct = true;
507
+ if (!this.doHeadLinks) {
508
+ this.doneLinks = this.headLinks;
509
+ this.headLinks = new sorted_array_1.SortedArray();
510
+ this.headLinks.distinct = true;
491
511
  }
492
512
  }
493
- let shouldInLiteral = inLiteral;
513
+ let shouldInLiteral = this.inLiteral;
494
514
  if (!this.unclosingTags.includes(closeTagName)) {
495
515
  do {
496
516
  shouldInLiteral = this.closeTag(shouldInLiteral, tagIndex);
497
- } while ((tagName !== closeTagName) && tagName.length);
517
+ } while ((this.tagName !== closeTagName) && this.tagName.length);
498
518
  }
499
519
  if (shouldInLiteral) {
500
- lockLiteral = false;
501
- this.literalTarget(tagIndex, (tagName[0] === 't') && (tagName === 'title'));
520
+ this.lockLiteral = false;
521
+ this.literalTarget(tagIndex, (this.tagName[0] === 't') && (this.tagName === 'title'));
502
522
  }
503
- if (inLiteral && (index > start)) {
523
+ if (this.inLiteral && (this.index > this.start)) {
504
524
  this.sourceToTarget();
505
525
  }
506
526
  continue;
507
527
  }
508
528
  // tag open
509
- while ((index < length) && !' >\n\r\t\f'.includes(source[index]))
510
- index++;
511
- tagName = source.substring(tagIndex + 1, index);
529
+ while ((this.index < this.length) && !' >\n\r\t\f'.includes(this.source[this.index]))
530
+ this.index++;
531
+ this.tagName = this.source.substring(tagIndex + 1, this.index);
512
532
  if (this.onTagOpen)
513
- this.onTagOpen.call(this, tagName);
514
- while (' \n\r\t\f'.includes(source[index]))
515
- index++;
516
- char = tagName[0];
517
- if ((char === 'h') && (tagName === 'head')) {
533
+ this.onTagOpen.call(this, this.tagName);
534
+ while (' \n\r\t\f'.includes(this.source[this.index]))
535
+ this.index++;
536
+ char = this.tagName[0];
537
+ if ((char === 'h') && (this.tagName === 'head')) {
518
538
  inHead = true;
519
539
  }
520
- const unclosingTag = this.unclosingTags.includes(tagName);
540
+ const unclosingTag = this.unclosingTags.includes(this.tagName);
521
541
  if (!unclosingTag) {
522
- tagStack.push({ tagName, inLiteral });
542
+ this.tagStack.push({ tagName: this.tagName, inLiteral: this.inLiteral });
523
543
  }
524
544
  let inlineElement = false;
525
545
  let pushedParts = false;
526
- if (inLiteral) {
527
- inlineElement = this.inlineElements.includes(tagName);
546
+ if (this.inLiteral) {
547
+ inlineElement = this.inlineElements.includes(this.tagName);
528
548
  if (inlineElement) {
529
- if (literalParts.length) {
530
- targetStack.push(target + source.substring(start, tagIndex));
549
+ if (this.literalParts.length) {
550
+ this.targetStack.push(this.target + this.source.substring(this.start, tagIndex));
531
551
  }
532
552
  else {
533
- targetStack.push(target, source.substring(start, tagIndex));
553
+ this.targetStack.push(this.target, this.source.substring(this.start, tagIndex));
534
554
  }
535
- start = tagIndex;
536
- target = '';
555
+ this.start = tagIndex;
556
+ this.target = '';
537
557
  if (!unclosingTag) {
538
- literalPartStack.push(literalParts);
539
- literalParts = [];
558
+ this.literalPartStack.push(this.literalParts);
559
+ this.literalParts = [];
540
560
  pushedParts = true;
541
561
  }
542
562
  }
@@ -544,95 +564,95 @@ class Template {
544
564
  this.literalTarget(tagIndex);
545
565
  }
546
566
  }
547
- const elementInLiteral = inLiteral;
567
+ const elementInLiteral = this.inLiteral;
548
568
  // attributes
549
569
  let hasTypeSubmit = false;
550
- const inInput = (char === 'i') && (tagName === 'input');
551
- const inLink = (char === 'l') && (tagName === 'link');
552
- const inScript = (char === 's') && (tagName === 'script');
570
+ const inInput = (char === 'i') && (this.tagName === 'input');
571
+ const inLink = (char === 'l') && (this.tagName === 'link');
572
+ const inScript = (char === 's') && (this.tagName === 'script');
553
573
  let targetTagIndex = -1;
554
574
  if (inHead && (inLink || inScript)) {
555
575
  this.sourceToTarget();
556
- targetTagIndex = target.lastIndexOf('<');
576
+ targetTagIndex = this.target.lastIndexOf('<');
557
577
  }
558
- while (source[index] !== '>') {
578
+ while (this.source[this.index] !== '>') {
559
579
  // attribute name
560
- const position = index;
561
- while ((index < length) && !' =>\n\r\t\f'.includes(source[index]))
562
- index++;
563
- const attributeName = source.substring(position, index);
564
- while (' \n\r\t\f'.includes(source[index]))
565
- index++;
580
+ const position = this.index;
581
+ while ((this.index < this.length) && !' =>\n\r\t\f'.includes(this.source[this.index]))
582
+ this.index++;
583
+ const attributeName = this.source.substring(position, this.index);
584
+ while (' \n\r\t\f'.includes(this.source[this.index]))
585
+ this.index++;
566
586
  // attribute value
567
- if (source[index] === '=') {
568
- index++;
569
- while (' \n\r\t\f'.includes(source[index]))
570
- index++;
587
+ if (this.source[this.index] === '=') {
588
+ this.index++;
589
+ while (' \n\r\t\f'.includes(this.source[this.index]))
590
+ this.index++;
571
591
  const attributeChar = attributeName[0];
572
592
  const [open, close] = ('afhls'.includes(attributeChar)
573
593
  && ['action', 'formaction', 'href', 'location', 'src'].includes(attributeName)) ? ['(', ')']
574
594
  : ['{', '}'];
575
- let quote = source[index];
595
+ let quote = this.source[this.index];
576
596
  if ((quote === '"') || (quote === "'")) {
577
- index++;
597
+ this.index++;
578
598
  }
579
599
  else {
580
600
  quote = ' >';
581
601
  }
582
- if ((open === '(') && (source.substring(index, index + 6) === 'app://')) {
602
+ if ((open === '(') && (this.source.substring(this.index, this.index + 6) === 'app://')) {
583
603
  this.sourceToTarget();
584
- index += 6;
585
- start = index;
604
+ this.index += 6;
605
+ this.start = this.index;
586
606
  }
587
- inLiteral = this.doLiteral && (this.literalAttributes.includes(attributeName)
607
+ this.inLiteral = this.doLiteral && (this.literalAttributes.includes(attributeName)
588
608
  || (hasTypeSubmit && (attributeChar === 'v') && (attributeName === 'value')));
589
- if (inLiteral && !pushedParts && unclosingTag && literalParts.length) {
590
- literalPartStack.push(literalParts);
591
- literalParts = [];
609
+ if (this.inLiteral && !pushedParts && unclosingTag && this.literalParts.length) {
610
+ this.literalPartStack.push(this.literalParts);
611
+ this.literalParts = [];
592
612
  pushedParts = true;
593
613
  }
594
614
  const inLinkHRef = inLink && (attributeChar === 'h') && (attributeName === 'href');
595
615
  const inScriptSrc = inScript && (attributeChar === 's') && (attributeName === 'src');
596
- if ((inLinkHRef || inScriptSrc || inLiteral) && (index > start)) {
616
+ if ((inLinkHRef || inScriptSrc || this.inLiteral) && (this.index > this.start)) {
597
617
  this.sourceToTarget();
598
618
  }
599
- const position = index;
619
+ const position = this.index;
600
620
  const shortQuote = !(quote.length - 1);
601
- while (index < length) {
602
- const char = source[index];
621
+ while (this.index < this.length) {
622
+ const char = this.source[this.index];
603
623
  // end of attribute value
604
624
  if (shortQuote ? (char === quote) : quote.includes(char)) {
605
- const attributeValue = source.substring(position, index);
606
- if (inInput) {
607
- hasTypeSubmit ||= ((attributeChar === 't') && (attributeValue[0] === 's')
608
- && (attributeName === 'type') && (attributeValue === 'submit'));
625
+ const attributeValue = this.source.substring(position, this.index);
626
+ if (inInput && (hasTypeSubmit === undefined)) {
627
+ hasTypeSubmit = (attributeChar === 't') && (attributeValue[0] === 's')
628
+ && (attributeName === 'type') && (attributeValue === 'submit');
609
629
  }
610
- if (inLiteral) {
611
- this.literalTarget(index);
630
+ if (this.inLiteral) {
631
+ this.literalTarget(this.index);
612
632
  }
613
633
  if (inLinkHRef && attributeValue.endsWith('.css')) {
614
- let frontStyle = (0, node_path_1.normalize)(this.filePath + node_path_1.sep + source.substring(start, index))
634
+ let frontStyle = (0, node_path_1.normalize)(this.filePath + node_path_1.sep + this.source.substring(this.start, this.index))
615
635
  .substring(app_dir_1.default.length);
616
636
  if (node_path_1.sep !== '/') {
617
637
  frontStyle = frontStyle.replaceAll(node_path_1.sep, '/');
618
638
  }
619
- target += frontStyle;
620
- start = index;
639
+ this.target += frontStyle;
640
+ this.start = this.index;
621
641
  }
622
642
  if (inScriptSrc && attributeValue.endsWith('.js')) {
623
- let frontScript = (0, node_path_1.normalize)(this.filePath + node_path_1.sep + source.substring(start, index))
643
+ let frontScript = (0, node_path_1.normalize)(this.filePath + node_path_1.sep + this.source.substring(this.start, this.index))
624
644
  .substring(app_dir_1.default.length);
625
645
  if (node_path_1.sep !== '/') {
626
646
  frontScript = frontScript.replaceAll(node_path_1.sep, '/');
627
647
  }
628
648
  exports.frontScripts.insert(frontScript);
629
- target += frontScript;
630
- start = index;
649
+ this.target += frontScript;
650
+ this.start = this.index;
631
651
  }
632
652
  if (this.onAttribute)
633
653
  this.onAttribute(attributeName, attributeValue);
634
654
  if (char !== '>')
635
- index++;
655
+ this.index++;
636
656
  break;
637
657
  }
638
658
  // expression in attribute value
@@ -640,34 +660,34 @@ class Template {
640
660
  await this.parseExpression(data, close);
641
661
  continue;
642
662
  }
643
- index++;
663
+ this.index++;
644
664
  }
645
665
  }
646
666
  else if (this.onAttribute)
647
667
  this.onAttribute(attributeName, '');
648
668
  // next attribute
649
- while (' \n\r\t\f'.includes(source[index]))
650
- index++;
669
+ while (' \n\r\t\f'.includes(this.source[this.index]))
670
+ this.index++;
651
671
  }
652
- index++;
672
+ this.index++;
653
673
  if (this.onTagOpened)
654
- this.onTagOpened.call(this, tagName);
674
+ this.onTagOpened.call(this, this.tagName);
655
675
  // skip script content
656
676
  if (inScript) {
657
677
  if (this.onTagClose)
658
678
  this.onTagClose.call(this, 'script');
659
- index = source.indexOf('</script>', index) + 9;
660
- if (index === 8)
679
+ this.index = this.source.indexOf('</script>', this.index) + 9;
680
+ if (this.index === 8)
661
681
  break;
662
- if (inLiteral && (index > start)) {
682
+ if (this.inLiteral && (this.index > this.start)) {
663
683
  this.sourceToTarget();
664
684
  }
665
685
  }
666
686
  if (targetTagIndex > -1) {
667
687
  this.sourceToTarget();
668
- const headLink = target.substring(targetTagIndex);
669
- if (!doneLinks || !doneLinks.includes(headLink)) {
670
- headLinks.insert(headLink);
688
+ const headLink = this.target.substring(targetTagIndex);
689
+ if (!this.doneLinks || !this.doneLinks.includes(headLink)) {
690
+ this.headLinks.insert(headLink);
671
691
  }
672
692
  }
673
693
  if (inScript) {
@@ -675,95 +695,95 @@ class Template {
675
695
  }
676
696
  if (unclosingTag) {
677
697
  if (pushedParts) {
678
- literalParts = literalPartStack.pop();
698
+ this.literalParts = this.literalPartStack.pop();
679
699
  }
680
- inLiteral = elementInLiteral;
700
+ this.inLiteral = elementInLiteral;
681
701
  if (this.onTagClose)
682
- this.onTagClose.call(this, tagName);
683
- if (inLiteral) {
684
- if (index > start) {
702
+ this.onTagClose.call(this, this.tagName);
703
+ if (this.inLiteral) {
704
+ if (this.index > this.start) {
685
705
  this.sourceToTarget();
686
706
  }
687
707
  if (inlineElement) {
688
- literalParts.push(target);
689
- target = targetStack.pop() + '$' + literalParts.length;
708
+ this.literalParts.push(this.target);
709
+ this.target = this.targetStack.pop() + '$' + this.literalParts.length;
690
710
  }
691
711
  }
692
712
  }
693
713
  else {
694
- lockLiteral ||= (tagName[0] === 'a') && (tagName === 'address');
695
- inLiteral = this.doLiteral && !lockLiteral && this.literalElements.includes(tagName);
696
- if (inLiteral && (index > start)) {
714
+ this.lockLiteral ||= (this.tagName[0] === 'a') && (this.tagName === 'address');
715
+ this.inLiteral = this.doLiteral && !this.lockLiteral && this.literalElements.includes(this.tagName);
716
+ if (this.inLiteral && (this.index > this.start)) {
697
717
  this.sourceToTarget();
698
718
  }
699
719
  }
700
720
  }
701
- if (tagStack.length) {
702
- let shouldInLiteral = inLiteral;
703
- while (tagStack.length) {
704
- shouldInLiteral = this.closeTag(shouldInLiteral, length);
721
+ if (this.tagStack.length) {
722
+ let shouldInLiteral = this.inLiteral;
723
+ while (this.tagStack.length) {
724
+ shouldInLiteral = this.closeTag(shouldInLiteral, this.length);
705
725
  }
706
726
  if (shouldInLiteral) {
707
- this.literalTarget(length);
727
+ this.literalTarget(this.length);
708
728
  }
709
- return target;
729
+ return this.target;
710
730
  }
711
- if (inLiteral) {
712
- this.literalTarget(index);
731
+ if (this.inLiteral) {
732
+ this.literalTarget(this.index);
713
733
  }
714
- if (start < length) {
715
- target += source.substring(start);
716
- start = length;
734
+ if (this.start < this.length) {
735
+ this.target += this.source.substring(this.start);
736
+ this.start = this.length;
717
737
  }
718
- return target;
738
+ return this.target;
719
739
  }
720
- setSource(setSource, setIndex = 0, setStart, setTarget = '') {
721
- index = setIndex;
722
- length = setSource.length;
723
- source = setSource;
724
- start = setStart ?? index;
725
- tagName = '';
726
- tagStack = [];
727
- target = setTarget;
728
- inLiteral = this.doLiteral;
729
- literalPartStack = [];
730
- literalParts = [];
731
- lockLiteral = false;
732
- targetStack = [];
740
+ setSource(source, index = 0, start, target = '') {
741
+ this.index = index;
742
+ this.length = source.length;
743
+ this.source = source;
744
+ this.start = start ?? index;
745
+ this.tagName = '';
746
+ this.tagStack = [];
747
+ this.target = target;
748
+ this.inLiteral = this.doLiteral;
749
+ this.literalPartStack = [];
750
+ this.literalParts = [];
751
+ this.lockLiteral = false;
752
+ this.targetStack = [];
733
753
  }
734
754
  skipBlock() {
735
- if (index > start) {
755
+ if (this.index > this.start) {
736
756
  this.sourceToTarget();
737
757
  }
738
758
  let depth = 1;
739
759
  while (depth) {
740
- index = source.indexOf('<!--', index);
741
- if (index < 0) {
760
+ this.index = this.source.indexOf('<!--', this.index);
761
+ if (this.index < 0) {
742
762
  break;
743
763
  }
744
- index += 4;
745
- const char = source[index];
764
+ this.index += 4;
765
+ const char = this.source[this.index];
746
766
  if (!this.startsExpression(char)) {
747
767
  continue;
748
768
  }
749
- if ((char === 'e') && (source.substring(index, index + 6) === 'end-->')) {
769
+ if ((char === 'e') && (this.source.substring(this.index, this.index + 6) === 'end-->')) {
750
770
  depth--;
751
771
  continue;
752
772
  }
753
773
  depth++;
754
774
  }
755
- index -= 4;
756
- if (index < 0) {
757
- index = length;
775
+ this.index -= 4;
776
+ if (this.index < 0) {
777
+ this.index = this.length;
758
778
  }
759
- start = index;
779
+ this.start = this.index;
760
780
  }
761
781
  sourceToTarget() {
762
- target += source.substring(start, index);
763
- start = index;
782
+ this.target += this.source.substring(this.start, this.index);
783
+ this.start = this.index;
764
784
  }
765
785
  startsExpression(char, open = '{', close = '}') {
766
- return RegExp('[a-z0-9"%*.?@\'' + open + close + '-]', 'i').test(char);
786
+ return RegExp('[a-z0-9"*.?\'' + open + close + '-' + this.prefixes + ']', 'i').test(char);
767
787
  }
768
788
  trimEndLine(string) {
769
789
  let index = string.length;