@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.
Files changed (102) hide show
  1. package/README.md +586 -151
  2. package/dist/HtmlCurlyBraceLexer.d.ts +4 -1
  3. package/dist/HtmlRenderer.d.ts +5 -5
  4. package/dist/InlineReader.d.ts +3 -2
  5. package/dist/{types/lexer.d.ts → Lexer.types.d.ts} +8 -5
  6. package/dist/NodeParser.d.ts +3 -2
  7. package/dist/{types/parser.d.ts → Parser.types.d.ts} +8 -8
  8. package/dist/{types/base.d.ts → Primitive.types.d.ts} +1 -1
  9. package/dist/{types/reader.d.ts → Reader.types.d.ts} +9 -7
  10. package/dist/Renderer.types.d.ts +14 -0
  11. package/dist/TemplateLoader.d.ts +3 -2
  12. package/dist/{types/token.d.ts → Token.types.d.ts} +1 -1
  13. package/dist/assets/services/expand.d.ts +19 -0
  14. package/dist/assets/ui-doc.cjs +283 -9
  15. package/dist/assets/ui-doc.cjs.map +1 -1
  16. package/dist/assets/ui-doc.css +1169 -250
  17. package/dist/assets/ui-doc.css.map +1 -1
  18. package/dist/assets/ui-doc.min.css +9 -1
  19. package/dist/assets/ui-doc.min.js +1 -1
  20. package/dist/assets/ui-doc.mjs +283 -9
  21. package/dist/assets/ui-doc.mjs.map +1 -1
  22. package/dist/assets/utils/delay.d.ts +1 -0
  23. package/dist/assets/utils/dom.d.ts +31 -0
  24. package/dist/assets/utils/select.d.ts +12 -0
  25. package/dist/index.cjs +161 -126
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.ts +6 -1
  28. package/dist/index.mjs +160 -126
  29. package/dist/index.mjs.map +1 -1
  30. package/dist/nodes/CommentNode.d.ts +2 -1
  31. package/dist/nodes/Node.d.ts +1 -1
  32. package/dist/nodes/TemplateNode.d.ts +2 -1
  33. package/dist/nodes/index.d.ts +4 -2
  34. package/dist/nodes/tags/debug.d.ts +2 -1
  35. package/dist/nodes/tags/for.d.ts +4 -3
  36. package/dist/nodes/tags/if.d.ts +5 -4
  37. package/dist/nodes/tags/index.d.ts +1 -1
  38. package/dist/nodes/tags/page.d.ts +2 -1
  39. package/dist/nodes/tags/partial.d.ts +2 -1
  40. package/dist/nodes/tags/var.d.ts +2 -1
  41. package/dist/utils/index.d.ts +1 -1
  42. package/package.json +32 -29
  43. package/scripts/app.ts +5 -3
  44. package/scripts/{src → services}/example.ts +3 -3
  45. package/scripts/services/expand.ts +214 -0
  46. package/scripts/{src → services}/sidebar.ts +4 -3
  47. package/scripts/utils/delay.ts +12 -0
  48. package/scripts/utils/dom.ts +77 -0
  49. package/scripts/utils/select.ts +46 -0
  50. package/styles/01_resets/initial.css +8 -3
  51. package/styles/01_resets/root/color.css +19 -0
  52. package/styles/01_resets/root/font.css +28 -0
  53. package/styles/01_resets/root/space.css +30 -0
  54. package/styles/01_resets/root/witdh.css +12 -0
  55. package/styles/01_resets/root.css +61 -23
  56. package/styles/01_resets/typography.css +105 -8
  57. package/styles/02_utils/background.css +14 -0
  58. package/styles/02_utils/control.css +41 -0
  59. package/styles/02_utils/margin.css +150 -0
  60. package/styles/02_utils/padding.css +134 -0
  61. package/styles/02_utils/width.css +39 -0
  62. package/styles/03_components/button.css +42 -0
  63. package/styles/03_components/colors.css +7 -19
  64. package/styles/03_components/container.css +16 -0
  65. package/styles/03_components/example-markup.css +1 -6
  66. package/styles/03_components/grid-auto.css +49 -0
  67. package/styles/03_components/icons.css +7 -19
  68. package/styles/03_components/navigation/burger-control.css +75 -0
  69. package/styles/03_components/{nav → navigation}/list.css +9 -11
  70. package/styles/03_components/navigation/main.css +102 -0
  71. package/styles/03_components/spaces.css +8 -7
  72. package/styles/04_layout/body.css +22 -0
  73. package/styles/04_layout/inline-code.css +6 -0
  74. package/styles/04_layout/page.css +73 -0
  75. package/styles/index.css +58 -17
  76. package/templates/layouts/default.html +4 -6
  77. package/templates/layouts/example.html +1 -1
  78. package/templates/pages/default.html +13 -13
  79. package/templates/pages/index.html +9 -3
  80. package/templates/partials/code.html +1 -1
  81. package/templates/partials/colors.html +2 -2
  82. package/templates/partials/content.html +1 -1
  83. package/templates/partials/icons.html +3 -3
  84. package/templates/partials/nav-main.html +19 -8
  85. package/templates/partials/section.html +1 -1
  86. package/templates/partials/spaces.html +2 -2
  87. package/LICENSE.md +0 -9
  88. package/dist/assets/src/utils.d.ts +0 -2
  89. package/dist/types/index.d.ts +0 -6
  90. package/dist/types/renderer.d.ts +0 -14
  91. package/scripts/src/utils.ts +0 -20
  92. package/styles/02_objects/background.css +0 -7
  93. package/styles/02_objects/control.css +0 -25
  94. package/styles/02_objects/margin.css +0 -44
  95. package/styles/02_objects/padding.css +0 -44
  96. package/styles/02_objects/text.css +0 -3
  97. package/styles/02_objects/width.css +0 -16
  98. package/styles/03_components/nav/main.css +0 -39
  99. package/styles/03_components/text-flow.css +0 -5
  100. package/styles/04_layouts/page.css +0 -70
  101. /package/dist/assets/{src → services}/example.d.ts +0 -0
  102. /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 = 'TagNodeSyntaxError';
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.peak();
75
- if (char === '{' && this.reader.peak(2) === '{{') {
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.peak(4) === '<!--') {
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.peak(3) === '-->') {
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.peak();
124
- if (peek === '{' && this.reader.peak(2) === '{{') {
128
+ const peek = this.reader.peek();
129
+ if (peek === '{' && this.reader.peek(2) === '{{') {
125
130
  break;
126
131
  }
127
- if (peek === '<' && this.reader.peak(4) === '<!--') {
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.peak();
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.peak(2) === '}}') {
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.peak(4) === 'true') {
176
+ if (char === 't' && this.reader.peek(4) === 'true') {
172
177
  return this.consumeBoolean(true);
173
178
  }
174
- if (char === 'f' && this.reader.peak(5) === 'false') {
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.peak();
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.peak();
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.peak();
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
- peak(k = 1) {
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 (typeof object.peak === 'function' &&
311
- typeof object.consume === 'function' &&
312
- typeof object.isEof === 'function' &&
313
- typeof object.debug === 'function');
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 !== null && layout !== void 0 ? layout : 'default';
355
- const content = this.layouts[layout] || undefined;
356
- if (!content) {
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] || this.pages.default || undefined;
363
- if (!content) {
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] || this.partials.default || undefined;
370
- if (!content) {
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 !== null && context !== void 0 ? 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 target[name];
447
+ return obj[name];
435
448
  }
436
449
  const currentName = name.substring(0, index);
437
450
  const nextName = name.substring(index + 1);
438
- if (!target[currentName]) {
451
+ if (obj[currentName] === undefined || obj[currentName] === null) {
439
452
  return undefined;
440
453
  }
441
- return readNestedValue(nextName, target[currentName]);
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('<', '&lt;')
447
460
  .replaceAll('>', '&gt;')
448
461
  .replaceAll('"', '&quot;')
449
- .replaceAll("'", '&#039;');
462
+ .replaceAll('\'', '&#039;');
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 !== null && contextKey !== void 0 ? contextKey : 'this';
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 !== null && contextKey !== void 0 ? contextKey : 'this';
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 context[key] === 'object' ? context[key] : {}),
544
+ ...(value !== null && typeof value === 'object' ? value : {}),
529
545
  _contextKey: this.contextKey,
530
- _loop: { index, key, value: context[key] },
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
- return value ? this.renderChildNodes(context, renderer) : '';
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 !== null && name !== void 0 ? name : 'default';
677
- this.contextKey = contextKey !== null && contextKey !== void 0 ? contextKey : 'this';
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' ? context : readNestedValue(this.contextKey, context);
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 !== null && contextKey !== void 0 ? contextKey : 'this';
755
+ this.contextKey = contextKey ?? 'this';
732
756
  }
733
757
  render(context, renderer) {
734
- const newContext = this.contextKey === 'this' ? context : readNestedValue(this.contextKey, context);
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 (!options.name) {
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
- let value = readNestedValue(this.contextKey, context) || '';
785
- if (typeof value !== 'string') {
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 (!options.contextKey) {
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
- constructor() {
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 (((_a = lexer.peek()) === null || _a === void 0 ? void 0 : _a.type) === 'tag-end') {
907
+ if (lexer.peek()?.type === 'tag-end') {
884
908
  return parent;
885
909
  }
886
910
  parent.append(this.parseTag(lexer));
887
911
  break;
888
- default:
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 (!tagDefinition) {
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}\nShould be something like: ${tagDefinition.example}`);
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 (!closeTokens ||
927
- ((_a = closeTokens[0]) === null || _a === void 0 ? void 0 : _a.type) !== 'tag-end' ||
928
- ((_b = closeTokens[1]) === null || _b === void 0 ? void 0 : _b.type) !== 'tag-identifier' ||
929
- closeTokens[1].name !== tagIdentifier.name ||
930
- ((_c = closeTokens[2]) === null || _c === void 0 ? void 0 : _c.type) !== 'tag-close') {
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 async load({ renderer, fileSystem, templateBasePath = '@ui-doc/html-renderer/templates', }) {
939
- const templatePath = await fileSystem.assetLoader().packagePath(templateBasePath);
940
- const layoutFinder = fileSystem.createFileFinder([`${templatePath}/layouts/*.html`]);
941
- const pageFinder = fileSystem.createFileFinder([`${templatePath}/pages/*.html`]);
942
- const partialFinder = fileSystem.createFileFinder([`${templatePath}/partials/*.html`]);
943
- const name = (file) => fileSystem.fileBasename(file);
944
- const content = async (file) => (await fileSystem.fileRead(file)).trim();
945
- await Promise.all([
946
- layoutFinder.search(async (file) => {
947
- renderer.addLayout(name(file), { content: await content(file), source: file });
948
- }),
949
- pageFinder.search(async (file) => {
950
- renderer.addPage(name(file), { content: await content(file), source: file });
951
- }),
952
- partialFinder.search(async (file) => {
953
- renderer.addPartial(name(file), { content: await content(file), source: file });
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