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