@itrocks/template 0.1.3 → 0.1.5
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 +4 -7
- package/cjs/template.js +100 -64
- package/esm/template.d.ts +4 -7
- package/esm/template.js +100 -64
- package/package.json +1 -1
package/cjs/template.d.ts
CHANGED
|
@@ -49,9 +49,7 @@ export declare class Template {
|
|
|
49
49
|
literalPartStack: string[][];
|
|
50
50
|
lockLiteral: boolean;
|
|
51
51
|
addLinks: SortedArray<string>;
|
|
52
|
-
doHeadLinks: boolean;
|
|
53
52
|
doneLinks: SortedArray<string>;
|
|
54
|
-
headLinks: SortedArray<string>;
|
|
55
53
|
headTitle?: string;
|
|
56
54
|
fileName?: string;
|
|
57
55
|
filePath?: string;
|
|
@@ -74,9 +72,8 @@ export declare class Template {
|
|
|
74
72
|
embedHtmlResponse(htmlResponse: HtmlResponse): void;
|
|
75
73
|
getCleanContext(): {
|
|
76
74
|
addLinks: SortedArray<string>;
|
|
77
|
-
doHeadLinks: boolean;
|
|
78
75
|
doneLinks: SortedArray<string>;
|
|
79
|
-
|
|
76
|
+
included: boolean;
|
|
80
77
|
index: number;
|
|
81
78
|
inLiteral: boolean;
|
|
82
79
|
length: number;
|
|
@@ -94,9 +91,8 @@ export declare class Template {
|
|
|
94
91
|
};
|
|
95
92
|
getContext(): {
|
|
96
93
|
addLinks: SortedArray<string>;
|
|
97
|
-
doHeadLinks: boolean;
|
|
98
94
|
doneLinks: SortedArray<string>;
|
|
99
|
-
|
|
95
|
+
included: boolean;
|
|
100
96
|
index: number;
|
|
101
97
|
inLiteral: boolean;
|
|
102
98
|
length: number;
|
|
@@ -111,9 +107,10 @@ export declare class Template {
|
|
|
111
107
|
includePath(filePath: string): string;
|
|
112
108
|
isContextClean(): boolean;
|
|
113
109
|
literalTarget(index: number, isTitle?: boolean): void;
|
|
110
|
+
normalizeLink(link: string): string;
|
|
114
111
|
parseBuffer(buffer: string): Promise<string>;
|
|
115
112
|
parseExpression(data: any, open: Open | '<', close: Close, finalClose?: Final): Promise<boolean | undefined>;
|
|
116
|
-
parseFile(fileName: string, containerFileName?: string): Promise<string>;
|
|
113
|
+
parseFile(fileName: string, containerFileName?: string | false): Promise<string>;
|
|
117
114
|
parsePath(expression: string, data: any): Promise<any>;
|
|
118
115
|
parseVariable(variable: string, data: any): Promise<any>;
|
|
119
116
|
parseVars(): Promise<string>;
|
package/cjs/template.js
CHANGED
|
@@ -11,6 +11,7 @@ const node_path_2 = require("node:path");
|
|
|
11
11
|
exports.depends = {
|
|
12
12
|
toString: async (value) => '' + value
|
|
13
13
|
};
|
|
14
|
+
const DEBUG = false;
|
|
14
15
|
const done = { done: true };
|
|
15
16
|
exports.frontScripts = new sorted_array_1.SortedArray();
|
|
16
17
|
exports.frontScripts.distinct = true;
|
|
@@ -52,9 +53,7 @@ class Template {
|
|
|
52
53
|
lockLiteral = false;
|
|
53
54
|
// html head
|
|
54
55
|
addLinks = new sorted_array_1.SortedArray();
|
|
55
|
-
doHeadLinks = false;
|
|
56
56
|
doneLinks = new sorted_array_1.SortedArray();
|
|
57
|
-
headLinks = new sorted_array_1.SortedArray();
|
|
58
57
|
headTitle;
|
|
59
58
|
// file
|
|
60
59
|
fileName;
|
|
@@ -81,7 +80,6 @@ class Template {
|
|
|
81
80
|
this.containerData = containerData;
|
|
82
81
|
this.addLinks.distinct = true;
|
|
83
82
|
this.doneLinks.distinct = true;
|
|
84
|
-
this.headLinks.distinct = true;
|
|
85
83
|
if (containerData) {
|
|
86
84
|
this.blockStack.push({ blockStart: 0, data: containerData, iteration: done });
|
|
87
85
|
}
|
|
@@ -134,19 +132,25 @@ class Template {
|
|
|
134
132
|
if (dependency[0] === '<') {
|
|
135
133
|
const script = dependency.match(/<script[^>]*\bsrc=["']([^"']+)["']/i)?.[1];
|
|
136
134
|
if (script) {
|
|
137
|
-
exports.frontScripts.
|
|
135
|
+
exports.frontScripts.push(script);
|
|
138
136
|
}
|
|
139
|
-
|
|
137
|
+
if (DEBUG)
|
|
138
|
+
console.log('addLink(', dependency, ')');
|
|
139
|
+
this.addLinks.push(dependency);
|
|
140
140
|
continue;
|
|
141
141
|
}
|
|
142
142
|
dependency = (0, node_path_1.normalize)(dependency).slice(app_dir_1.appDir.length);
|
|
143
143
|
switch (dependency.slice(dependency.lastIndexOf('.') + 1)) {
|
|
144
144
|
case 'css':
|
|
145
|
-
|
|
145
|
+
if (DEBUG)
|
|
146
|
+
console.log('addLink(', '<link href="' + dependency + '" rel="stylesheet">', ')');
|
|
147
|
+
this.addLinks.push('<link href="' + dependency + '" rel="stylesheet">');
|
|
146
148
|
continue;
|
|
147
149
|
case 'js':
|
|
148
|
-
exports.frontScripts.
|
|
149
|
-
|
|
150
|
+
exports.frontScripts.push(dependency);
|
|
151
|
+
if (DEBUG)
|
|
152
|
+
console.log('addLink(', '<script src="' + dependency + '" type="module"></script>', ')');
|
|
153
|
+
this.addLinks.push('<script src="' + dependency + '" type="module"></script>');
|
|
150
154
|
continue;
|
|
151
155
|
}
|
|
152
156
|
}
|
|
@@ -154,15 +158,12 @@ class Template {
|
|
|
154
158
|
getCleanContext() {
|
|
155
159
|
const addLinks = new sorted_array_1.SortedArray;
|
|
156
160
|
const doneLinks = new sorted_array_1.SortedArray;
|
|
157
|
-
const headLinks = new sorted_array_1.SortedArray;
|
|
158
161
|
addLinks.distinct = true;
|
|
159
162
|
doneLinks.distinct = true;
|
|
160
|
-
headLinks.distinct = true;
|
|
161
163
|
return {
|
|
162
|
-
addLinks
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
headLinks: headLinks,
|
|
164
|
+
addLinks,
|
|
165
|
+
doneLinks,
|
|
166
|
+
included: false,
|
|
166
167
|
index: this.length,
|
|
167
168
|
inLiteral: this.doLiteral,
|
|
168
169
|
length: this.source.length,
|
|
@@ -180,9 +181,8 @@ class Template {
|
|
|
180
181
|
getContext() {
|
|
181
182
|
return {
|
|
182
183
|
addLinks: this.addLinks,
|
|
183
|
-
doHeadLinks: this.doHeadLinks,
|
|
184
184
|
doneLinks: this.doneLinks,
|
|
185
|
-
|
|
185
|
+
included: this.included,
|
|
186
186
|
index: this.index,
|
|
187
187
|
inLiteral: this.inLiteral,
|
|
188
188
|
length: this.length,
|
|
@@ -196,10 +196,10 @@ class Template {
|
|
|
196
196
|
}
|
|
197
197
|
async include(path, data) {
|
|
198
198
|
const template = new (Object.getPrototypeOf(this).constructor)(data, this.blockStack[0]?.data);
|
|
199
|
+
template.addLinks = this.addLinks;
|
|
199
200
|
template.doExpression = this.doExpression;
|
|
200
|
-
template.doHeadLinks = true;
|
|
201
201
|
template.doLiteral = this.doLiteral;
|
|
202
|
-
template.doneLinks = this.
|
|
202
|
+
template.doneLinks = this.doneLinks;
|
|
203
203
|
template.included = true;
|
|
204
204
|
template.onAttribute = this.onAttribute;
|
|
205
205
|
template.onTagClose = this.onTagClose;
|
|
@@ -209,15 +209,13 @@ class Template {
|
|
|
209
209
|
const parsed = await template.parseFile(((path[0] === node_path_2.sep) || (path[1] === ':'))
|
|
210
210
|
? path
|
|
211
211
|
: (this.filePath + node_path_2.sep + path));
|
|
212
|
-
|
|
213
|
-
this.addLinks.push(...template.headLinks);
|
|
214
|
-
this.headTitle = template.headTitle;
|
|
215
|
-
}
|
|
216
|
-
this.headLinks.push(...template.headLinks);
|
|
212
|
+
this.headTitle = template.headTitle;
|
|
217
213
|
const beginPosition = parsed.indexOf('<!--BEGIN-->');
|
|
218
|
-
const endPosition = parsed.
|
|
219
|
-
if ((beginPosition
|
|
214
|
+
const endPosition = parsed.lastIndexOf('<!--END-->');
|
|
215
|
+
if ((beginPosition < 0) && (parsed[1] === '!') && parsed.startsWith('<!DOCTYPE html>')) {
|
|
220
216
|
if (this.targetReplace === '') {
|
|
217
|
+
if (DEBUG)
|
|
218
|
+
console.log('! targetReplace', path);
|
|
221
219
|
this.targetReplace = parsed;
|
|
222
220
|
}
|
|
223
221
|
return '';
|
|
@@ -234,13 +232,10 @@ class Template {
|
|
|
234
232
|
isContextClean() {
|
|
235
233
|
const clean = this.getCleanContext();
|
|
236
234
|
const context = this.getContext();
|
|
237
|
-
return context.
|
|
238
|
-
&& context.addLinks.distinct === clean.addLinks.distinct
|
|
235
|
+
return context.addLinks.distinct === clean.addLinks.distinct
|
|
239
236
|
&& context.addLinks.length === clean.addLinks.length
|
|
240
237
|
&& context.doneLinks.distinct === clean.doneLinks.distinct
|
|
241
|
-
&& context.
|
|
242
|
-
&& context.headLinks.distinct === clean.headLinks.distinct
|
|
243
|
-
&& context.headLinks.length === clean.headLinks.length
|
|
238
|
+
&& context.included === clean.included
|
|
244
239
|
&& context.index === clean.index
|
|
245
240
|
&& context.inLiteral === clean.inLiteral
|
|
246
241
|
&& context.literalPartStack.length === clean.literalPartStack.length
|
|
@@ -261,27 +256,55 @@ class Template {
|
|
|
261
256
|
combined = this.combineLiterals(this.source.substring(this.start, index));
|
|
262
257
|
this.target += combined;
|
|
263
258
|
}
|
|
264
|
-
if (isTitle && this.
|
|
259
|
+
if (isTitle && this.included) {
|
|
265
260
|
this.headTitle = combined;
|
|
266
261
|
}
|
|
267
262
|
this.start = index;
|
|
268
263
|
}
|
|
264
|
+
normalizeLink(link) {
|
|
265
|
+
if (link[0] === '/')
|
|
266
|
+
return link;
|
|
267
|
+
const result = (0, node_path_1.normalize)(this.filePath + node_path_2.sep + link).substring(app_dir_1.appDir.length);
|
|
268
|
+
return (node_path_2.sep === '/') ? result : result.replaceAll(node_path_2.sep, '/');
|
|
269
|
+
}
|
|
269
270
|
async parseBuffer(buffer) {
|
|
270
271
|
this.prefixes = this.parsers.map(([prefix]) => prefix).join('');
|
|
271
272
|
this.setSource(buffer);
|
|
272
273
|
await this.parseVars();
|
|
273
|
-
if (this.
|
|
274
|
+
if (this.included) {
|
|
274
275
|
return this.target;
|
|
275
276
|
}
|
|
276
277
|
if (this.addLinks.length) {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
278
|
+
let addLink;
|
|
279
|
+
const addLinks = new Array;
|
|
280
|
+
while (addLink = this.addLinks.shift()) {
|
|
281
|
+
for (const attribute of ['href', 'src']) {
|
|
282
|
+
let start = addLink.indexOf(attribute + '=');
|
|
283
|
+
if (start < 0)
|
|
284
|
+
continue;
|
|
285
|
+
start += attribute.length;
|
|
286
|
+
while ((addLink[start] !== '"') && (addLink[start] !== "'")) {
|
|
287
|
+
start++;
|
|
288
|
+
}
|
|
289
|
+
const quote = addLink[start++];
|
|
290
|
+
const stop = addLink.indexOf(quote, start);
|
|
291
|
+
const link = addLink.substring(start, stop);
|
|
292
|
+
if (DEBUG)
|
|
293
|
+
console.log('check(', link, ')');
|
|
294
|
+
if (!this.doneLinks.includes(link)) {
|
|
295
|
+
if (DEBUG)
|
|
296
|
+
console.log('+ addLink(', addLink, ')');
|
|
297
|
+
if (DEBUG)
|
|
298
|
+
console.log('+ doneLink(', link, ')');
|
|
299
|
+
addLinks.push(addLink);
|
|
300
|
+
this.doneLinks.push(link);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
if (addLinks.length) {
|
|
305
|
+
const position = this.target.lastIndexOf('>', this.target.indexOf('</head>')) + 1;
|
|
306
|
+
this.target = this.target.slice(0, position) + '\n\t' + addLinks.join('\n\t') + this.target.slice(position);
|
|
307
|
+
}
|
|
285
308
|
}
|
|
286
309
|
return (this.targetReplace !== '') ? this.targetReplace : this.target;
|
|
287
310
|
}
|
|
@@ -382,16 +405,27 @@ class Template {
|
|
|
382
405
|
return conditional;
|
|
383
406
|
}
|
|
384
407
|
async parseFile(fileName, containerFileName) {
|
|
385
|
-
if (
|
|
408
|
+
if (DEBUG)
|
|
409
|
+
console.log('----- parseFile', containerFileName ? 'contained' : 'fetched', this.included ? 'included' : 'final', fileName);
|
|
410
|
+
if (containerFileName) {
|
|
386
411
|
const data = this.data;
|
|
387
412
|
this.data = Object.assign({ content: () => this.include(fileName, data) }, this.blockStack[0]?.data);
|
|
388
413
|
return this.parseFile((0, node_path_1.normalize)(containerFileName));
|
|
389
414
|
}
|
|
390
415
|
this.fileName = fileName.substring(fileName.lastIndexOf(node_path_2.sep) + 1);
|
|
391
416
|
this.filePath = fileName.substring(0, fileName.lastIndexOf(node_path_2.sep));
|
|
392
|
-
|
|
417
|
+
let target = await this.parseBuffer(await (0, promises_1.readFile)(fileName, 'utf-8'));
|
|
418
|
+
if (containerFileName && this.headTitle) {
|
|
419
|
+
const position = target.indexOf('>', target.indexOf('<title') + 6) + 1;
|
|
420
|
+
target = target.slice(0, position)
|
|
421
|
+
+ this.headTitle
|
|
422
|
+
+ target.slice(target.indexOf('</title>', position));
|
|
423
|
+
}
|
|
424
|
+
return target;
|
|
393
425
|
}
|
|
394
426
|
async parsePath(expression, data) {
|
|
427
|
+
if (DEBUG)
|
|
428
|
+
console.log('parsePath', expression);
|
|
395
429
|
if (expression === '') {
|
|
396
430
|
return undefined;
|
|
397
431
|
}
|
|
@@ -439,6 +473,8 @@ class Template {
|
|
|
439
473
|
return data;
|
|
440
474
|
}
|
|
441
475
|
async parseVariable(variable, data) {
|
|
476
|
+
if (DEBUG)
|
|
477
|
+
console.log('parseVariable', variable, 'in', data);
|
|
442
478
|
if (variable === '') {
|
|
443
479
|
let dataBack;
|
|
444
480
|
do {
|
|
@@ -503,14 +539,10 @@ class Template {
|
|
|
503
539
|
const firstChar = this.source[this.index];
|
|
504
540
|
if (!this.doExpression
|
|
505
541
|
|| !this.startsExpression(firstChar)
|
|
506
|
-
|| ((firstChar === 'B')
|
|
507
|
-
|
|
508
|
-
&& (this.source.substring(this.index, this.index + 8) === 'BEGIN-->'))
|
|
509
|
-
|| ((firstChar === 'E')
|
|
510
|
-
&& this.included
|
|
511
|
-
&& (this.source.substring(this.index, this.index + 6) === 'END-->'))) {
|
|
542
|
+
|| ((firstChar === 'B') && (this.source.substring(this.index, this.index + 8) === 'BEGIN-->'))
|
|
543
|
+
|| ((firstChar === 'E') && (this.source.substring(this.index, this.index + 6) === 'END-->'))) {
|
|
512
544
|
this.index = this.source.indexOf('-->', this.index) + 3;
|
|
513
|
-
if (this.index
|
|
545
|
+
if (this.index < 3)
|
|
514
546
|
break;
|
|
515
547
|
if (this.inLiteral && (this.index > this.start)) {
|
|
516
548
|
this.sourceToTarget();
|
|
@@ -576,7 +608,7 @@ class Template {
|
|
|
576
608
|
// cdata section
|
|
577
609
|
if ((char === '[') && (this.source.substring(this.index, this.index + 6) === 'CDATA[')) {
|
|
578
610
|
this.index = this.source.indexOf(']]>', this.index + 6) + 3;
|
|
579
|
-
if (this.index
|
|
611
|
+
if (this.index < 3)
|
|
580
612
|
break;
|
|
581
613
|
}
|
|
582
614
|
// DOCTYPE
|
|
@@ -723,23 +755,25 @@ class Template {
|
|
|
723
755
|
this.literalTarget(this.index);
|
|
724
756
|
}
|
|
725
757
|
if (inLinkHRef && attributeValue.endsWith('.css')) {
|
|
726
|
-
let frontStyle =
|
|
727
|
-
.substring(app_dir_1.appDir.length);
|
|
728
|
-
if (node_path_2.sep !== '/') {
|
|
729
|
-
frontStyle = frontStyle.replaceAll(node_path_2.sep, '/');
|
|
730
|
-
}
|
|
758
|
+
let frontStyle = this.normalizeLink(this.source.substring(this.start, this.index));
|
|
731
759
|
this.target += frontStyle;
|
|
732
760
|
this.start = this.index;
|
|
761
|
+
if (!(inHead && this.included)) {
|
|
762
|
+
if (DEBUG)
|
|
763
|
+
console.log('doneLink(', frontStyle, ')');
|
|
764
|
+
this.doneLinks.push(frontStyle);
|
|
765
|
+
}
|
|
733
766
|
}
|
|
734
767
|
if (inScriptSrc && attributeValue.endsWith('.js')) {
|
|
735
|
-
let frontScript =
|
|
736
|
-
|
|
737
|
-
if (node_path_2.sep !== '/') {
|
|
738
|
-
frontScript = frontScript.replaceAll(node_path_2.sep, '/');
|
|
739
|
-
}
|
|
740
|
-
exports.frontScripts.insert(frontScript);
|
|
768
|
+
let frontScript = this.normalizeLink(this.source.substring(this.start, this.index));
|
|
769
|
+
exports.frontScripts.push(frontScript);
|
|
741
770
|
this.target += frontScript;
|
|
742
771
|
this.start = this.index;
|
|
772
|
+
if (!(inHead && this.included)) {
|
|
773
|
+
if (DEBUG)
|
|
774
|
+
console.log('doneLink(', frontScript, ')');
|
|
775
|
+
this.doneLinks.push(frontScript);
|
|
776
|
+
}
|
|
743
777
|
}
|
|
744
778
|
if (this.onAttribute)
|
|
745
779
|
this.onAttribute(attributeName, attributeValue);
|
|
@@ -788,16 +822,18 @@ class Template {
|
|
|
788
822
|
if (this.onTagClose)
|
|
789
823
|
this.onTagClose.call(this, 'script');
|
|
790
824
|
this.index = this.source.indexOf('</script>', this.index) + 9;
|
|
791
|
-
if (this.index
|
|
825
|
+
if (this.index < 9)
|
|
792
826
|
break;
|
|
793
827
|
if (this.inLiteral && (this.index > this.start)) {
|
|
794
828
|
this.sourceToTarget();
|
|
795
829
|
}
|
|
796
830
|
}
|
|
797
|
-
if (targetTagIndex > -1) {
|
|
831
|
+
if ((targetTagIndex > -1) && this.included) {
|
|
798
832
|
this.sourceToTarget();
|
|
799
833
|
const headLink = this.target.substring(targetTagIndex);
|
|
800
|
-
|
|
834
|
+
if (DEBUG)
|
|
835
|
+
console.log('addLink(', headLink, ')');
|
|
836
|
+
this.addLinks.push(headLink);
|
|
801
837
|
}
|
|
802
838
|
if (inScript) {
|
|
803
839
|
continue;
|
package/esm/template.d.ts
CHANGED
|
@@ -49,9 +49,7 @@ export declare class Template {
|
|
|
49
49
|
literalPartStack: string[][];
|
|
50
50
|
lockLiteral: boolean;
|
|
51
51
|
addLinks: SortedArray<string>;
|
|
52
|
-
doHeadLinks: boolean;
|
|
53
52
|
doneLinks: SortedArray<string>;
|
|
54
|
-
headLinks: SortedArray<string>;
|
|
55
53
|
headTitle?: string;
|
|
56
54
|
fileName?: string;
|
|
57
55
|
filePath?: string;
|
|
@@ -74,9 +72,8 @@ export declare class Template {
|
|
|
74
72
|
embedHtmlResponse(htmlResponse: HtmlResponse): void;
|
|
75
73
|
getCleanContext(): {
|
|
76
74
|
addLinks: SortedArray<string>;
|
|
77
|
-
doHeadLinks: boolean;
|
|
78
75
|
doneLinks: SortedArray<string>;
|
|
79
|
-
|
|
76
|
+
included: boolean;
|
|
80
77
|
index: number;
|
|
81
78
|
inLiteral: boolean;
|
|
82
79
|
length: number;
|
|
@@ -94,9 +91,8 @@ export declare class Template {
|
|
|
94
91
|
};
|
|
95
92
|
getContext(): {
|
|
96
93
|
addLinks: SortedArray<string>;
|
|
97
|
-
doHeadLinks: boolean;
|
|
98
94
|
doneLinks: SortedArray<string>;
|
|
99
|
-
|
|
95
|
+
included: boolean;
|
|
100
96
|
index: number;
|
|
101
97
|
inLiteral: boolean;
|
|
102
98
|
length: number;
|
|
@@ -111,9 +107,10 @@ export declare class Template {
|
|
|
111
107
|
includePath(filePath: string): string;
|
|
112
108
|
isContextClean(): boolean;
|
|
113
109
|
literalTarget(index: number, isTitle?: boolean): void;
|
|
110
|
+
normalizeLink(link: string): string;
|
|
114
111
|
parseBuffer(buffer: string): Promise<string>;
|
|
115
112
|
parseExpression(data: any, open: Open | '<', close: Close, finalClose?: Final): Promise<boolean | undefined>;
|
|
116
|
-
parseFile(fileName: string, containerFileName?: string): Promise<string>;
|
|
113
|
+
parseFile(fileName: string, containerFileName?: string | false): Promise<string>;
|
|
117
114
|
parsePath(expression: string, data: any): Promise<any>;
|
|
118
115
|
parseVariable(variable: string, data: any): Promise<any>;
|
|
119
116
|
parseVars(): Promise<string>;
|
package/esm/template.js
CHANGED
|
@@ -7,6 +7,7 @@ import { sep } from 'node:path';
|
|
|
7
7
|
export const depends = {
|
|
8
8
|
toString: async (value) => '' + value
|
|
9
9
|
};
|
|
10
|
+
const DEBUG = false;
|
|
10
11
|
const done = { done: true };
|
|
11
12
|
export const frontScripts = new SortedArray();
|
|
12
13
|
frontScripts.distinct = true;
|
|
@@ -47,9 +48,7 @@ export class Template {
|
|
|
47
48
|
lockLiteral = false;
|
|
48
49
|
// html head
|
|
49
50
|
addLinks = new SortedArray();
|
|
50
|
-
doHeadLinks = false;
|
|
51
51
|
doneLinks = new SortedArray();
|
|
52
|
-
headLinks = new SortedArray();
|
|
53
52
|
headTitle;
|
|
54
53
|
// file
|
|
55
54
|
fileName;
|
|
@@ -76,7 +75,6 @@ export class Template {
|
|
|
76
75
|
this.containerData = containerData;
|
|
77
76
|
this.addLinks.distinct = true;
|
|
78
77
|
this.doneLinks.distinct = true;
|
|
79
|
-
this.headLinks.distinct = true;
|
|
80
78
|
if (containerData) {
|
|
81
79
|
this.blockStack.push({ blockStart: 0, data: containerData, iteration: done });
|
|
82
80
|
}
|
|
@@ -129,19 +127,25 @@ export class Template {
|
|
|
129
127
|
if (dependency[0] === '<') {
|
|
130
128
|
const script = dependency.match(/<script[^>]*\bsrc=["']([^"']+)["']/i)?.[1];
|
|
131
129
|
if (script) {
|
|
132
|
-
frontScripts.
|
|
130
|
+
frontScripts.push(script);
|
|
133
131
|
}
|
|
134
|
-
|
|
132
|
+
if (DEBUG)
|
|
133
|
+
console.log('addLink(', dependency, ')');
|
|
134
|
+
this.addLinks.push(dependency);
|
|
135
135
|
continue;
|
|
136
136
|
}
|
|
137
137
|
dependency = normalize(dependency).slice(appDir.length);
|
|
138
138
|
switch (dependency.slice(dependency.lastIndexOf('.') + 1)) {
|
|
139
139
|
case 'css':
|
|
140
|
-
|
|
140
|
+
if (DEBUG)
|
|
141
|
+
console.log('addLink(', '<link href="' + dependency + '" rel="stylesheet">', ')');
|
|
142
|
+
this.addLinks.push('<link href="' + dependency + '" rel="stylesheet">');
|
|
141
143
|
continue;
|
|
142
144
|
case 'js':
|
|
143
|
-
frontScripts.
|
|
144
|
-
|
|
145
|
+
frontScripts.push(dependency);
|
|
146
|
+
if (DEBUG)
|
|
147
|
+
console.log('addLink(', '<script src="' + dependency + '" type="module"></script>', ')');
|
|
148
|
+
this.addLinks.push('<script src="' + dependency + '" type="module"></script>');
|
|
145
149
|
continue;
|
|
146
150
|
}
|
|
147
151
|
}
|
|
@@ -149,15 +153,12 @@ export class Template {
|
|
|
149
153
|
getCleanContext() {
|
|
150
154
|
const addLinks = new SortedArray;
|
|
151
155
|
const doneLinks = new SortedArray;
|
|
152
|
-
const headLinks = new SortedArray;
|
|
153
156
|
addLinks.distinct = true;
|
|
154
157
|
doneLinks.distinct = true;
|
|
155
|
-
headLinks.distinct = true;
|
|
156
158
|
return {
|
|
157
|
-
addLinks
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
headLinks: headLinks,
|
|
159
|
+
addLinks,
|
|
160
|
+
doneLinks,
|
|
161
|
+
included: false,
|
|
161
162
|
index: this.length,
|
|
162
163
|
inLiteral: this.doLiteral,
|
|
163
164
|
length: this.source.length,
|
|
@@ -175,9 +176,8 @@ export class Template {
|
|
|
175
176
|
getContext() {
|
|
176
177
|
return {
|
|
177
178
|
addLinks: this.addLinks,
|
|
178
|
-
doHeadLinks: this.doHeadLinks,
|
|
179
179
|
doneLinks: this.doneLinks,
|
|
180
|
-
|
|
180
|
+
included: this.included,
|
|
181
181
|
index: this.index,
|
|
182
182
|
inLiteral: this.inLiteral,
|
|
183
183
|
length: this.length,
|
|
@@ -191,10 +191,10 @@ export class Template {
|
|
|
191
191
|
}
|
|
192
192
|
async include(path, data) {
|
|
193
193
|
const template = new (Object.getPrototypeOf(this).constructor)(data, this.blockStack[0]?.data);
|
|
194
|
+
template.addLinks = this.addLinks;
|
|
194
195
|
template.doExpression = this.doExpression;
|
|
195
|
-
template.doHeadLinks = true;
|
|
196
196
|
template.doLiteral = this.doLiteral;
|
|
197
|
-
template.doneLinks = this.
|
|
197
|
+
template.doneLinks = this.doneLinks;
|
|
198
198
|
template.included = true;
|
|
199
199
|
template.onAttribute = this.onAttribute;
|
|
200
200
|
template.onTagClose = this.onTagClose;
|
|
@@ -204,15 +204,13 @@ export class Template {
|
|
|
204
204
|
const parsed = await template.parseFile(((path[0] === sep) || (path[1] === ':'))
|
|
205
205
|
? path
|
|
206
206
|
: (this.filePath + sep + path));
|
|
207
|
-
|
|
208
|
-
this.addLinks.push(...template.headLinks);
|
|
209
|
-
this.headTitle = template.headTitle;
|
|
210
|
-
}
|
|
211
|
-
this.headLinks.push(...template.headLinks);
|
|
207
|
+
this.headTitle = template.headTitle;
|
|
212
208
|
const beginPosition = parsed.indexOf('<!--BEGIN-->');
|
|
213
|
-
const endPosition = parsed.
|
|
214
|
-
if ((beginPosition
|
|
209
|
+
const endPosition = parsed.lastIndexOf('<!--END-->');
|
|
210
|
+
if ((beginPosition < 0) && (parsed[1] === '!') && parsed.startsWith('<!DOCTYPE html>')) {
|
|
215
211
|
if (this.targetReplace === '') {
|
|
212
|
+
if (DEBUG)
|
|
213
|
+
console.log('! targetReplace', path);
|
|
216
214
|
this.targetReplace = parsed;
|
|
217
215
|
}
|
|
218
216
|
return '';
|
|
@@ -229,13 +227,10 @@ export class Template {
|
|
|
229
227
|
isContextClean() {
|
|
230
228
|
const clean = this.getCleanContext();
|
|
231
229
|
const context = this.getContext();
|
|
232
|
-
return context.
|
|
233
|
-
&& context.addLinks.distinct === clean.addLinks.distinct
|
|
230
|
+
return context.addLinks.distinct === clean.addLinks.distinct
|
|
234
231
|
&& context.addLinks.length === clean.addLinks.length
|
|
235
232
|
&& context.doneLinks.distinct === clean.doneLinks.distinct
|
|
236
|
-
&& context.
|
|
237
|
-
&& context.headLinks.distinct === clean.headLinks.distinct
|
|
238
|
-
&& context.headLinks.length === clean.headLinks.length
|
|
233
|
+
&& context.included === clean.included
|
|
239
234
|
&& context.index === clean.index
|
|
240
235
|
&& context.inLiteral === clean.inLiteral
|
|
241
236
|
&& context.literalPartStack.length === clean.literalPartStack.length
|
|
@@ -256,27 +251,55 @@ export class Template {
|
|
|
256
251
|
combined = this.combineLiterals(this.source.substring(this.start, index));
|
|
257
252
|
this.target += combined;
|
|
258
253
|
}
|
|
259
|
-
if (isTitle && this.
|
|
254
|
+
if (isTitle && this.included) {
|
|
260
255
|
this.headTitle = combined;
|
|
261
256
|
}
|
|
262
257
|
this.start = index;
|
|
263
258
|
}
|
|
259
|
+
normalizeLink(link) {
|
|
260
|
+
if (link[0] === '/')
|
|
261
|
+
return link;
|
|
262
|
+
const result = normalize(this.filePath + sep + link).substring(appDir.length);
|
|
263
|
+
return (sep === '/') ? result : result.replaceAll(sep, '/');
|
|
264
|
+
}
|
|
264
265
|
async parseBuffer(buffer) {
|
|
265
266
|
this.prefixes = this.parsers.map(([prefix]) => prefix).join('');
|
|
266
267
|
this.setSource(buffer);
|
|
267
268
|
await this.parseVars();
|
|
268
|
-
if (this.
|
|
269
|
+
if (this.included) {
|
|
269
270
|
return this.target;
|
|
270
271
|
}
|
|
271
272
|
if (this.addLinks.length) {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
273
|
+
let addLink;
|
|
274
|
+
const addLinks = new Array;
|
|
275
|
+
while (addLink = this.addLinks.shift()) {
|
|
276
|
+
for (const attribute of ['href', 'src']) {
|
|
277
|
+
let start = addLink.indexOf(attribute + '=');
|
|
278
|
+
if (start < 0)
|
|
279
|
+
continue;
|
|
280
|
+
start += attribute.length;
|
|
281
|
+
while ((addLink[start] !== '"') && (addLink[start] !== "'")) {
|
|
282
|
+
start++;
|
|
283
|
+
}
|
|
284
|
+
const quote = addLink[start++];
|
|
285
|
+
const stop = addLink.indexOf(quote, start);
|
|
286
|
+
const link = addLink.substring(start, stop);
|
|
287
|
+
if (DEBUG)
|
|
288
|
+
console.log('check(', link, ')');
|
|
289
|
+
if (!this.doneLinks.includes(link)) {
|
|
290
|
+
if (DEBUG)
|
|
291
|
+
console.log('+ addLink(', addLink, ')');
|
|
292
|
+
if (DEBUG)
|
|
293
|
+
console.log('+ doneLink(', link, ')');
|
|
294
|
+
addLinks.push(addLink);
|
|
295
|
+
this.doneLinks.push(link);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (addLinks.length) {
|
|
300
|
+
const position = this.target.lastIndexOf('>', this.target.indexOf('</head>')) + 1;
|
|
301
|
+
this.target = this.target.slice(0, position) + '\n\t' + addLinks.join('\n\t') + this.target.slice(position);
|
|
302
|
+
}
|
|
280
303
|
}
|
|
281
304
|
return (this.targetReplace !== '') ? this.targetReplace : this.target;
|
|
282
305
|
}
|
|
@@ -377,16 +400,27 @@ export class Template {
|
|
|
377
400
|
return conditional;
|
|
378
401
|
}
|
|
379
402
|
async parseFile(fileName, containerFileName) {
|
|
380
|
-
if (
|
|
403
|
+
if (DEBUG)
|
|
404
|
+
console.log('----- parseFile', containerFileName ? 'contained' : 'fetched', this.included ? 'included' : 'final', fileName);
|
|
405
|
+
if (containerFileName) {
|
|
381
406
|
const data = this.data;
|
|
382
407
|
this.data = Object.assign({ content: () => this.include(fileName, data) }, this.blockStack[0]?.data);
|
|
383
408
|
return this.parseFile(normalize(containerFileName));
|
|
384
409
|
}
|
|
385
410
|
this.fileName = fileName.substring(fileName.lastIndexOf(sep) + 1);
|
|
386
411
|
this.filePath = fileName.substring(0, fileName.lastIndexOf(sep));
|
|
387
|
-
|
|
412
|
+
let target = await this.parseBuffer(await readFile(fileName, 'utf-8'));
|
|
413
|
+
if (containerFileName && this.headTitle) {
|
|
414
|
+
const position = target.indexOf('>', target.indexOf('<title') + 6) + 1;
|
|
415
|
+
target = target.slice(0, position)
|
|
416
|
+
+ this.headTitle
|
|
417
|
+
+ target.slice(target.indexOf('</title>', position));
|
|
418
|
+
}
|
|
419
|
+
return target;
|
|
388
420
|
}
|
|
389
421
|
async parsePath(expression, data) {
|
|
422
|
+
if (DEBUG)
|
|
423
|
+
console.log('parsePath', expression);
|
|
390
424
|
if (expression === '') {
|
|
391
425
|
return undefined;
|
|
392
426
|
}
|
|
@@ -434,6 +468,8 @@ export class Template {
|
|
|
434
468
|
return data;
|
|
435
469
|
}
|
|
436
470
|
async parseVariable(variable, data) {
|
|
471
|
+
if (DEBUG)
|
|
472
|
+
console.log('parseVariable', variable, 'in', data);
|
|
437
473
|
if (variable === '') {
|
|
438
474
|
let dataBack;
|
|
439
475
|
do {
|
|
@@ -498,14 +534,10 @@ export class Template {
|
|
|
498
534
|
const firstChar = this.source[this.index];
|
|
499
535
|
if (!this.doExpression
|
|
500
536
|
|| !this.startsExpression(firstChar)
|
|
501
|
-
|| ((firstChar === 'B')
|
|
502
|
-
|
|
503
|
-
&& (this.source.substring(this.index, this.index + 8) === 'BEGIN-->'))
|
|
504
|
-
|| ((firstChar === 'E')
|
|
505
|
-
&& this.included
|
|
506
|
-
&& (this.source.substring(this.index, this.index + 6) === 'END-->'))) {
|
|
537
|
+
|| ((firstChar === 'B') && (this.source.substring(this.index, this.index + 8) === 'BEGIN-->'))
|
|
538
|
+
|| ((firstChar === 'E') && (this.source.substring(this.index, this.index + 6) === 'END-->'))) {
|
|
507
539
|
this.index = this.source.indexOf('-->', this.index) + 3;
|
|
508
|
-
if (this.index
|
|
540
|
+
if (this.index < 3)
|
|
509
541
|
break;
|
|
510
542
|
if (this.inLiteral && (this.index > this.start)) {
|
|
511
543
|
this.sourceToTarget();
|
|
@@ -571,7 +603,7 @@ export class Template {
|
|
|
571
603
|
// cdata section
|
|
572
604
|
if ((char === '[') && (this.source.substring(this.index, this.index + 6) === 'CDATA[')) {
|
|
573
605
|
this.index = this.source.indexOf(']]>', this.index + 6) + 3;
|
|
574
|
-
if (this.index
|
|
606
|
+
if (this.index < 3)
|
|
575
607
|
break;
|
|
576
608
|
}
|
|
577
609
|
// DOCTYPE
|
|
@@ -718,23 +750,25 @@ export class Template {
|
|
|
718
750
|
this.literalTarget(this.index);
|
|
719
751
|
}
|
|
720
752
|
if (inLinkHRef && attributeValue.endsWith('.css')) {
|
|
721
|
-
let frontStyle =
|
|
722
|
-
.substring(appDir.length);
|
|
723
|
-
if (sep !== '/') {
|
|
724
|
-
frontStyle = frontStyle.replaceAll(sep, '/');
|
|
725
|
-
}
|
|
753
|
+
let frontStyle = this.normalizeLink(this.source.substring(this.start, this.index));
|
|
726
754
|
this.target += frontStyle;
|
|
727
755
|
this.start = this.index;
|
|
756
|
+
if (!(inHead && this.included)) {
|
|
757
|
+
if (DEBUG)
|
|
758
|
+
console.log('doneLink(', frontStyle, ')');
|
|
759
|
+
this.doneLinks.push(frontStyle);
|
|
760
|
+
}
|
|
728
761
|
}
|
|
729
762
|
if (inScriptSrc && attributeValue.endsWith('.js')) {
|
|
730
|
-
let frontScript =
|
|
731
|
-
|
|
732
|
-
if (sep !== '/') {
|
|
733
|
-
frontScript = frontScript.replaceAll(sep, '/');
|
|
734
|
-
}
|
|
735
|
-
frontScripts.insert(frontScript);
|
|
763
|
+
let frontScript = this.normalizeLink(this.source.substring(this.start, this.index));
|
|
764
|
+
frontScripts.push(frontScript);
|
|
736
765
|
this.target += frontScript;
|
|
737
766
|
this.start = this.index;
|
|
767
|
+
if (!(inHead && this.included)) {
|
|
768
|
+
if (DEBUG)
|
|
769
|
+
console.log('doneLink(', frontScript, ')');
|
|
770
|
+
this.doneLinks.push(frontScript);
|
|
771
|
+
}
|
|
738
772
|
}
|
|
739
773
|
if (this.onAttribute)
|
|
740
774
|
this.onAttribute(attributeName, attributeValue);
|
|
@@ -783,16 +817,18 @@ export class Template {
|
|
|
783
817
|
if (this.onTagClose)
|
|
784
818
|
this.onTagClose.call(this, 'script');
|
|
785
819
|
this.index = this.source.indexOf('</script>', this.index) + 9;
|
|
786
|
-
if (this.index
|
|
820
|
+
if (this.index < 9)
|
|
787
821
|
break;
|
|
788
822
|
if (this.inLiteral && (this.index > this.start)) {
|
|
789
823
|
this.sourceToTarget();
|
|
790
824
|
}
|
|
791
825
|
}
|
|
792
|
-
if (targetTagIndex > -1) {
|
|
826
|
+
if ((targetTagIndex > -1) && this.included) {
|
|
793
827
|
this.sourceToTarget();
|
|
794
828
|
const headLink = this.target.substring(targetTagIndex);
|
|
795
|
-
|
|
829
|
+
if (DEBUG)
|
|
830
|
+
console.log('addLink(', headLink, ')');
|
|
831
|
+
this.addLinks.push(headLink);
|
|
796
832
|
}
|
|
797
833
|
if (inScript) {
|
|
798
834
|
continue;
|
package/package.json
CHANGED