@ui-doc/html-renderer 0.3.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +586 -151
- package/dist/HtmlCurlyBraceLexer.d.ts +4 -1
- package/dist/HtmlRenderer.d.ts +5 -5
- package/dist/InlineReader.d.ts +3 -2
- package/dist/{types/lexer.d.ts → Lexer.types.d.ts} +8 -5
- package/dist/NodeParser.d.ts +3 -2
- package/dist/{types/parser.d.ts → Parser.types.d.ts} +8 -8
- package/dist/{types/base.d.ts → Primitive.types.d.ts} +1 -1
- package/dist/{types/reader.d.ts → Reader.types.d.ts} +9 -7
- package/dist/Renderer.types.d.ts +14 -0
- package/dist/TemplateLoader.d.ts +3 -2
- package/dist/{types/token.d.ts → Token.types.d.ts} +1 -1
- package/dist/assets/services/expand.d.ts +19 -0
- package/dist/assets/ui-doc.cjs +283 -9
- package/dist/assets/ui-doc.cjs.map +1 -1
- package/dist/assets/ui-doc.css +1169 -250
- package/dist/assets/ui-doc.css.map +1 -1
- package/dist/assets/ui-doc.min.css +9 -1
- package/dist/assets/ui-doc.min.js +1 -1
- package/dist/assets/ui-doc.mjs +283 -9
- package/dist/assets/ui-doc.mjs.map +1 -1
- package/dist/assets/utils/delay.d.ts +1 -0
- package/dist/assets/utils/dom.d.ts +31 -0
- package/dist/assets/utils/select.d.ts +12 -0
- package/dist/index.cjs +161 -126
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.mjs +160 -126
- package/dist/index.mjs.map +1 -1
- package/dist/nodes/CommentNode.d.ts +2 -1
- package/dist/nodes/Node.d.ts +1 -1
- package/dist/nodes/TemplateNode.d.ts +2 -1
- package/dist/nodes/index.d.ts +4 -2
- package/dist/nodes/tags/debug.d.ts +2 -1
- package/dist/nodes/tags/for.d.ts +4 -3
- package/dist/nodes/tags/if.d.ts +5 -4
- package/dist/nodes/tags/index.d.ts +1 -1
- package/dist/nodes/tags/page.d.ts +2 -1
- package/dist/nodes/tags/partial.d.ts +2 -1
- package/dist/nodes/tags/var.d.ts +2 -1
- package/dist/utils/index.d.ts +1 -1
- package/package.json +32 -29
- package/scripts/app.ts +5 -3
- package/scripts/{src → services}/example.ts +3 -3
- package/scripts/services/expand.ts +214 -0
- package/scripts/{src → services}/sidebar.ts +4 -3
- package/scripts/utils/delay.ts +12 -0
- package/scripts/utils/dom.ts +77 -0
- package/scripts/utils/select.ts +46 -0
- package/styles/01_resets/initial.css +8 -3
- package/styles/01_resets/root/color.css +19 -0
- package/styles/01_resets/root/font.css +28 -0
- package/styles/01_resets/root/space.css +30 -0
- package/styles/01_resets/root/witdh.css +12 -0
- package/styles/01_resets/root.css +61 -23
- package/styles/01_resets/typography.css +105 -8
- package/styles/02_utils/background.css +14 -0
- package/styles/02_utils/control.css +41 -0
- package/styles/02_utils/margin.css +150 -0
- package/styles/02_utils/padding.css +134 -0
- package/styles/02_utils/width.css +39 -0
- package/styles/03_components/button.css +42 -0
- package/styles/03_components/colors.css +7 -19
- package/styles/03_components/container.css +16 -0
- package/styles/03_components/example-markup.css +1 -6
- package/styles/03_components/grid-auto.css +49 -0
- package/styles/03_components/icons.css +7 -19
- package/styles/03_components/navigation/burger-control.css +75 -0
- package/styles/03_components/{nav → navigation}/list.css +9 -11
- package/styles/03_components/navigation/main.css +102 -0
- package/styles/03_components/spaces.css +8 -7
- package/styles/04_layout/body.css +22 -0
- package/styles/04_layout/inline-code.css +6 -0
- package/styles/04_layout/page.css +73 -0
- package/styles/index.css +58 -17
- package/templates/layouts/default.html +4 -6
- package/templates/layouts/example.html +1 -1
- package/templates/pages/default.html +13 -13
- package/templates/pages/index.html +9 -3
- package/templates/partials/code.html +1 -1
- package/templates/partials/colors.html +2 -2
- package/templates/partials/content.html +1 -1
- package/templates/partials/icons.html +3 -3
- package/templates/partials/nav-main.html +19 -8
- package/templates/partials/section.html +1 -1
- package/templates/partials/spaces.html +2 -2
- package/LICENSE.md +0 -9
- package/dist/assets/src/utils.d.ts +0 -2
- package/dist/types/index.d.ts +0 -6
- package/dist/types/renderer.d.ts +0 -14
- package/scripts/src/utils.ts +0 -20
- package/styles/02_objects/background.css +0 -7
- package/styles/02_objects/control.css +0 -25
- package/styles/02_objects/margin.css +0 -44
- package/styles/02_objects/padding.css +0 -44
- package/styles/02_objects/text.css +0 -3
- package/styles/02_objects/width.css +0 -16
- package/styles/03_components/nav/main.css +0 -39
- package/styles/03_components/text-flow.css +0 -5
- package/styles/04_layouts/page.css +0 -70
- /package/dist/assets/{src → services}/example.d.ts +0 -0
- /package/dist/assets/{src → services}/sidebar.d.ts +0 -0
package/dist/index.cjs
CHANGED
|
@@ -8,6 +8,10 @@ class HTMLRendererError extends Error {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
class HTMLRendererSyntaxError extends SyntaxError {
|
|
11
|
+
code;
|
|
12
|
+
line;
|
|
13
|
+
column;
|
|
14
|
+
source;
|
|
11
15
|
constructor({ message, code, column, line, source, }) {
|
|
12
16
|
super(message);
|
|
13
17
|
this.name = 'HTMLRendererSyntaxError';
|
|
@@ -29,19 +33,20 @@ class ParserError extends Error {
|
|
|
29
33
|
class TagNodeError extends Error {
|
|
30
34
|
constructor(message) {
|
|
31
35
|
super(message);
|
|
32
|
-
this.name = '
|
|
36
|
+
this.name = 'TagNodeError';
|
|
33
37
|
}
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
const IDENTIFIER_CHARS = {
|
|
37
|
-
identifier: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.',
|
|
41
|
+
'identifier': 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.',
|
|
38
42
|
'tag-identifier': 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
|
39
43
|
};
|
|
40
44
|
class HtmlCurlyBraceLexer {
|
|
45
|
+
reader;
|
|
46
|
+
currentTokens = [];
|
|
47
|
+
tagConsuming = false;
|
|
48
|
+
tagIdentified = false;
|
|
41
49
|
constructor(reader) {
|
|
42
|
-
this.currentTokens = [];
|
|
43
|
-
this.tagConsuming = false;
|
|
44
|
-
this.tagIdentified = false;
|
|
45
50
|
this.reader = reader;
|
|
46
51
|
}
|
|
47
52
|
debug() {
|
|
@@ -71,11 +76,11 @@ class HtmlCurlyBraceLexer {
|
|
|
71
76
|
if (this.tagConsuming) {
|
|
72
77
|
return this.progressTag();
|
|
73
78
|
}
|
|
74
|
-
const char = this.reader.
|
|
75
|
-
if (char === '{' && this.reader.
|
|
79
|
+
const char = this.reader.peek();
|
|
80
|
+
if (char === '{' && this.reader.peek(2) === '{{') {
|
|
76
81
|
return this.consumeTagOpen();
|
|
77
82
|
}
|
|
78
|
-
if (char === '<' && this.reader.
|
|
83
|
+
if (char === '<' && this.reader.peek(4) === '<!--') {
|
|
79
84
|
return this.consumeComment();
|
|
80
85
|
}
|
|
81
86
|
return this.consumeTemplate();
|
|
@@ -106,7 +111,7 @@ class HtmlCurlyBraceLexer {
|
|
|
106
111
|
this.reader.consume(4);
|
|
107
112
|
let content = '';
|
|
108
113
|
while (!this.reader.isEof()) {
|
|
109
|
-
if (this.reader.
|
|
114
|
+
if (this.reader.peek(3) === '-->') {
|
|
110
115
|
this.reader.consume(3);
|
|
111
116
|
break;
|
|
112
117
|
}
|
|
@@ -120,11 +125,11 @@ class HtmlCurlyBraceLexer {
|
|
|
120
125
|
consumeTemplate() {
|
|
121
126
|
let content = '';
|
|
122
127
|
while (!this.reader.isEof()) {
|
|
123
|
-
const peek = this.reader.
|
|
124
|
-
if (peek === '{' && this.reader.
|
|
128
|
+
const peek = this.reader.peek();
|
|
129
|
+
if (peek === '{' && this.reader.peek(2) === '{{') {
|
|
125
130
|
break;
|
|
126
131
|
}
|
|
127
|
-
if (peek === '<' && this.reader.
|
|
132
|
+
if (peek === '<' && this.reader.peek(4) === '<!--') {
|
|
128
133
|
break;
|
|
129
134
|
}
|
|
130
135
|
content += this.reader.consume();
|
|
@@ -135,12 +140,12 @@ class HtmlCurlyBraceLexer {
|
|
|
135
140
|
};
|
|
136
141
|
}
|
|
137
142
|
progressTag() {
|
|
138
|
-
const char = this.reader.
|
|
143
|
+
const char = this.reader.peek();
|
|
139
144
|
if (char === ' ' || char === '\n' || char === '\r' || char === '\t') {
|
|
140
145
|
this.reader.consume();
|
|
141
146
|
return this.progressTag();
|
|
142
147
|
}
|
|
143
|
-
if (char === '}' && this.reader.
|
|
148
|
+
if (char === '}' && this.reader.peek(2) === '}}') {
|
|
144
149
|
return this.consumeTagClose();
|
|
145
150
|
}
|
|
146
151
|
if (char === '/') {
|
|
@@ -153,25 +158,25 @@ class HtmlCurlyBraceLexer {
|
|
|
153
158
|
if (char === ':') {
|
|
154
159
|
return this.consumeTagSeparator();
|
|
155
160
|
}
|
|
156
|
-
if (char === '"' || char ===
|
|
161
|
+
if (char === '"' || char === '\'') {
|
|
157
162
|
return this.consumeString();
|
|
158
163
|
}
|
|
159
|
-
if (char === '1'
|
|
160
|
-
char === '2'
|
|
161
|
-
char === '3'
|
|
162
|
-
char === '4'
|
|
163
|
-
char === '5'
|
|
164
|
-
char === '6'
|
|
165
|
-
char === '7'
|
|
166
|
-
char === '8'
|
|
167
|
-
char === '9'
|
|
168
|
-
char === '0') {
|
|
164
|
+
if (char === '1'
|
|
165
|
+
|| char === '2'
|
|
166
|
+
|| char === '3'
|
|
167
|
+
|| char === '4'
|
|
168
|
+
|| char === '5'
|
|
169
|
+
|| char === '6'
|
|
170
|
+
|| char === '7'
|
|
171
|
+
|| char === '8'
|
|
172
|
+
|| char === '9'
|
|
173
|
+
|| char === '0') {
|
|
169
174
|
return this.consumeNumber();
|
|
170
175
|
}
|
|
171
|
-
if (char === 't' && this.reader.
|
|
176
|
+
if (char === 't' && this.reader.peek(4) === 'true') {
|
|
172
177
|
return this.consumeBoolean(true);
|
|
173
178
|
}
|
|
174
|
-
if (char === 'f' && this.reader.
|
|
179
|
+
if (char === 'f' && this.reader.peek(5) === 'false') {
|
|
175
180
|
return this.consumeBoolean(false);
|
|
176
181
|
}
|
|
177
182
|
if (char === '=' || char === '!' || char === '<' || char === '>') {
|
|
@@ -203,18 +208,18 @@ class HtmlCurlyBraceLexer {
|
|
|
203
208
|
consumeNumber() {
|
|
204
209
|
let value = '';
|
|
205
210
|
while (!this.reader.isEof()) {
|
|
206
|
-
const char = this.reader.
|
|
207
|
-
if (char === '1'
|
|
208
|
-
char === '2'
|
|
209
|
-
char === '3'
|
|
210
|
-
char === '4'
|
|
211
|
-
char === '5'
|
|
212
|
-
char === '6'
|
|
213
|
-
char === '7'
|
|
214
|
-
char === '8'
|
|
215
|
-
char === '9'
|
|
216
|
-
char === '0'
|
|
217
|
-
char === '.') {
|
|
211
|
+
const char = this.reader.peek();
|
|
212
|
+
if (char === '1'
|
|
213
|
+
|| char === '2'
|
|
214
|
+
|| char === '3'
|
|
215
|
+
|| char === '4'
|
|
216
|
+
|| char === '5'
|
|
217
|
+
|| char === '6'
|
|
218
|
+
|| char === '7'
|
|
219
|
+
|| char === '8'
|
|
220
|
+
|| char === '9'
|
|
221
|
+
|| char === '0'
|
|
222
|
+
|| char === '.') {
|
|
218
223
|
value += this.reader.consume();
|
|
219
224
|
}
|
|
220
225
|
else {
|
|
@@ -223,7 +228,7 @@ class HtmlCurlyBraceLexer {
|
|
|
223
228
|
}
|
|
224
229
|
return {
|
|
225
230
|
type: 'number',
|
|
226
|
-
value: parseFloat(value),
|
|
231
|
+
value: Number.parseFloat(value),
|
|
227
232
|
};
|
|
228
233
|
}
|
|
229
234
|
consumeBoolean(value) {
|
|
@@ -236,7 +241,7 @@ class HtmlCurlyBraceLexer {
|
|
|
236
241
|
consumeOperator() {
|
|
237
242
|
let operator = '';
|
|
238
243
|
while (!this.reader.isEof()) {
|
|
239
|
-
const char = this.reader.
|
|
244
|
+
const char = this.reader.peek();
|
|
240
245
|
if (char === '=' || char === '!' || char === '<' || char === '>') {
|
|
241
246
|
operator += this.reader.consume();
|
|
242
247
|
}
|
|
@@ -253,7 +258,7 @@ class HtmlCurlyBraceLexer {
|
|
|
253
258
|
const chars = IDENTIFIER_CHARS[type];
|
|
254
259
|
let name = '';
|
|
255
260
|
while (!this.reader.isEof()) {
|
|
256
|
-
const char = this.reader.
|
|
261
|
+
const char = this.reader.peek();
|
|
257
262
|
if (!chars.includes(char)) {
|
|
258
263
|
break;
|
|
259
264
|
}
|
|
@@ -267,14 +272,16 @@ class HtmlCurlyBraceLexer {
|
|
|
267
272
|
}
|
|
268
273
|
|
|
269
274
|
class InlineReader {
|
|
275
|
+
input;
|
|
276
|
+
source;
|
|
277
|
+
currentLine = 1;
|
|
278
|
+
currentPos = 1;
|
|
279
|
+
currentContent = '';
|
|
270
280
|
constructor(input, source = 'inline') {
|
|
271
|
-
this.currentLine = 1;
|
|
272
|
-
this.currentPos = 1;
|
|
273
|
-
this.currentContent = '';
|
|
274
281
|
this.input = input;
|
|
275
282
|
this.source = source;
|
|
276
283
|
}
|
|
277
|
-
|
|
284
|
+
peek(k = 1) {
|
|
278
285
|
return this.input.slice(0, k);
|
|
279
286
|
}
|
|
280
287
|
consume(k = 1) {
|
|
@@ -307,16 +314,19 @@ class InlineReader {
|
|
|
307
314
|
}
|
|
308
315
|
|
|
309
316
|
function instanceofReader(object) {
|
|
310
|
-
return (
|
|
311
|
-
typeof object
|
|
312
|
-
typeof object.
|
|
313
|
-
typeof object.
|
|
317
|
+
return (object !== null
|
|
318
|
+
&& typeof object === 'object'
|
|
319
|
+
&& typeof object.peek === 'function'
|
|
320
|
+
&& typeof object.consume === 'function'
|
|
321
|
+
&& typeof object.isEof === 'function'
|
|
322
|
+
&& typeof object.debug === 'function');
|
|
314
323
|
}
|
|
315
324
|
class HtmlRenderer {
|
|
325
|
+
parser;
|
|
326
|
+
layouts = {};
|
|
327
|
+
partials = {};
|
|
328
|
+
pages = {};
|
|
316
329
|
constructor(parser) {
|
|
317
|
-
this.layouts = {};
|
|
318
|
-
this.partials = {};
|
|
319
|
-
this.pages = {};
|
|
320
330
|
this.parser = parser;
|
|
321
331
|
}
|
|
322
332
|
addLayout(name, layout) {
|
|
@@ -351,26 +361,26 @@ class HtmlRenderer {
|
|
|
351
361
|
}
|
|
352
362
|
}
|
|
353
363
|
generate(context, layout) {
|
|
354
|
-
layout = layout
|
|
355
|
-
const content = this.layouts[layout]
|
|
356
|
-
if (
|
|
364
|
+
layout = layout ?? 'default';
|
|
365
|
+
const content = this.layouts[layout];
|
|
366
|
+
if (content === undefined) {
|
|
357
367
|
throw new HTMLRendererError(`Layout "${layout}" not found. Please register it using "addLayout" method.`);
|
|
358
368
|
}
|
|
359
369
|
return this.render(content, this.generateContext(context));
|
|
360
370
|
}
|
|
361
371
|
page(name, context) {
|
|
362
|
-
const content = this.pages[name]
|
|
363
|
-
if (
|
|
372
|
+
const content = this.pages[name] ?? this.pages.default;
|
|
373
|
+
if (content === undefined) {
|
|
364
374
|
throw new HTMLRendererError(`Page "${name}" not found. Please register it using "addPage" method.`);
|
|
365
375
|
}
|
|
366
376
|
return this.render(content, context);
|
|
367
377
|
}
|
|
368
378
|
partial(name, context) {
|
|
369
|
-
const content = this.partials[name]
|
|
370
|
-
if (
|
|
379
|
+
const content = this.partials[name] ?? this.partials.default;
|
|
380
|
+
if (content === undefined) {
|
|
371
381
|
throw new HTMLRendererError(`Partial "${name}" not found. Please register it using "addPartial" method.`);
|
|
372
382
|
}
|
|
373
|
-
return this.render(content, context
|
|
383
|
+
return this.render(content, context ?? {});
|
|
374
384
|
}
|
|
375
385
|
render(rootNode, context) {
|
|
376
386
|
return rootNode.render(context, this);
|
|
@@ -394,8 +404,9 @@ class HtmlRenderer {
|
|
|
394
404
|
|
|
395
405
|
const nodeOperators = ['==', '!=', '===', '!==', '<', '<=', '>', '>='];
|
|
396
406
|
class Node {
|
|
407
|
+
type;
|
|
408
|
+
childNodes = [];
|
|
397
409
|
constructor(type) {
|
|
398
|
-
this.childNodes = [];
|
|
399
410
|
this.type = type;
|
|
400
411
|
}
|
|
401
412
|
append(node) {
|
|
@@ -413,11 +424,12 @@ class Node {
|
|
|
413
424
|
}
|
|
414
425
|
|
|
415
426
|
class CommentNode extends Node {
|
|
427
|
+
content;
|
|
416
428
|
constructor(content) {
|
|
417
429
|
super('comment');
|
|
418
430
|
this.content = content;
|
|
419
431
|
}
|
|
420
|
-
render() {
|
|
432
|
+
render(_context, _renderer) {
|
|
421
433
|
return `<!-- ${this.content} -->`;
|
|
422
434
|
}
|
|
423
435
|
}
|
|
@@ -430,15 +442,16 @@ function readNestedValue(name, target) {
|
|
|
430
442
|
if (name === '') {
|
|
431
443
|
return target;
|
|
432
444
|
}
|
|
445
|
+
const obj = target;
|
|
433
446
|
if (index <= 0) {
|
|
434
|
-
return
|
|
447
|
+
return obj[name];
|
|
435
448
|
}
|
|
436
449
|
const currentName = name.substring(0, index);
|
|
437
450
|
const nextName = name.substring(index + 1);
|
|
438
|
-
if (
|
|
451
|
+
if (obj[currentName] === undefined || obj[currentName] === null) {
|
|
439
452
|
return undefined;
|
|
440
453
|
}
|
|
441
|
-
return readNestedValue(nextName,
|
|
454
|
+
return readNestedValue(nextName, obj[currentName]);
|
|
442
455
|
}
|
|
443
456
|
function escapeHtml(unsafe) {
|
|
444
457
|
return unsafe
|
|
@@ -446,20 +459,21 @@ function escapeHtml(unsafe) {
|
|
|
446
459
|
.replaceAll('<', '<')
|
|
447
460
|
.replaceAll('>', '>')
|
|
448
461
|
.replaceAll('"', '"')
|
|
449
|
-
.replaceAll(
|
|
462
|
+
.replaceAll('\'', ''');
|
|
450
463
|
}
|
|
451
464
|
|
|
452
465
|
class TagNode extends Node {
|
|
453
466
|
}
|
|
454
467
|
|
|
455
468
|
class TagDebugNode extends TagNode {
|
|
469
|
+
contextKey;
|
|
456
470
|
constructor({ contextKey }) {
|
|
457
471
|
super('tag-debug');
|
|
458
|
-
this.contextKey = contextKey
|
|
472
|
+
this.contextKey = contextKey ?? 'this';
|
|
459
473
|
}
|
|
460
474
|
render(context) {
|
|
461
475
|
const debugContext = this.contextKey !== 'this' ? readNestedValue(this.contextKey, context) : context;
|
|
462
|
-
const debugContent = debugContext
|
|
476
|
+
const debugContent = debugContext !== undefined && debugContext !== null
|
|
463
477
|
? JSON.stringify(debugContext, null, 2)
|
|
464
478
|
: `Current context for "${this.contextKey}" is empty`;
|
|
465
479
|
return `<pre>${debugContent}</pre>`;
|
|
@@ -495,16 +509,17 @@ const parseTagDebugNode = {
|
|
|
495
509
|
};
|
|
496
510
|
|
|
497
511
|
class TagForNode extends TagNode {
|
|
512
|
+
contextKey;
|
|
498
513
|
constructor({ contextKey }) {
|
|
499
514
|
super('tag-for');
|
|
500
|
-
this.contextKey = contextKey
|
|
515
|
+
this.contextKey = contextKey ?? 'this';
|
|
501
516
|
}
|
|
502
517
|
render(context, renderer) {
|
|
503
518
|
const contextNew = this.contextKey === 'this' ? context : readNestedValue(this.contextKey, context);
|
|
504
519
|
if (Array.isArray(contextNew)) {
|
|
505
520
|
return this.renderArray(contextNew, context, renderer);
|
|
506
521
|
}
|
|
507
|
-
if (typeof contextNew === 'object') {
|
|
522
|
+
if (contextNew !== null && typeof contextNew === 'object') {
|
|
508
523
|
return this.renderObject(contextNew, context, renderer);
|
|
509
524
|
}
|
|
510
525
|
return '';
|
|
@@ -513,7 +528,7 @@ class TagForNode extends TagNode {
|
|
|
513
528
|
return context
|
|
514
529
|
.map((item, index) => {
|
|
515
530
|
return this.renderChildNodes({
|
|
516
|
-
...(typeof item === 'object' ? item : {}),
|
|
531
|
+
...(item !== null && typeof item === 'object' ? item : {}),
|
|
517
532
|
_contextKey: this.contextKey,
|
|
518
533
|
_loop: { index, value: item },
|
|
519
534
|
_parent: parentContext,
|
|
@@ -524,10 +539,11 @@ class TagForNode extends TagNode {
|
|
|
524
539
|
renderObject(context, parentContext, renderer) {
|
|
525
540
|
return Object.keys(context)
|
|
526
541
|
.map((key, index) => {
|
|
542
|
+
const value = context[key];
|
|
527
543
|
return this.renderChildNodes({
|
|
528
|
-
...(typeof
|
|
544
|
+
...(value !== null && typeof value === 'object' ? value : {}),
|
|
529
545
|
_contextKey: this.contextKey,
|
|
530
|
-
_loop: { index, key, value
|
|
546
|
+
_loop: { index, key, value },
|
|
531
547
|
_parent: parentContext,
|
|
532
548
|
}, renderer);
|
|
533
549
|
})
|
|
@@ -564,6 +580,7 @@ const parseTagForNode = {
|
|
|
564
580
|
};
|
|
565
581
|
|
|
566
582
|
class TagIfNode extends TagNode {
|
|
583
|
+
options;
|
|
567
584
|
constructor(options) {
|
|
568
585
|
super('tag-if');
|
|
569
586
|
this.options = options;
|
|
@@ -573,7 +590,8 @@ class TagIfNode extends TagNode {
|
|
|
573
590
|
if (this.options.operator) {
|
|
574
591
|
value = this.compare(value, this.getValue(context, 'secondValue', 'secondContextKey'), this.options.operator);
|
|
575
592
|
}
|
|
576
|
-
|
|
593
|
+
const isTruthy = value !== undefined && value !== null && value !== false && value !== 0 && value !== '';
|
|
594
|
+
return isTruthy ? this.renderChildNodes(context, renderer) : '';
|
|
577
595
|
}
|
|
578
596
|
getValue(context, valueKey, contextKey) {
|
|
579
597
|
return this.options[contextKey] !== undefined
|
|
@@ -659,9 +677,9 @@ const parseTagIfNode = {
|
|
|
659
677
|
if (options.operator === undefined && options.firstContextKey === undefined) {
|
|
660
678
|
throw new TagNodeError('Expected context key when no operator is given');
|
|
661
679
|
}
|
|
662
|
-
if (options.operator !== undefined
|
|
663
|
-
options.secondContextKey === undefined
|
|
664
|
-
options.secondValue === undefined) {
|
|
680
|
+
if (options.operator !== undefined
|
|
681
|
+
&& options.secondContextKey === undefined
|
|
682
|
+
&& options.secondValue === undefined) {
|
|
665
683
|
throw new TagNodeError('Expected second context key or value when operator is given');
|
|
666
684
|
}
|
|
667
685
|
return new TagIfNode(options);
|
|
@@ -671,14 +689,18 @@ const parseTagIfNode = {
|
|
|
671
689
|
};
|
|
672
690
|
|
|
673
691
|
class TagPageNode extends TagNode {
|
|
692
|
+
name;
|
|
693
|
+
contextKey;
|
|
674
694
|
constructor({ name, contextKey }) {
|
|
675
695
|
super('tag-page');
|
|
676
|
-
this.name = name
|
|
677
|
-
this.contextKey = contextKey
|
|
696
|
+
this.name = name ?? 'default';
|
|
697
|
+
this.contextKey = contextKey ?? 'this';
|
|
678
698
|
}
|
|
679
699
|
render(context, renderer) {
|
|
680
700
|
let pageName = this.name;
|
|
681
|
-
const newContext = this.contextKey === 'this'
|
|
701
|
+
const newContext = this.contextKey === 'this'
|
|
702
|
+
? context
|
|
703
|
+
: readNestedValue(this.contextKey, context);
|
|
682
704
|
if (pageName.includes('.')) {
|
|
683
705
|
const foundName = readNestedValue(pageName, context);
|
|
684
706
|
if (typeof foundName === 'string' && foundName) {
|
|
@@ -707,10 +729,10 @@ const parseTagPageNode = {
|
|
|
707
729
|
if (token.type !== 'identifier') {
|
|
708
730
|
throw new TagNodeError('Expected tag identifier');
|
|
709
731
|
}
|
|
710
|
-
if (options.name && options.contextKey) {
|
|
732
|
+
if ((options.name !== undefined && options.name !== '') && (options.contextKey !== undefined && options.contextKey !== '')) {
|
|
711
733
|
throw new TagNodeError('Expected only one name and context key');
|
|
712
734
|
}
|
|
713
|
-
if (options.name) {
|
|
735
|
+
if (options.name !== undefined && options.name !== '') {
|
|
714
736
|
options.contextKey = token.name;
|
|
715
737
|
}
|
|
716
738
|
else {
|
|
@@ -725,13 +747,17 @@ const parseTagPageNode = {
|
|
|
725
747
|
};
|
|
726
748
|
|
|
727
749
|
class TagPartialNode extends TagNode {
|
|
750
|
+
name;
|
|
751
|
+
contextKey;
|
|
728
752
|
constructor({ name, contextKey }) {
|
|
729
753
|
super('tag-partial');
|
|
730
754
|
this.name = name;
|
|
731
|
-
this.contextKey = contextKey
|
|
755
|
+
this.contextKey = contextKey ?? 'this';
|
|
732
756
|
}
|
|
733
757
|
render(context, renderer) {
|
|
734
|
-
const newContext = this.contextKey === 'this'
|
|
758
|
+
const newContext = this.contextKey === 'this'
|
|
759
|
+
? context
|
|
760
|
+
: readNestedValue(this.contextKey, context);
|
|
735
761
|
return renderer.partial(this.name, newContext);
|
|
736
762
|
}
|
|
737
763
|
}
|
|
@@ -754,10 +780,10 @@ const parseTagPartialNode = {
|
|
|
754
780
|
if (token.type !== 'identifier') {
|
|
755
781
|
throw new TagNodeError('Expected tag identifier');
|
|
756
782
|
}
|
|
757
|
-
if (options.name && options.contextKey) {
|
|
783
|
+
if ((options.name !== undefined && options.name !== '') && (options.contextKey !== undefined && options.contextKey !== '')) {
|
|
758
784
|
throw new TagNodeError('Expected only one name and context key');
|
|
759
785
|
}
|
|
760
|
-
if (options.name) {
|
|
786
|
+
if (options.name !== undefined && options.name !== '') {
|
|
761
787
|
options.contextKey = token.name;
|
|
762
788
|
}
|
|
763
789
|
else {
|
|
@@ -765,7 +791,7 @@ const parseTagPartialNode = {
|
|
|
765
791
|
}
|
|
766
792
|
},
|
|
767
793
|
create() {
|
|
768
|
-
if (
|
|
794
|
+
if (options.name === undefined || options.name === '') {
|
|
769
795
|
throw new TagNodeError('Expected partial name');
|
|
770
796
|
}
|
|
771
797
|
return new TagPartialNode(options);
|
|
@@ -775,16 +801,16 @@ const parseTagPartialNode = {
|
|
|
775
801
|
};
|
|
776
802
|
|
|
777
803
|
class TagVarNode extends TagNode {
|
|
804
|
+
contextKey;
|
|
805
|
+
escape;
|
|
778
806
|
constructor({ contextKey, escape }) {
|
|
779
807
|
super('tag-var');
|
|
780
808
|
this.contextKey = contextKey;
|
|
781
809
|
this.escape = !!escape;
|
|
782
810
|
}
|
|
783
811
|
render(context) {
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
value = String(value);
|
|
787
|
-
}
|
|
812
|
+
const rawValue = readNestedValue(this.contextKey, context);
|
|
813
|
+
const value = rawValue === undefined || rawValue === null ? '' : String(rawValue);
|
|
788
814
|
return this.escape ? escapeHtml(value) : value;
|
|
789
815
|
}
|
|
790
816
|
}
|
|
@@ -820,7 +846,7 @@ const parseTagVarNode = {
|
|
|
820
846
|
options.escape = true;
|
|
821
847
|
},
|
|
822
848
|
create() {
|
|
823
|
-
if (
|
|
849
|
+
if (options.contextKey === undefined || options.contextKey === '') {
|
|
824
850
|
throw new TagNodeError('Expected context key');
|
|
825
851
|
}
|
|
826
852
|
return new TagVarNode(options);
|
|
@@ -839,19 +865,18 @@ const tagNodes = [
|
|
|
839
865
|
];
|
|
840
866
|
|
|
841
867
|
class TemplateNode extends Node {
|
|
868
|
+
content;
|
|
842
869
|
constructor(content) {
|
|
843
870
|
super('template');
|
|
844
871
|
this.content = content;
|
|
845
872
|
}
|
|
846
|
-
render() {
|
|
873
|
+
render(_context, _renderer) {
|
|
847
874
|
return this.content;
|
|
848
875
|
}
|
|
849
876
|
}
|
|
850
877
|
|
|
851
878
|
class NodeParser {
|
|
852
|
-
|
|
853
|
-
this.tags = {};
|
|
854
|
-
}
|
|
879
|
+
tags = {};
|
|
855
880
|
static init() {
|
|
856
881
|
const parser = new NodeParser();
|
|
857
882
|
tagNodes.forEach(tag => parser.registerTagParser(tag));
|
|
@@ -869,7 +894,6 @@ class NodeParser {
|
|
|
869
894
|
return this.parseChildren(lexer, tree);
|
|
870
895
|
}
|
|
871
896
|
parseChildren(lexer, parent) {
|
|
872
|
-
var _a;
|
|
873
897
|
let token = lexer.consume();
|
|
874
898
|
while (token) {
|
|
875
899
|
switch (token.type) {
|
|
@@ -880,12 +904,20 @@ class NodeParser {
|
|
|
880
904
|
parent.append(new CommentNode(token.content));
|
|
881
905
|
break;
|
|
882
906
|
case 'tag-open':
|
|
883
|
-
if (
|
|
907
|
+
if (lexer.peek()?.type === 'tag-end') {
|
|
884
908
|
return parent;
|
|
885
909
|
}
|
|
886
910
|
parent.append(this.parseTag(lexer));
|
|
887
911
|
break;
|
|
888
|
-
|
|
912
|
+
case 'string':
|
|
913
|
+
case 'number':
|
|
914
|
+
case 'boolean':
|
|
915
|
+
case 'tag-identifier':
|
|
916
|
+
case 'identifier':
|
|
917
|
+
case 'operator':
|
|
918
|
+
case 'tag-close':
|
|
919
|
+
case 'tag-end':
|
|
920
|
+
case 'tag-separator':
|
|
889
921
|
throw new ParserError(`Unexpected token type "${token.type}"`);
|
|
890
922
|
}
|
|
891
923
|
token = lexer.consume();
|
|
@@ -893,13 +925,12 @@ class NodeParser {
|
|
|
893
925
|
return parent;
|
|
894
926
|
}
|
|
895
927
|
parseTag(lexer) {
|
|
896
|
-
var _a, _b, _c;
|
|
897
928
|
const tagIdentifier = lexer.consume();
|
|
898
929
|
if (!tagIdentifier || tagIdentifier.type !== 'tag-identifier') {
|
|
899
930
|
throw new ParserError('Expected tag identifier');
|
|
900
931
|
}
|
|
901
932
|
const tagDefinition = this.tags[tagIdentifier.name];
|
|
902
|
-
if (
|
|
933
|
+
if (tagDefinition === undefined) {
|
|
903
934
|
throw new ParserError(`Unknown tag "${tagIdentifier.name}"`);
|
|
904
935
|
}
|
|
905
936
|
const { addToken, create } = tagDefinition.parse();
|
|
@@ -914,7 +945,8 @@ class NodeParser {
|
|
|
914
945
|
}
|
|
915
946
|
catch (error) {
|
|
916
947
|
if (error instanceof TagNodeError) {
|
|
917
|
-
throw new ParserError(`Error parsing tag ${tagIdentifier.name} - ${error.message}\
|
|
948
|
+
throw new ParserError(`Error parsing tag ${tagIdentifier.name} - ${error.message}\n`
|
|
949
|
+
+ `Should be something like: ${tagDefinition.example}`);
|
|
918
950
|
}
|
|
919
951
|
throw error;
|
|
920
952
|
}
|
|
@@ -923,11 +955,11 @@ class NodeParser {
|
|
|
923
955
|
}
|
|
924
956
|
this.parseChildren(lexer, node);
|
|
925
957
|
const closeTokens = lexer.consume(3);
|
|
926
|
-
if (
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
closeTokens[1].name !== tagIdentifier.name
|
|
930
|
-
|
|
958
|
+
if (closeTokens === undefined
|
|
959
|
+
|| closeTokens[0]?.type !== 'tag-end'
|
|
960
|
+
|| closeTokens[1]?.type !== 'tag-identifier'
|
|
961
|
+
|| closeTokens[1].name !== tagIdentifier.name
|
|
962
|
+
|| closeTokens[2]?.type !== 'tag-close') {
|
|
931
963
|
throw new ParserError('Expected closing tag');
|
|
932
964
|
}
|
|
933
965
|
return node;
|
|
@@ -935,24 +967,26 @@ class NodeParser {
|
|
|
935
967
|
}
|
|
936
968
|
|
|
937
969
|
class TemplateLoader {
|
|
938
|
-
static
|
|
939
|
-
|
|
940
|
-
const
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
await Promise.all(
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
970
|
+
static TEMPLATES_PACKAGE = '@ui-doc/html-renderer/templates';
|
|
971
|
+
static async load({ renderer, fileSystem, templatePath, }) {
|
|
972
|
+
const paths = [
|
|
973
|
+
{ folderName: 'layouts', addFunction: 'addLayout' },
|
|
974
|
+
{ folderName: 'pages', addFunction: 'addPage' },
|
|
975
|
+
{ folderName: 'partials', addFunction: 'addPartial' },
|
|
976
|
+
];
|
|
977
|
+
await Promise.all(paths.map(async ({ folderName, addFunction }) => {
|
|
978
|
+
const searchPath = `${templatePath}/${folderName}`;
|
|
979
|
+
if (!(await fileSystem.isDirectory(searchPath))) {
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
982
|
+
const finder = fileSystem.createFileFinder([`${searchPath}/*.html`]);
|
|
983
|
+
await finder.search(async (file) => {
|
|
984
|
+
renderer[addFunction](fileSystem.fileBasename(file), {
|
|
985
|
+
content: (await fileSystem.fileRead(file)).trim(),
|
|
986
|
+
source: file,
|
|
987
|
+
});
|
|
988
|
+
});
|
|
989
|
+
}));
|
|
956
990
|
}
|
|
957
991
|
}
|
|
958
992
|
|
|
@@ -978,4 +1012,5 @@ exports.TemplateNode = TemplateNode;
|
|
|
978
1012
|
exports.escapeHtml = escapeHtml;
|
|
979
1013
|
exports.nodeOperators = nodeOperators;
|
|
980
1014
|
exports.readNestedValue = readNestedValue;
|
|
1015
|
+
if (exports.default) { module.exports = Object.assign(exports.default, exports); }
|
|
981
1016
|
//# sourceMappingURL=index.cjs.map
|