@ui-doc/html-renderer 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +9 -0
- package/README.md +251 -0
- package/dist/HtmlCurlyBraceLexer.d.ts +25 -0
- package/dist/HtmlRenderer.d.ts +21 -0
- package/dist/InlineReader.d.ts +18 -0
- package/dist/NodeParser.d.ts +12 -0
- package/dist/TemplateLoader.d.ts +9 -0
- package/dist/assets/app.d.ts +1 -0
- package/dist/assets/src/base.d.ts +1 -0
- package/dist/assets/src/example.d.ts +1 -0
- package/dist/assets/src/sidebar.d.ts +1 -0
- package/dist/assets/ui-doc.cjs +81 -0
- package/dist/assets/ui-doc.cjs.map +1 -0
- package/dist/assets/ui-doc.css +359 -0
- package/dist/assets/ui-doc.css.map +1 -0
- package/dist/assets/ui-doc.js.map +1 -0
- package/dist/assets/ui-doc.min.css +1 -0
- package/dist/assets/ui-doc.min.js +1 -0
- package/dist/assets/ui-doc.mjs +79 -0
- package/dist/assets/ui-doc.mjs.map +1 -0
- package/dist/errors/HtmlRendererError.d.ts +3 -0
- package/dist/errors/HtmlRendererSyntaxError.d.ts +13 -0
- package/dist/errors/ParserError.d.ts +3 -0
- package/dist/errors/TagNodeError.d.ts +3 -0
- package/dist/errors/index.d.ts +4 -0
- package/dist/index.cjs +981 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.mjs +958 -0
- package/dist/index.mjs.map +1 -0
- package/dist/nodes/CommentNode.d.ts +6 -0
- package/dist/nodes/Node.d.ts +14 -0
- package/dist/nodes/TagNode.d.ts +4 -0
- package/dist/nodes/TemplateNode.d.ts +6 -0
- package/dist/nodes/index.d.ts +10 -0
- package/dist/nodes/tags/debug.d.ts +11 -0
- package/dist/nodes/tags/for.d.ts +13 -0
- package/dist/nodes/tags/if.d.ts +18 -0
- package/dist/nodes/tags/index.d.ts +3 -0
- package/dist/nodes/tags/page.d.ts +13 -0
- package/dist/nodes/tags/partial.d.ts +13 -0
- package/dist/nodes/tags/var.d.ts +13 -0
- package/dist/types/base.d.ts +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/lexer.d.ts +23 -0
- package/dist/types/parser.d.ts +25 -0
- package/dist/types/reader.d.ts +35 -0
- package/dist/types/renderer.d.ts +14 -0
- package/dist/types/token.d.ts +40 -0
- package/dist/utils/index.d.ts +2 -0
- package/package.json +71 -0
- package/scripts/app.ts +8 -0
- package/scripts/src/base.ts +7 -0
- package/scripts/src/example.ts +31 -0
- package/scripts/src/sidebar.ts +46 -0
- package/styles/01_resets/initial.css +18 -0
- package/styles/01_resets/root.css +36 -0
- package/styles/01_resets/typography.css +67 -0
- package/styles/02_objects/background.css +7 -0
- package/styles/02_objects/control.css +25 -0
- package/styles/02_objects/margin.css +44 -0
- package/styles/02_objects/padding.css +44 -0
- package/styles/02_objects/text.css +3 -0
- package/styles/02_objects/width.css +16 -0
- package/styles/03_components/example-markup.css +31 -0
- package/styles/03_components/nav/list.css +42 -0
- package/styles/03_components/nav/main.css +39 -0
- package/styles/03_components/text-flow.css +5 -0
- package/styles/04_layouts/page.css +68 -0
- package/styles/index.css +17 -0
- package/templates/layouts/default.html +24 -0
- package/templates/layouts/example.html +29 -0
- package/templates/pages/default.html +14 -0
- package/templates/pages/index.html +3 -0
- package/templates/partials/code.html +5 -0
- package/templates/partials/content.html +7 -0
- package/templates/partials/example.html +5 -0
- package/templates/partials/nav-main.html +9 -0
- package/templates/partials/nav-sidebar.html +18 -0
- package/templates/partials/section-inner.html +5 -0
- package/templates/partials/section.html +1 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,958 @@
|
|
|
1
|
+
class HTMLRendererError extends Error {
|
|
2
|
+
constructor(message) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.name = 'HTMLRendererError';
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
class HTMLRendererSyntaxError extends SyntaxError {
|
|
9
|
+
constructor({ message, code, column, line, source, }) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = 'HTMLRendererSyntaxError';
|
|
12
|
+
this.code = code;
|
|
13
|
+
this.line = line;
|
|
14
|
+
this.column = column;
|
|
15
|
+
this.source = source;
|
|
16
|
+
this.stack = `HTMLRendererSyntaxError: ${message}\n in ${this.source}:${this.line}:${this.column}\n\n ${code.replaceAll('\n', '\n ')}`;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
class ParserError extends Error {
|
|
21
|
+
constructor(message) {
|
|
22
|
+
super(message);
|
|
23
|
+
this.name = 'ParserError';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
class TagNodeError extends Error {
|
|
28
|
+
constructor(message) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.name = 'TagNodeSyntaxError';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const IDENTIFIER_CHARS = {
|
|
35
|
+
identifier: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.',
|
|
36
|
+
'tag-identifier': 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
|
37
|
+
};
|
|
38
|
+
class HtmlCurlyBraceLexer {
|
|
39
|
+
constructor(reader) {
|
|
40
|
+
this.currentTokens = [];
|
|
41
|
+
this.tagConsuming = false;
|
|
42
|
+
this.tagIdentified = false;
|
|
43
|
+
this.reader = reader;
|
|
44
|
+
}
|
|
45
|
+
debug() {
|
|
46
|
+
return this.reader.debug();
|
|
47
|
+
}
|
|
48
|
+
peek(k = 1) {
|
|
49
|
+
this.consumeNextTokens(k);
|
|
50
|
+
return k === 1
|
|
51
|
+
? this.currentTokens.slice(0, k)[0]
|
|
52
|
+
: this.currentTokens.slice(0, k);
|
|
53
|
+
}
|
|
54
|
+
consume(k = 1) {
|
|
55
|
+
this.consumeNextTokens(k);
|
|
56
|
+
return k === 1
|
|
57
|
+
? this.currentTokens.splice(0, k)[0]
|
|
58
|
+
: this.currentTokens.splice(0, k);
|
|
59
|
+
}
|
|
60
|
+
consumeNextTokens(k = 1) {
|
|
61
|
+
while (this.currentTokens.length < k) {
|
|
62
|
+
this.currentTokens.push(this.consumeNextToken());
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
consumeNextToken() {
|
|
66
|
+
if (this.reader.isEof()) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
if (this.tagConsuming) {
|
|
70
|
+
return this.progressTag();
|
|
71
|
+
}
|
|
72
|
+
const char = this.reader.peak();
|
|
73
|
+
if (char === '{' && this.reader.peak(2) === '{{') {
|
|
74
|
+
return this.consumeTagOpen();
|
|
75
|
+
}
|
|
76
|
+
if (char === '<' && this.reader.peak(4) === '<!--') {
|
|
77
|
+
return this.consumeComment();
|
|
78
|
+
}
|
|
79
|
+
return this.consumeTemplate();
|
|
80
|
+
}
|
|
81
|
+
consumeTagOpen() {
|
|
82
|
+
this.reader.consume(2);
|
|
83
|
+
this.tagConsuming = true;
|
|
84
|
+
this.tagIdentified = false;
|
|
85
|
+
return {
|
|
86
|
+
type: 'tag-open',
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
consumeTagClose() {
|
|
90
|
+
this.reader.consume(2);
|
|
91
|
+
this.tagConsuming = false;
|
|
92
|
+
this.tagIdentified = false;
|
|
93
|
+
return {
|
|
94
|
+
type: 'tag-close',
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
consumeTagSeparator() {
|
|
98
|
+
this.reader.consume();
|
|
99
|
+
return {
|
|
100
|
+
type: 'tag-separator',
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
consumeComment() {
|
|
104
|
+
this.reader.consume(4);
|
|
105
|
+
let content = '';
|
|
106
|
+
while (!this.reader.isEof()) {
|
|
107
|
+
if (this.reader.peak(3) === '-->') {
|
|
108
|
+
this.reader.consume(3);
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
content += this.reader.consume();
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
content: content.trim(),
|
|
115
|
+
type: 'comment',
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
consumeTemplate() {
|
|
119
|
+
let content = '';
|
|
120
|
+
while (!this.reader.isEof()) {
|
|
121
|
+
const peek = this.reader.peak();
|
|
122
|
+
if (peek === '{' && this.reader.peak(2) === '{{') {
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
if (peek === '<' && this.reader.peak(4) === '<!--') {
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
content += this.reader.consume();
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
content,
|
|
132
|
+
type: 'template',
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
progressTag() {
|
|
136
|
+
const char = this.reader.peak();
|
|
137
|
+
if (char === ' ' || char === '\n' || char === '\r' || char === '\t') {
|
|
138
|
+
this.reader.consume();
|
|
139
|
+
return this.progressTag();
|
|
140
|
+
}
|
|
141
|
+
if (char === '}' && this.reader.peak(2) === '}}') {
|
|
142
|
+
return this.consumeTagClose();
|
|
143
|
+
}
|
|
144
|
+
if (char === '/') {
|
|
145
|
+
return this.consumeTagEnd();
|
|
146
|
+
}
|
|
147
|
+
if (!this.tagIdentified) {
|
|
148
|
+
this.tagIdentified = true;
|
|
149
|
+
return this.consumeIdentifier('tag-identifier');
|
|
150
|
+
}
|
|
151
|
+
if (char === ':') {
|
|
152
|
+
return this.consumeTagSeparator();
|
|
153
|
+
}
|
|
154
|
+
if (char === '"' || char === "'") {
|
|
155
|
+
return this.consumeString();
|
|
156
|
+
}
|
|
157
|
+
if (char === '1' ||
|
|
158
|
+
char === '2' ||
|
|
159
|
+
char === '3' ||
|
|
160
|
+
char === '4' ||
|
|
161
|
+
char === '5' ||
|
|
162
|
+
char === '6' ||
|
|
163
|
+
char === '7' ||
|
|
164
|
+
char === '8' ||
|
|
165
|
+
char === '9' ||
|
|
166
|
+
char === '0') {
|
|
167
|
+
return this.consumeNumber();
|
|
168
|
+
}
|
|
169
|
+
if (char === 't' && this.reader.peak(4) === 'true') {
|
|
170
|
+
return this.consumeBoolean(true);
|
|
171
|
+
}
|
|
172
|
+
if (char === 'f' && this.reader.peak(5) === 'false') {
|
|
173
|
+
return this.consumeBoolean(false);
|
|
174
|
+
}
|
|
175
|
+
if (char === '=' || char === '!' || char === '<' || char === '>') {
|
|
176
|
+
return this.consumeOperator();
|
|
177
|
+
}
|
|
178
|
+
return this.consumeIdentifier();
|
|
179
|
+
}
|
|
180
|
+
consumeTagEnd() {
|
|
181
|
+
this.reader.consume();
|
|
182
|
+
return {
|
|
183
|
+
type: 'tag-end',
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
consumeString() {
|
|
187
|
+
const quote = this.reader.consume();
|
|
188
|
+
let value = '';
|
|
189
|
+
while (!this.reader.isEof()) {
|
|
190
|
+
const char = this.reader.consume();
|
|
191
|
+
if (char === quote) {
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
value += char;
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
type: 'string',
|
|
198
|
+
value,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
consumeNumber() {
|
|
202
|
+
let value = '';
|
|
203
|
+
while (!this.reader.isEof()) {
|
|
204
|
+
const char = this.reader.peak();
|
|
205
|
+
if (char === '1' ||
|
|
206
|
+
char === '2' ||
|
|
207
|
+
char === '3' ||
|
|
208
|
+
char === '4' ||
|
|
209
|
+
char === '5' ||
|
|
210
|
+
char === '6' ||
|
|
211
|
+
char === '7' ||
|
|
212
|
+
char === '8' ||
|
|
213
|
+
char === '9' ||
|
|
214
|
+
char === '0' ||
|
|
215
|
+
char === '.') {
|
|
216
|
+
value += this.reader.consume();
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
type: 'number',
|
|
224
|
+
value: parseFloat(value),
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
consumeBoolean(value) {
|
|
228
|
+
this.reader.consume(value ? 4 : 5);
|
|
229
|
+
return {
|
|
230
|
+
type: 'boolean',
|
|
231
|
+
value,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
consumeOperator() {
|
|
235
|
+
let operator = '';
|
|
236
|
+
while (!this.reader.isEof()) {
|
|
237
|
+
const char = this.reader.peak();
|
|
238
|
+
if (char === '=' || char === '!' || char === '<' || char === '>') {
|
|
239
|
+
operator += this.reader.consume();
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return {
|
|
246
|
+
operator,
|
|
247
|
+
type: 'operator',
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
consumeIdentifier(type = 'identifier') {
|
|
251
|
+
const chars = IDENTIFIER_CHARS[type];
|
|
252
|
+
let name = '';
|
|
253
|
+
while (!this.reader.isEof()) {
|
|
254
|
+
const char = this.reader.peak();
|
|
255
|
+
if (!chars.includes(char)) {
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
name += this.reader.consume();
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
name,
|
|
262
|
+
type,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
class InlineReader {
|
|
268
|
+
constructor(input, source = 'inline') {
|
|
269
|
+
this.currentLine = 1;
|
|
270
|
+
this.currentPos = 1;
|
|
271
|
+
this.currentContent = '';
|
|
272
|
+
this.input = input;
|
|
273
|
+
this.source = source;
|
|
274
|
+
}
|
|
275
|
+
peak(k = 1) {
|
|
276
|
+
return this.input.slice(0, k);
|
|
277
|
+
}
|
|
278
|
+
consume(k = 1) {
|
|
279
|
+
const result = this.input.slice(0, k);
|
|
280
|
+
if (result.includes('\n')) {
|
|
281
|
+
const lines = result.split('\n');
|
|
282
|
+
this.currentLine += lines.length - 1;
|
|
283
|
+
this.currentContent = lines[lines.length - 1];
|
|
284
|
+
this.currentPos = this.currentContent.length + 1;
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
this.currentPos += k;
|
|
288
|
+
this.currentContent += result;
|
|
289
|
+
}
|
|
290
|
+
this.input = this.input.slice(k);
|
|
291
|
+
return result;
|
|
292
|
+
}
|
|
293
|
+
isEof() {
|
|
294
|
+
return this.input.length === 0;
|
|
295
|
+
}
|
|
296
|
+
debug() {
|
|
297
|
+
const lines = this.input.split('\n', 1);
|
|
298
|
+
return {
|
|
299
|
+
content: this.currentContent + lines[0],
|
|
300
|
+
line: this.currentLine,
|
|
301
|
+
pos: this.currentPos,
|
|
302
|
+
source: this.source,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function instanceofReader(object) {
|
|
308
|
+
return (typeof object.peak === 'function' &&
|
|
309
|
+
typeof object.consume === 'function' &&
|
|
310
|
+
typeof object.isEof === 'function' &&
|
|
311
|
+
typeof object.debug === 'function');
|
|
312
|
+
}
|
|
313
|
+
class HtmlRenderer {
|
|
314
|
+
constructor(parser) {
|
|
315
|
+
this.layouts = {};
|
|
316
|
+
this.partials = {};
|
|
317
|
+
this.pages = {};
|
|
318
|
+
this.parser = parser;
|
|
319
|
+
}
|
|
320
|
+
addLayout(name, layout) {
|
|
321
|
+
this.layouts[name] = this.parse(layout);
|
|
322
|
+
return this;
|
|
323
|
+
}
|
|
324
|
+
addPartial(name, partial) {
|
|
325
|
+
this.partials[name] = this.parse(partial);
|
|
326
|
+
return this;
|
|
327
|
+
}
|
|
328
|
+
addPage(name, page) {
|
|
329
|
+
this.pages[name] = this.parse(page);
|
|
330
|
+
return this;
|
|
331
|
+
}
|
|
332
|
+
parse(input) {
|
|
333
|
+
const reader = !instanceofReader(input) ? new InlineReader(input.content, input.source) : input;
|
|
334
|
+
try {
|
|
335
|
+
return this.parser.parse(reader);
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
if (error instanceof ParserError) {
|
|
339
|
+
const debug = reader.debug();
|
|
340
|
+
throw new HTMLRendererSyntaxError({
|
|
341
|
+
code: debug.content,
|
|
342
|
+
column: debug.pos,
|
|
343
|
+
line: debug.line,
|
|
344
|
+
message: error.message,
|
|
345
|
+
source: debug.source,
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
throw error;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
generate(context, layout) {
|
|
352
|
+
layout = layout !== null && layout !== void 0 ? layout : 'default';
|
|
353
|
+
const content = this.layouts[layout] || undefined;
|
|
354
|
+
if (!content) {
|
|
355
|
+
throw new HTMLRendererError(`Layout "${layout}" not found. Please register it using "addLayout" method.`);
|
|
356
|
+
}
|
|
357
|
+
return this.render(content, this.generateContext(context));
|
|
358
|
+
}
|
|
359
|
+
page(name, context) {
|
|
360
|
+
const content = this.pages[name] || this.pages.default || undefined;
|
|
361
|
+
if (!content) {
|
|
362
|
+
throw new HTMLRendererError(`Page "${name}" not found. Please register it using "addPage" method.`);
|
|
363
|
+
}
|
|
364
|
+
return this.render(content, context);
|
|
365
|
+
}
|
|
366
|
+
partial(name, context) {
|
|
367
|
+
const content = this.partials[name] || this.partials.default || undefined;
|
|
368
|
+
if (!content) {
|
|
369
|
+
throw new HTMLRendererError(`Partial "${name}" not found. Please register it using "addPartial" method.`);
|
|
370
|
+
}
|
|
371
|
+
return this.render(content, context !== null && context !== void 0 ? context : {});
|
|
372
|
+
}
|
|
373
|
+
render(rootNode, context) {
|
|
374
|
+
return rootNode.render(context, this);
|
|
375
|
+
}
|
|
376
|
+
generateContext(context) {
|
|
377
|
+
const renderContext = context;
|
|
378
|
+
renderContext.styles = context.assets
|
|
379
|
+
.filter((asset) => asset.type === 'style')
|
|
380
|
+
.map((asset) => `<link href="${asset.src}" rel="stylesheet"${this.makeAttributes(asset.attrs)}>`)
|
|
381
|
+
.join('\n');
|
|
382
|
+
renderContext.scripts = context.assets
|
|
383
|
+
.filter((asset) => asset.type === 'script')
|
|
384
|
+
.map((asset) => `<script src="${asset.src}"${this.makeAttributes(asset.attrs)}></script>`)
|
|
385
|
+
.join('\n');
|
|
386
|
+
return renderContext;
|
|
387
|
+
}
|
|
388
|
+
makeAttributes(attrs = {}) {
|
|
389
|
+
return Object.keys(attrs).reduce((result, key) => `${result} ${key}="${attrs[key]}"`, '');
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
const nodeOperators = ['==', '!=', '===', '!==', '<', '<=', '>', '>='];
|
|
394
|
+
class Node {
|
|
395
|
+
constructor(type) {
|
|
396
|
+
this.childNodes = [];
|
|
397
|
+
this.type = type;
|
|
398
|
+
}
|
|
399
|
+
append(node) {
|
|
400
|
+
this.childNodes.push(node);
|
|
401
|
+
}
|
|
402
|
+
get children() {
|
|
403
|
+
return this.childNodes;
|
|
404
|
+
}
|
|
405
|
+
render(context, renderer) {
|
|
406
|
+
return this.renderChildNodes(context, renderer);
|
|
407
|
+
}
|
|
408
|
+
renderChildNodes(context, renderer) {
|
|
409
|
+
return this.childNodes.map(node => node.render(context, renderer)).join('');
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
class CommentNode extends Node {
|
|
414
|
+
constructor(content) {
|
|
415
|
+
super('comment');
|
|
416
|
+
this.content = content;
|
|
417
|
+
}
|
|
418
|
+
render() {
|
|
419
|
+
return `<!-- ${this.content} -->`;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function readNestedValue(name, target) {
|
|
424
|
+
const index = name.indexOf('.');
|
|
425
|
+
if (target === undefined || target === null) {
|
|
426
|
+
return undefined;
|
|
427
|
+
}
|
|
428
|
+
if (name === '') {
|
|
429
|
+
return target;
|
|
430
|
+
}
|
|
431
|
+
if (index <= 0) {
|
|
432
|
+
return target[name];
|
|
433
|
+
}
|
|
434
|
+
const currentName = name.substring(0, index);
|
|
435
|
+
const nextName = name.substring(index + 1);
|
|
436
|
+
if (!target[currentName]) {
|
|
437
|
+
return undefined;
|
|
438
|
+
}
|
|
439
|
+
return readNestedValue(nextName, target[currentName]);
|
|
440
|
+
}
|
|
441
|
+
function escapeHtml(unsafe) {
|
|
442
|
+
return unsafe
|
|
443
|
+
.replaceAll('&', '&')
|
|
444
|
+
.replaceAll('<', '<')
|
|
445
|
+
.replaceAll('>', '>')
|
|
446
|
+
.replaceAll('"', '"')
|
|
447
|
+
.replaceAll("'", ''');
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
class TagNode extends Node {
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
class TagDebugNode extends TagNode {
|
|
454
|
+
constructor({ contextKey }) {
|
|
455
|
+
super('tag-debug');
|
|
456
|
+
this.contextKey = contextKey !== null && contextKey !== void 0 ? contextKey : 'this';
|
|
457
|
+
}
|
|
458
|
+
render(context) {
|
|
459
|
+
const debugContext = this.contextKey !== 'this' ? readNestedValue(this.contextKey, context) : context;
|
|
460
|
+
const debugContent = debugContext
|
|
461
|
+
? JSON.stringify(debugContext, null, 2)
|
|
462
|
+
: `Current context for "${this.contextKey}" is empty`;
|
|
463
|
+
return `<pre>${debugContent}</pre>`;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
const parseTagDebugNode = {
|
|
467
|
+
example: '{{ debug[:contextKey] }}',
|
|
468
|
+
hasContent: false,
|
|
469
|
+
identifier: 'debug',
|
|
470
|
+
parse() {
|
|
471
|
+
const options = {};
|
|
472
|
+
let gotSeparator = false;
|
|
473
|
+
return {
|
|
474
|
+
addToken(token) {
|
|
475
|
+
if (!gotSeparator) {
|
|
476
|
+
if (token.type !== 'tag-separator') {
|
|
477
|
+
throw new TagNodeError('Expected separator');
|
|
478
|
+
}
|
|
479
|
+
gotSeparator = true;
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
if (token.type === 'identifier') {
|
|
483
|
+
options.contextKey = token.name;
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
throw new TagNodeError('Expected tag identifier');
|
|
487
|
+
},
|
|
488
|
+
create() {
|
|
489
|
+
return new TagDebugNode(options);
|
|
490
|
+
},
|
|
491
|
+
};
|
|
492
|
+
},
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
class TagForNode extends TagNode {
|
|
496
|
+
constructor({ contextKey }) {
|
|
497
|
+
super('tag-for');
|
|
498
|
+
this.contextKey = contextKey !== null && contextKey !== void 0 ? contextKey : 'this';
|
|
499
|
+
}
|
|
500
|
+
render(context, renderer) {
|
|
501
|
+
const contextNew = this.contextKey === 'this' ? context : readNestedValue(this.contextKey, context);
|
|
502
|
+
if (Array.isArray(contextNew)) {
|
|
503
|
+
return this.renderArray(contextNew, context, renderer);
|
|
504
|
+
}
|
|
505
|
+
if (typeof contextNew === 'object') {
|
|
506
|
+
return this.renderObject(contextNew, context, renderer);
|
|
507
|
+
}
|
|
508
|
+
return '';
|
|
509
|
+
}
|
|
510
|
+
renderArray(context, parentContext, renderer) {
|
|
511
|
+
return context
|
|
512
|
+
.map((item, index) => {
|
|
513
|
+
return this.renderChildNodes({
|
|
514
|
+
...(typeof item === 'object' ? item : {}),
|
|
515
|
+
_contextKey: this.contextKey,
|
|
516
|
+
_loop: { index, value: item },
|
|
517
|
+
_parent: parentContext,
|
|
518
|
+
}, renderer);
|
|
519
|
+
})
|
|
520
|
+
.join('');
|
|
521
|
+
}
|
|
522
|
+
renderObject(context, parentContext, renderer) {
|
|
523
|
+
return Object.keys(context)
|
|
524
|
+
.map((key, index) => {
|
|
525
|
+
return this.renderChildNodes({
|
|
526
|
+
...(typeof context[key] === 'object' ? context[key] : {}),
|
|
527
|
+
_contextKey: this.contextKey,
|
|
528
|
+
_loop: { index, key, value: context[key] },
|
|
529
|
+
_parent: parentContext,
|
|
530
|
+
}, renderer);
|
|
531
|
+
})
|
|
532
|
+
.join('');
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
const parseTagForNode = {
|
|
536
|
+
example: '{{ for[:contextKey] }}###{{ /for }}',
|
|
537
|
+
hasContent: true,
|
|
538
|
+
identifier: 'for',
|
|
539
|
+
parse() {
|
|
540
|
+
const options = {};
|
|
541
|
+
let gotSeparator = false;
|
|
542
|
+
return {
|
|
543
|
+
addToken(token) {
|
|
544
|
+
if (!gotSeparator) {
|
|
545
|
+
if (token.type !== 'tag-separator') {
|
|
546
|
+
throw new TagNodeError('Expected separator');
|
|
547
|
+
}
|
|
548
|
+
gotSeparator = true;
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
if (token.type === 'identifier') {
|
|
552
|
+
options.contextKey = token.name;
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
throw new TagNodeError('Expected tag identifier"');
|
|
556
|
+
},
|
|
557
|
+
create() {
|
|
558
|
+
return new TagForNode(options);
|
|
559
|
+
},
|
|
560
|
+
};
|
|
561
|
+
},
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
class TagIfNode extends TagNode {
|
|
565
|
+
constructor(options) {
|
|
566
|
+
super('tag-if');
|
|
567
|
+
this.options = options;
|
|
568
|
+
}
|
|
569
|
+
render(context, renderer) {
|
|
570
|
+
let value = this.getValue(context, 'firstValue', 'firstContextKey');
|
|
571
|
+
if (this.options.operator) {
|
|
572
|
+
value = this.compare(value, this.getValue(context, 'secondValue', 'secondContextKey'), this.options.operator);
|
|
573
|
+
}
|
|
574
|
+
return value ? this.renderChildNodes(context, renderer) : '';
|
|
575
|
+
}
|
|
576
|
+
getValue(context, valueKey, contextKey) {
|
|
577
|
+
return this.options[contextKey] !== undefined
|
|
578
|
+
? readNestedValue(this.options[contextKey], context)
|
|
579
|
+
: this.options[valueKey];
|
|
580
|
+
}
|
|
581
|
+
compare(value, compareValue, operator) {
|
|
582
|
+
switch (operator) {
|
|
583
|
+
case '==':
|
|
584
|
+
// eslint-disable-next-line eqeqeq
|
|
585
|
+
return value == compareValue;
|
|
586
|
+
case '!=':
|
|
587
|
+
// eslint-disable-next-line eqeqeq
|
|
588
|
+
return value != compareValue;
|
|
589
|
+
case '===':
|
|
590
|
+
return value === compareValue;
|
|
591
|
+
case '!==':
|
|
592
|
+
return value !== compareValue;
|
|
593
|
+
case '<':
|
|
594
|
+
return value < compareValue;
|
|
595
|
+
case '<=':
|
|
596
|
+
return value <= compareValue;
|
|
597
|
+
case '>':
|
|
598
|
+
return value > compareValue;
|
|
599
|
+
case '>=':
|
|
600
|
+
return value >= compareValue;
|
|
601
|
+
default:
|
|
602
|
+
return false;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
const parseTagIfNode = {
|
|
607
|
+
example: '{{ if:(contextKey|contextKey === (true|"a string"|12.34)|contextKey === otherContextKey) }}###{{ /if }}',
|
|
608
|
+
hasContent: true,
|
|
609
|
+
identifier: 'if',
|
|
610
|
+
parse() {
|
|
611
|
+
const options = {};
|
|
612
|
+
const addOptionKeyOrValue = (token, keyName, valueName) => {
|
|
613
|
+
if (token.type === 'identifier') {
|
|
614
|
+
options[keyName] = token.name;
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
if (token.type === 'string' || token.type === 'number' || token.type === 'boolean') {
|
|
618
|
+
options[valueName] = token.value;
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
throw new TagNodeError('Expected identifier or value');
|
|
622
|
+
};
|
|
623
|
+
let gotSeparator = false;
|
|
624
|
+
return {
|
|
625
|
+
addToken(token) {
|
|
626
|
+
if (!gotSeparator) {
|
|
627
|
+
if (token.type !== 'tag-separator') {
|
|
628
|
+
throw new TagNodeError('Expected separator');
|
|
629
|
+
}
|
|
630
|
+
gotSeparator = true;
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
if (options.firstContextKey === undefined && options.firstValue === undefined) {
|
|
634
|
+
addOptionKeyOrValue(token, 'firstContextKey', 'firstValue');
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
if (options.operator === undefined) {
|
|
638
|
+
if (token.type !== 'operator') {
|
|
639
|
+
throw new TagNodeError('Expected operator');
|
|
640
|
+
}
|
|
641
|
+
if (!nodeOperators.includes(token.operator)) {
|
|
642
|
+
throw new TagNodeError(`Invalid operator ${token.operator}`);
|
|
643
|
+
}
|
|
644
|
+
options.operator = token.operator;
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
if (options.secondContextKey === undefined && options.secondValue === undefined) {
|
|
648
|
+
addOptionKeyOrValue(token, 'secondContextKey', 'secondValue');
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
throw new TagNodeError('Unexpected token');
|
|
652
|
+
},
|
|
653
|
+
create() {
|
|
654
|
+
if (options.firstContextKey === undefined && options.firstValue === undefined) {
|
|
655
|
+
throw new TagNodeError('Expected first context key or value');
|
|
656
|
+
}
|
|
657
|
+
if (options.operator === undefined && options.firstContextKey === undefined) {
|
|
658
|
+
throw new TagNodeError('Expected context key when no operator is given');
|
|
659
|
+
}
|
|
660
|
+
if (options.operator !== undefined &&
|
|
661
|
+
options.secondContextKey === undefined &&
|
|
662
|
+
options.secondValue === undefined) {
|
|
663
|
+
throw new TagNodeError('Expected second context key or value when operator is given');
|
|
664
|
+
}
|
|
665
|
+
return new TagIfNode(options);
|
|
666
|
+
},
|
|
667
|
+
};
|
|
668
|
+
},
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
class TagPageNode extends TagNode {
|
|
672
|
+
constructor({ name, contextKey }) {
|
|
673
|
+
super('tag-page');
|
|
674
|
+
this.name = name !== null && name !== void 0 ? name : 'default';
|
|
675
|
+
this.contextKey = contextKey !== null && contextKey !== void 0 ? contextKey : 'this';
|
|
676
|
+
}
|
|
677
|
+
render(context, renderer) {
|
|
678
|
+
let pageName = this.name;
|
|
679
|
+
const newContext = this.contextKey === 'this' ? context : readNestedValue(this.contextKey, context);
|
|
680
|
+
if (pageName.includes('.')) {
|
|
681
|
+
const foundName = readNestedValue(pageName, context);
|
|
682
|
+
if (typeof foundName === 'string' && foundName) {
|
|
683
|
+
pageName = foundName;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
return renderer.page(pageName, newContext);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
const parseTagPageNode = {
|
|
690
|
+
example: '{{ page[:page-name [contextKey]] }}',
|
|
691
|
+
hasContent: false,
|
|
692
|
+
identifier: 'page',
|
|
693
|
+
parse() {
|
|
694
|
+
const options = {};
|
|
695
|
+
let gotSeparator = false;
|
|
696
|
+
return {
|
|
697
|
+
addToken(token) {
|
|
698
|
+
if (!gotSeparator) {
|
|
699
|
+
if (token.type !== 'tag-separator') {
|
|
700
|
+
throw new TagNodeError('Expected separator');
|
|
701
|
+
}
|
|
702
|
+
gotSeparator = true;
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
if (token.type !== 'identifier') {
|
|
706
|
+
throw new TagNodeError('Expected tag identifier');
|
|
707
|
+
}
|
|
708
|
+
if (options.name && options.contextKey) {
|
|
709
|
+
throw new TagNodeError('Expected only one name and context key');
|
|
710
|
+
}
|
|
711
|
+
if (options.name) {
|
|
712
|
+
options.contextKey = token.name;
|
|
713
|
+
}
|
|
714
|
+
else {
|
|
715
|
+
options.name = token.name;
|
|
716
|
+
}
|
|
717
|
+
},
|
|
718
|
+
create() {
|
|
719
|
+
return new TagPageNode(options);
|
|
720
|
+
},
|
|
721
|
+
};
|
|
722
|
+
},
|
|
723
|
+
};
|
|
724
|
+
|
|
725
|
+
class TagPartialNode extends TagNode {
|
|
726
|
+
constructor({ name, contextKey }) {
|
|
727
|
+
super('tag-partial');
|
|
728
|
+
this.name = name;
|
|
729
|
+
this.contextKey = contextKey !== null && contextKey !== void 0 ? contextKey : 'this';
|
|
730
|
+
}
|
|
731
|
+
render(context, renderer) {
|
|
732
|
+
const newContext = this.contextKey === 'this' ? context : readNestedValue(this.contextKey, context);
|
|
733
|
+
return renderer.partial(this.name, newContext);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
const parseTagPartialNode = {
|
|
737
|
+
example: '{{ partial:partial-name [contextKey] }}',
|
|
738
|
+
hasContent: false,
|
|
739
|
+
identifier: 'partial',
|
|
740
|
+
parse() {
|
|
741
|
+
const options = {};
|
|
742
|
+
let gotSeparator = false;
|
|
743
|
+
return {
|
|
744
|
+
addToken(token) {
|
|
745
|
+
if (!gotSeparator) {
|
|
746
|
+
if (token.type !== 'tag-separator') {
|
|
747
|
+
throw new TagNodeError('Expected separator');
|
|
748
|
+
}
|
|
749
|
+
gotSeparator = true;
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
if (token.type !== 'identifier') {
|
|
753
|
+
throw new TagNodeError('Expected tag identifier');
|
|
754
|
+
}
|
|
755
|
+
if (options.name && options.contextKey) {
|
|
756
|
+
throw new TagNodeError('Expected only one name and context key');
|
|
757
|
+
}
|
|
758
|
+
if (options.name) {
|
|
759
|
+
options.contextKey = token.name;
|
|
760
|
+
}
|
|
761
|
+
else {
|
|
762
|
+
options.name = token.name;
|
|
763
|
+
}
|
|
764
|
+
},
|
|
765
|
+
create() {
|
|
766
|
+
if (!options.name) {
|
|
767
|
+
throw new TagNodeError('Expected partial name');
|
|
768
|
+
}
|
|
769
|
+
return new TagPartialNode(options);
|
|
770
|
+
},
|
|
771
|
+
};
|
|
772
|
+
},
|
|
773
|
+
};
|
|
774
|
+
|
|
775
|
+
class TagVarNode extends TagNode {
|
|
776
|
+
constructor({ contextKey, escape }) {
|
|
777
|
+
super('tag-var');
|
|
778
|
+
this.contextKey = contextKey;
|
|
779
|
+
this.escape = !!escape;
|
|
780
|
+
}
|
|
781
|
+
render(context) {
|
|
782
|
+
let value = readNestedValue(this.contextKey, context) || '';
|
|
783
|
+
if (typeof value !== 'string') {
|
|
784
|
+
value = String(value);
|
|
785
|
+
}
|
|
786
|
+
return this.escape ? escapeHtml(value) : value;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
const parseTagVarNode = {
|
|
790
|
+
example: '{{ var:contextKey [escape] }}',
|
|
791
|
+
hasContent: false,
|
|
792
|
+
identifier: 'var',
|
|
793
|
+
parse() {
|
|
794
|
+
const options = {};
|
|
795
|
+
let gotSeparator = false;
|
|
796
|
+
return {
|
|
797
|
+
addToken(token) {
|
|
798
|
+
if (!gotSeparator) {
|
|
799
|
+
if (token.type !== 'tag-separator') {
|
|
800
|
+
throw new TagNodeError('Expected separator');
|
|
801
|
+
}
|
|
802
|
+
gotSeparator = true;
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
if (token.type !== 'identifier') {
|
|
806
|
+
throw new TagNodeError('Expected tag identifier');
|
|
807
|
+
}
|
|
808
|
+
if (options.contextKey !== undefined && options.escape !== undefined) {
|
|
809
|
+
throw new TagNodeError('Expected only context key followed by optional escape');
|
|
810
|
+
}
|
|
811
|
+
if (options.contextKey === undefined) {
|
|
812
|
+
options.contextKey = token.name;
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
if (token.name !== 'escape') {
|
|
816
|
+
throw new TagNodeError('Expected escape');
|
|
817
|
+
}
|
|
818
|
+
options.escape = true;
|
|
819
|
+
},
|
|
820
|
+
create() {
|
|
821
|
+
if (!options.contextKey) {
|
|
822
|
+
throw new TagNodeError('Expected context key');
|
|
823
|
+
}
|
|
824
|
+
return new TagVarNode(options);
|
|
825
|
+
},
|
|
826
|
+
};
|
|
827
|
+
},
|
|
828
|
+
};
|
|
829
|
+
|
|
830
|
+
const tagNodes = [
|
|
831
|
+
parseTagDebugNode,
|
|
832
|
+
parseTagForNode,
|
|
833
|
+
parseTagIfNode,
|
|
834
|
+
parseTagPageNode,
|
|
835
|
+
parseTagPartialNode,
|
|
836
|
+
parseTagVarNode,
|
|
837
|
+
];
|
|
838
|
+
|
|
839
|
+
class TemplateNode extends Node {
|
|
840
|
+
constructor(content) {
|
|
841
|
+
super('template');
|
|
842
|
+
this.content = content;
|
|
843
|
+
}
|
|
844
|
+
render() {
|
|
845
|
+
return this.content;
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
class NodeParser {
|
|
850
|
+
constructor() {
|
|
851
|
+
this.tags = {};
|
|
852
|
+
}
|
|
853
|
+
static init() {
|
|
854
|
+
const parser = new NodeParser();
|
|
855
|
+
tagNodes.forEach(tag => parser.registerTagParser(tag));
|
|
856
|
+
// TODO may make async
|
|
857
|
+
// (await import('./nodes/tags')).default.forEach(tag => parser.registerTag(tag))
|
|
858
|
+
return parser;
|
|
859
|
+
}
|
|
860
|
+
registerTagParser(tag) {
|
|
861
|
+
this.tags[tag.identifier] = tag;
|
|
862
|
+
return this;
|
|
863
|
+
}
|
|
864
|
+
parse(reader) {
|
|
865
|
+
const lexer = new HtmlCurlyBraceLexer(reader);
|
|
866
|
+
const tree = new Node('root');
|
|
867
|
+
return this.parseChildren(lexer, tree);
|
|
868
|
+
}
|
|
869
|
+
parseChildren(lexer, parent) {
|
|
870
|
+
var _a;
|
|
871
|
+
let token = lexer.consume();
|
|
872
|
+
while (token) {
|
|
873
|
+
switch (token.type) {
|
|
874
|
+
case 'template':
|
|
875
|
+
parent.append(new TemplateNode(token.content));
|
|
876
|
+
break;
|
|
877
|
+
case 'comment':
|
|
878
|
+
parent.append(new CommentNode(token.content));
|
|
879
|
+
break;
|
|
880
|
+
case 'tag-open':
|
|
881
|
+
if (((_a = lexer.peek()) === null || _a === void 0 ? void 0 : _a.type) === 'tag-end') {
|
|
882
|
+
return parent;
|
|
883
|
+
}
|
|
884
|
+
parent.append(this.parseTag(lexer));
|
|
885
|
+
break;
|
|
886
|
+
default:
|
|
887
|
+
throw new ParserError(`Unexpected token type "${token.type}"`);
|
|
888
|
+
}
|
|
889
|
+
token = lexer.consume();
|
|
890
|
+
}
|
|
891
|
+
return parent;
|
|
892
|
+
}
|
|
893
|
+
parseTag(lexer) {
|
|
894
|
+
var _a, _b, _c;
|
|
895
|
+
const tagIdentifier = lexer.consume();
|
|
896
|
+
if (!tagIdentifier || tagIdentifier.type !== 'tag-identifier') {
|
|
897
|
+
throw new ParserError('Expected tag identifier');
|
|
898
|
+
}
|
|
899
|
+
const tagDefinition = this.tags[tagIdentifier.name];
|
|
900
|
+
if (!tagDefinition) {
|
|
901
|
+
throw new ParserError(`Unknown tag "${tagIdentifier.name}"`);
|
|
902
|
+
}
|
|
903
|
+
const { addToken, create } = tagDefinition.parse();
|
|
904
|
+
let nextToken = lexer.consume();
|
|
905
|
+
let node;
|
|
906
|
+
try {
|
|
907
|
+
while (nextToken && nextToken.type !== 'tag-close') {
|
|
908
|
+
addToken(nextToken);
|
|
909
|
+
nextToken = lexer.consume();
|
|
910
|
+
}
|
|
911
|
+
node = create();
|
|
912
|
+
}
|
|
913
|
+
catch (error) {
|
|
914
|
+
if (error instanceof TagNodeError) {
|
|
915
|
+
throw new ParserError(`Error parsing tag ${tagIdentifier.name} - ${error.message}\nShould be something like: ${tagDefinition.example}`);
|
|
916
|
+
}
|
|
917
|
+
throw error;
|
|
918
|
+
}
|
|
919
|
+
if (!tagDefinition.hasContent) {
|
|
920
|
+
return node;
|
|
921
|
+
}
|
|
922
|
+
this.parseChildren(lexer, node);
|
|
923
|
+
const closeTokens = lexer.consume(3);
|
|
924
|
+
if (!closeTokens ||
|
|
925
|
+
((_a = closeTokens[0]) === null || _a === void 0 ? void 0 : _a.type) !== 'tag-end' ||
|
|
926
|
+
((_b = closeTokens[1]) === null || _b === void 0 ? void 0 : _b.type) !== 'tag-identifier' ||
|
|
927
|
+
closeTokens[1].name !== tagIdentifier.name ||
|
|
928
|
+
((_c = closeTokens[2]) === null || _c === void 0 ? void 0 : _c.type) !== 'tag-close') {
|
|
929
|
+
throw new ParserError('Expected closing tag');
|
|
930
|
+
}
|
|
931
|
+
return node;
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
class TemplateLoader {
|
|
936
|
+
static async load({ renderer, fileSystem, templateBasePath = '@ui-doc/html-renderer/templates', }) {
|
|
937
|
+
const templatePath = await fileSystem.assetLoader().packagePath(templateBasePath);
|
|
938
|
+
const layoutFinder = fileSystem.createFileFinder([`${templatePath}/layouts/*.html`]);
|
|
939
|
+
const pageFinder = fileSystem.createFileFinder([`${templatePath}/pages/*.html`]);
|
|
940
|
+
const partialFinder = fileSystem.createFileFinder([`${templatePath}/partials/*.html`]);
|
|
941
|
+
const name = (file) => fileSystem.fileBasename(file);
|
|
942
|
+
const content = async (file) => (await fileSystem.fileRead(file)).trim();
|
|
943
|
+
await Promise.all([
|
|
944
|
+
layoutFinder.search(async (file) => {
|
|
945
|
+
renderer.addLayout(name(file), { content: await content(file), source: file });
|
|
946
|
+
}),
|
|
947
|
+
pageFinder.search(async (file) => {
|
|
948
|
+
renderer.addPage(name(file), { content: await content(file), source: file });
|
|
949
|
+
}),
|
|
950
|
+
partialFinder.search(async (file) => {
|
|
951
|
+
renderer.addPartial(name(file), { content: await content(file), source: file });
|
|
952
|
+
}),
|
|
953
|
+
]);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
export { CommentNode, HTMLRendererError, HTMLRendererSyntaxError, HtmlCurlyBraceLexer, HtmlRenderer, InlineReader, Node, NodeParser, ParserError, TagDebugNode, TagForNode, TagIfNode, TagNode, TagNodeError, TagPageNode, TagPartialNode, TagVarNode, TemplateLoader, TemplateNode, escapeHtml, nodeOperators, readNestedValue };
|
|
958
|
+
//# sourceMappingURL=index.mjs.map
|