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