@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 CHANGED
@@ -1,251 +1,686 @@
1
- # UI-Doc HTML Renderer
1
+ # @ui-doc/html-renderer
2
2
 
3
- Simple and light HTML Rendering Engine. Its purpose is to create HTML from a Context Object by using a simple template syntax and have no dependencies. This project should not be used for complexer projects, because of it's simplicity.
3
+ HTML renderer for UI-Doc that converts UI-Doc context objects into interactive HTML documentation pages. It implements the `Renderer` interface from `@ui-doc/core` and includes a built-in template engine with zero dependencies.
4
4
 
5
- ## Tags
5
+ ## Overview
6
6
 
7
- Tags are used to get a bit of functionality into the html generation process.
7
+ The HTML renderer provides:
8
8
 
9
- ### var
9
+ - **Template Engine** - A lightweight, dependency-free template system with custom syntax
10
+ - **Built-in Templates** - Ready-to-use layouts, pages, and partials for documentation
11
+ - **Asset Management** - Pre-built CSS and JavaScript for documentation styling
12
+ - **Extensibility** - Custom templates and styling support
10
13
 
11
- Output value of a variable.
14
+ ## Installation
12
15
 
16
+ ```bash
17
+ npm install @ui-doc/html-renderer @ui-doc/core
13
18
  ```
14
- <h1>{{var:title}}</h1>
19
+
20
+ ## Quick Start
21
+
22
+ ### Basic Usage
23
+
24
+ ```ts
25
+ import { HtmlRenderer, NodeParser } from '@ui-doc/html-renderer'
26
+
27
+ // Create a renderer instance
28
+ const renderer = new HtmlRenderer(NodeParser.init())
29
+
30
+ // Add templates
31
+ renderer.addLayout('default', {
32
+ source: 'inline',
33
+ content: `
34
+ <html>
35
+ <head>
36
+ <title>{{var:title}}</title>
37
+ </head>
38
+ <body>
39
+ {{page:default}}
40
+ </body>
41
+ </html>
42
+ `,
43
+ })
44
+
45
+ renderer.addPage('default', {
46
+ source: 'inline',
47
+ content: `
48
+ <h1>{{var:title}}</h1>
49
+ <div>{{var:content}}</div>
50
+ `,
51
+ })
52
+
53
+ // Generate HTML from context
54
+ const html = renderer.generate({
55
+ title: 'My Documentation',
56
+ page: {
57
+ title: 'Welcome',
58
+ content: '<p>Documentation content here</p>',
59
+ },
60
+ assets: [],
61
+ })
15
62
  ```
16
63
 
17
- To escape the variable use `{{var:title escape}}`.
64
+ ### Integration with UI-Doc
18
65
 
19
- ### if
66
+ ```ts
67
+ import { UIDoc } from '@ui-doc/core'
68
+ import { HtmlRenderer, NodeParser, TemplateLoader } from '@ui-doc/html-renderer'
69
+ import { NodeFileSystem } from '@ui-doc/node'
20
70
 
21
- Use a if condition to decide when our when not to render something. Please not that currently there is no `else` or `ifelse`
71
+ const fileSystem = new NodeFileSystem()
72
+ const renderer = new HtmlRenderer(NodeParser.init())
22
73
 
23
- ```
24
- {{if:show}}
25
- <p>Show this if show inside the context is a true statement</p>
26
- {{/if}}
27
- ```
74
+ // Load built-in templates
75
+ const templatePath = await fileSystem.assetLoader().packagePath(
76
+ TemplateLoader.TEMPLATES_PACKAGE,
77
+ )
78
+ await TemplateLoader.load({ renderer, fileSystem, templatePath })
79
+
80
+ // Create UI-Doc instance
81
+ const uidoc = new UIDoc({ renderer })
28
82
 
29
- #### Conditions
83
+ // Process source files
84
+ uidoc.sourceCreate('path/to/source.css', await fileSystem.fileRead('path/to/source.css'))
30
85
 
31
- You can use conditions
86
+ // Output documentation
87
+ await uidoc.output(async (file, content) => {
88
+ await fileSystem.fileWrite(`./dist/${file}`, content)
89
+ })
32
90
 
91
+ // Copy required assets
92
+ const assetLoader = fileSystem.assetLoader()
93
+ await assetLoader.copy('@ui-doc/html-renderer/ui-doc.min.css', './dist/ui-doc.css')
94
+ await assetLoader.copy('@ui-doc/html-renderer/ui-doc.min.js', './dist/ui-doc.js')
33
95
  ```
34
- {{if:title === "foo"}}
35
- {{if:show === true}}
36
- {{if:page.number === 3}}
96
+
97
+ ## Template Syntax
98
+
99
+ The template engine uses double curly braces `{{...}}` for directives.
100
+
101
+ ### Variables
102
+
103
+ Output values from the context:
104
+
105
+ ```html
106
+ <h1>{{var:title}}</h1>
107
+ <p>{{var:description}}</p>
108
+
109
+ <!-- Access nested properties with dot notation -->
110
+ <div>{{var:page.content}}</div>
111
+
112
+ <!-- Escape HTML output -->
113
+ <div>{{var:userInput escape}}</div>
37
114
  ```
38
115
 
39
- **Operators:**
116
+ ### Conditionals
40
117
 
41
- - `===`
42
- - `==`
43
- - `!==`
44
- - `!=`
45
- - `<`
46
- - `<=`
47
- - `>`
48
- - `>=`
118
+ Render content conditionally:
49
119
 
50
- ### for
120
+ ```html
121
+ {{if:showContent}}
122
+ <p>This is visible when showContent is truthy</p>
123
+ {{/if}}
124
+ ```
51
125
 
52
- Use for to loop over objects and arrays. Please not that a loop will change the context to help you access inside your loop target and give you loop specific context like index and object keys.
126
+ Supported comparison operators: `===`, `==`, `!==`, `!=`, `<`, `<=`, `>`, `>=`
53
127
 
54
- #### array loop
128
+ ```html
129
+ {{if:status === "active"}}
130
+ <span>Active</span>
131
+ {{/if}}
55
132
 
133
+ {{if:count > 5}}
134
+ <span>More than 5 items</span>
135
+ {{/if}}
56
136
  ```
57
- <!-- context: {"list": ["foo", "bar", "baz"]} -->
137
+
138
+ ### Loops
139
+
140
+ #### Array Loops
141
+
142
+ ```html
143
+ <!-- Context: {"items": ["apple", "banana", "cherry"]} -->
58
144
  <ul>
59
- {{for:list}}
60
- <li>{{var:_loop.value}}, index: {{var:_loop.index}}</li>
145
+ {{for:items}}
146
+ <li>{{var:_loop.value}} (index: {{var:_loop.index}})</li>
61
147
  {{/for}}
62
148
  </ul>
63
149
 
64
150
  <!-- Output: -->
65
151
  <ul>
66
- <li>foo, index: 0</li>
67
- <li>bar, index: 1</li>
68
- <li>baz, index: 2</li>
152
+ <li>apple (index: 0)</li>
153
+ <li>banana (index: 1)</li>
154
+ <li>cherry (index: 2)</li>
69
155
  </ul>
70
156
  ```
71
157
 
72
- #### object loop
158
+ #### Object Loops
73
159
 
74
- ```
75
- <!-- context: {"list": {"foo": "FOO", "bar": "BAR", "baz": "BAZ"}} -->
160
+ ```html
161
+ <!-- Context: {"colors": {"red": "#f00", "green": "#0f0", "blue": "#00f"}} -->
76
162
  <ul>
77
- {{for:list}}
78
- <li>{{var:_loop.value}}, key: {{var:_loop.key}}, index: {{var:_loop.index}}</li>
163
+ {{for:colors}}
164
+ <li>{{var:_loop.key}}: {{var:_loop.value}}</li>
79
165
  {{/for}}
80
166
  </ul>
81
167
 
82
168
  <!-- Output: -->
83
169
  <ul>
84
- <li>FOO, key: foo, index: 0</li>
85
- <li>BAR, key: bar, index: 1</li>
86
- <li>BAZ, key: baz, index: 2</li>
170
+ <li>red: #f00</li>
171
+ <li>green: #0f0</li>
172
+ <li>blue: #00f</li>
87
173
  </ul>
88
174
  ```
89
175
 
90
- #### loop items as objects
176
+ #### Looping Over Object Arrays
91
177
 
92
- You can loop over an array or object of objects. The object items will directly be accessible inside the for context.
178
+ ```html
179
+ <!-- Context: {"sections": [{"title": "Intro", "content": "..."}, {"title": "Details", "content": "..."}]} -->
180
+ {{for:sections}}
181
+ <section>
182
+ <h2>{{var:title}}</h2>
183
+ <div>{{var:content}}</div>
184
+ </section>
185
+ {{/for}}
186
+ ```
187
+
188
+ Loop variables available in `_loop`:
189
+
190
+ - `_loop.value` - Current item value
191
+ - `_loop.index` - Current iteration index (0-based)
192
+ - `_loop.key` - Current key (for object loops)
193
+
194
+ ### Pages
195
+
196
+ Render registered page templates with optional context switching:
93
197
 
198
+ ```html
199
+ <!-- Use the default page template -->
200
+ {{page}}
201
+
202
+ <!-- Use a specific page template -->
203
+ {{page:default}}
204
+
205
+ <!-- Use a page template with different context -->
206
+ {{page:default page}}
94
207
  ```
95
- <!-- context: {"sections": [{"title": "Section 1", content: "<p>Section 1 content</p>"}, {"title": "Section 2", content: "<p>Section 2 content</p>"}]} -->
96
208
 
97
- {{for:sections}}
98
- <section>
99
- <h2>{{var::title}}</h2>
100
- {{var:content}}
101
- </section>
102
- {{/for}}
209
+ ### Partials
103
210
 
104
- <!-- Output: -->
105
- <section>
106
- <h2>Section 1</h2>
107
- <p>Section 1 content</p>
108
- </section>
109
- <section>
110
- <h2>Section 2</h2>
111
- <p>Section 2 content</p>
112
- </section>
211
+ Include reusable template fragments:
212
+
213
+ ```html
214
+ <!-- Include a partial -->
215
+ {{partial:nav-main}}
216
+
217
+ <!-- Include a partial with different context -->
218
+ {{partial:section currentSection}}
113
219
  ```
114
220
 
115
- ### page
221
+ ### Debug
222
+
223
+ Output context as JSON for debugging:
116
224
 
117
- Use page to output registered page templates (see Templates > Page). `{{page:foo}}` this will try to render the `foo` page. If no page with this name is registered the system will fallback to the `default` page. If you want to use the default page you can also just use `{{page}}`. As second parameter you can give a context if you like to change the context `{{page:layout newContext}}`.
225
+ ```html
226
+ <!-- Output entire context -->
227
+ {{debug}}
118
228
 
229
+ <!-- Output specific context property -->
230
+ {{debug:page}}
119
231
  ```
120
- <!-- context: {"title": "Document Title", "page": {"title": "Page title", "content": "Page content"}} -->
121
232
 
122
- <html>
123
- <head>
124
- <title>{{var:title}}</title>
125
- </head>
126
- <body>
127
- <!-- using default layout with new context `page` -->
128
- {{page:default page}}
129
- </body>
130
- </html>
233
+ ## Template Types
131
234
 
132
- <!-- default page template with change context -->
133
- <!-- context: {"title": "Page title", "content": "Page content"} -->
235
+ ### Layouts
134
236
 
135
- <main>
136
- <h1>{{var:title}}</h1>
137
- <p>{{var:content}}</p>
138
- </main>
237
+ Define the overall HTML structure. A layout typically includes the `<html>`, `<head>`, and `<body>` tags.
238
+
239
+ ```ts
240
+ renderer.addLayout('default', {
241
+ source: 'my-layout.html',
242
+ content: `
243
+ <!doctype html>
244
+ <html lang="en">
245
+ <head>
246
+ <meta charset="utf-8" />
247
+ <title>{{var:title}}</title>
248
+ {{var:styles}}
249
+ </head>
250
+ <body>
251
+ {{page:default}}
252
+ {{var:scripts}}
253
+ </body>
254
+ </html>
255
+ `,
256
+ })
257
+ ```
139
258
 
140
- <!-- Output: -->
141
- <html>
142
- <head>
143
- <title>Document Title</title>
144
- </head>
145
- <body>
146
- <main>
147
- <h1>Page title</h1>
148
- <p>Page content</p>
149
- </main>
150
- </body>
151
- </html>
259
+ ### Pages
260
+
261
+ Define page-specific content structures:
262
+
263
+ ```ts
264
+ renderer.addPage('default', {
265
+ source: 'my-page.html',
266
+ content: `
267
+ <header>
268
+ <h1>{{var:title}}</h1>
269
+ {{if:description}}
270
+ <p>{{var:description}}</p>
271
+ {{/if}}
272
+ </header>
273
+ <main>
274
+ {{for:sections}}
275
+ {{partial:section}}
276
+ {{/for}}
277
+ </main>
278
+ `,
279
+ })
280
+ ```
281
+
282
+ ### Partials
283
+
284
+ Create reusable template components:
285
+
286
+ ```ts
287
+ renderer.addPartial('section', {
288
+ source: 'section.html',
289
+ content: `
290
+ <section id="{{var:id}}">
291
+ <h2>{{var:title}}</h2>
292
+ <div>{{var:content}}</div>
293
+ </section>
294
+ `,
295
+ })
152
296
  ```
153
297
 
154
- ### partial
298
+ ## Loading Templates
299
+
300
+ ### From Files
301
+
302
+ Use `TemplateLoader` to load templates from the file system:
303
+
304
+ ```ts
305
+ import { TemplateLoader } from '@ui-doc/html-renderer'
306
+ import { NodeFileSystem } from '@ui-doc/node'
307
+
308
+ const fileSystem = new NodeFileSystem()
155
309
 
156
- Use partial to render registered partial templates (see Templates > Partial). If the given partial name was not found nothing will be generated
310
+ // Load templates from a directory
311
+ await TemplateLoader.load({
312
+ renderer,
313
+ fileSystem,
314
+ templatePath: './my-templates',
315
+ })
316
+ ```
157
317
 
318
+ The loader expects this directory structure:
319
+
320
+ ```text
321
+ my-templates/
322
+ layouts/
323
+ default.html
324
+ custom.html
325
+ pages/
326
+ default.html
327
+ index.html
328
+ partials/
329
+ nav.html
330
+ section.html
158
331
  ```
159
- {{partial:foo}} > output foo partial
332
+
333
+ ### Using Built-in Templates
334
+
335
+ The package includes ready-to-use templates:
336
+
337
+ ```ts
338
+ const templatePath = await fileSystem.assetLoader().packagePath(
339
+ TemplateLoader.TEMPLATES_PACKAGE,
340
+ )
341
+ await TemplateLoader.load({ renderer, fileSystem, templatePath })
160
342
  ```
161
343
 
162
- As second parameter you can give a context definition to change the context
344
+ ## Built-in Assets
345
+
346
+ The package provides pre-built CSS and JavaScript for documentation styling.
163
347
 
348
+ ### CSS
349
+
350
+ ```bash
351
+ # Full CSS
352
+ @ui-doc/html-renderer/ui-doc.css
353
+
354
+ # Minified CSS
355
+ @ui-doc/html-renderer/ui-doc.min.css
164
356
  ```
165
- {{partial:foo bar}} > output foo partial using bar of the current context as new context
357
+
358
+ ### JavaScript
359
+
360
+ ```bash
361
+ # Full JavaScript
362
+ @ui-doc/html-renderer/ui-doc.js
363
+
364
+ # Minified JavaScript (for use in browsers)
365
+ @ui-doc/html-renderer/ui-doc.min.js
166
366
  ```
167
367
 
168
- ### debug
368
+ ### Copying Assets
169
369
 
170
- Use debug to output the current context or parts of the context. The context will be outputted as JSON.
370
+ ```ts
371
+ const assetLoader = fileSystem.assetLoader()
171
372
 
373
+ await assetLoader.copy(
374
+ '@ui-doc/html-renderer/ui-doc.min.css',
375
+ './dist/ui-doc.css',
376
+ )
377
+ await assetLoader.copy(
378
+ '@ui-doc/html-renderer/ui-doc.min.js',
379
+ './dist/ui-doc.js',
380
+ )
172
381
  ```
173
- <!-- context: {"title": "Document Title", "page": {"title": "Page title", "content": "Page content"}} -->
174
382
 
175
- {{debug}}
176
- <!-- Output: -->
177
- {"title": "Document Title", "page": {"title": "Page title", "content": "Page content"}}
383
+ ### Syntax Highlighting
178
384
 
179
- {{debug:page}}
180
- <!-- Output: -->
181
- {"title": "Page title", "content": "Page content"}
385
+ The built-in templates use highlight.js for code syntax highlighting. Include it in your output:
182
386
 
387
+ ```ts
388
+ await assetLoader.copy(
389
+ '@highlightjs/cdn-assets/styles/default.min.css',
390
+ './dist/highlight.css',
391
+ )
392
+ await assetLoader.copy(
393
+ '@highlightjs/cdn-assets/highlight.min.js',
394
+ './dist/highlight.js',
395
+ )
183
396
  ```
184
397
 
185
- ## Templates
398
+ ## API Reference
186
399
 
187
- You can register different template parts to the renderer these templates can then be reused wile generation.
400
+ ### HtmlRenderer
188
401
 
189
- ### Layouts
402
+ The main renderer class implementing the `Renderer` interface.
403
+
404
+ #### Constructor
405
+
406
+ ```text
407
+ new HtmlRenderer(parser: Parser)
408
+ ```
409
+
410
+ - `parser` - A `Parser` instance (typically `NodeParser.init()`)
411
+
412
+ #### Methods
190
413
 
191
- Define the HTML basic structure.
414
+ ##### addLayout(name, layout)
192
415
 
193
- ### Page
416
+ Register a layout template.
194
417
 
195
- Define a page specific template. You can use the `{{page:your-page-template-name}}` tag to render a specific page template. Page templates are not necessary but they help to keep layouts smaller and easier to read.
418
+ ```text
419
+ renderer.addLayout(name: string, layout: SourceInput): HtmlRenderer
420
+ ```
421
+
422
+ - `name` - Unique identifier for the layout
423
+ - `layout` - Template source (object with `source` and `content` properties, or a `Reader` instance)
424
+ - Returns the renderer instance for chaining
425
+
426
+ ##### addPage(name, page)
427
+
428
+ Register a page template.
429
+
430
+ ```text
431
+ renderer.addPage(name: string, page: SourceInput): HtmlRenderer
432
+ ```
433
+
434
+ - `name` - Unique identifier for the page
435
+ - `page` - Template source
436
+ - Returns the renderer instance for chaining
437
+
438
+ ##### addPartial(name, partial)
439
+
440
+ Register a partial template.
441
+
442
+ ```text
443
+ renderer.addPartial(name: string, partial: SourceInput): HtmlRenderer
444
+ ```
445
+
446
+ - `name` - Unique identifier for the partial
447
+ - `partial` - Template source
448
+ - Returns the renderer instance for chaining
449
+
450
+ ##### generate(context, layout?)
451
+
452
+ Generate HTML from a context object.
453
+
454
+ ```text
455
+ renderer.generate(context: GenerateContext, layout?: string): string
456
+ ```
457
+
458
+ - `context` - The UI-Doc context object to render
459
+ - `layout` - Optional layout name (defaults to `'default'`)
460
+ - Returns the generated HTML string
461
+
462
+ The `GenerateContext` includes:
463
+
464
+ - `title` - Document title
465
+ - `page` - Page context object
466
+ - `assets` - Array of asset objects with `type`, `src`, and optional `attrs`
467
+ - Additional properties from your UI-Doc configuration
468
+
469
+ ##### page(name, context)
470
+
471
+ Render a specific page template with context.
472
+
473
+ ```text
474
+ renderer.page(name: string, context: RenderContext): string
475
+ ```
476
+
477
+ - `name` - Page template name (falls back to `'default'` if not found)
478
+ - `context` - Context object for rendering
479
+ - Returns the rendered HTML string
480
+
481
+ ##### partial(name, context?)
482
+
483
+ Render a specific partial template with optional context.
484
+
485
+ ```text
486
+ renderer.partial(name: string, context?: RenderContext): string
487
+ ```
488
+
489
+ - `name` - Partial template name (falls back to `'default'` if not found)
490
+ - `context` - Optional context object (defaults to empty object)
491
+ - Returns the rendered HTML string
492
+
493
+ ### NodeParser
494
+
495
+ Parser for the template syntax.
496
+
497
+ #### Static Methods
498
+
499
+ ##### init()
500
+
501
+ Create and initialize a parser with all built-in tags.
502
+
503
+ ```text
504
+ NodeParser.init(): NodeParser
505
+ ```
506
+
507
+ Returns a configured `NodeParser` instance.
508
+
509
+ #### Methods
510
+
511
+ ##### registerTagParser(tag)
512
+
513
+ Register a custom tag parser.
514
+
515
+ ```text
516
+ parser.registerTagParser(tag: TagNodeParse): NodeParser
517
+ ```
196
518
 
197
- ### Partial
519
+ - `tag` - Tag parser definition
520
+ - Returns the parser instance for chaining
198
521
 
199
- Define a partial that can be reused, to get the same output inside layouts, pages and even in other partials. You can use the `{{partial:your-partial-name}}` tag to render the partial.
522
+ ### TemplateLoader
200
523
 
201
- ## Usage
524
+ Utility for loading templates from the file system.
202
525
 
526
+ #### Static Properties
527
+
528
+ ##### TEMPLATES_PACKAGE
529
+
530
+ ```text
531
+ static readonly TEMPLATES_PACKAGE: string
203
532
  ```
204
- import { HtmlRenderer } from '@ui-doc/html-renderer'
205
533
 
206
- const layout = `
207
- <html>
534
+ Package identifier for built-in templates: `'@ui-doc/html-renderer/templates'`
535
+
536
+ #### Static Methods
537
+
538
+ ##### load(options)
539
+
540
+ Load templates from a directory.
541
+
542
+ ```text
543
+ static async load(options: {
544
+ renderer: HtmlRenderer
545
+ fileSystem: FileSystem
546
+ templatePath: string
547
+ }): Promise<void>
548
+ ```
549
+
550
+ - `options.renderer` - The renderer to load templates into
551
+ - `options.fileSystem` - File system instance (typically `NodeFileSystem`)
552
+ - `options.templatePath` - Path to the templates directory
553
+
554
+ ## Error Handling
555
+
556
+ The renderer throws specific errors for better debugging:
557
+
558
+ ### HTMLRendererError
559
+
560
+ Thrown when a required template is not found.
561
+
562
+ ```ts
563
+ try {
564
+ renderer.generate(context, 'nonexistent-layout')
565
+ } catch (error) {
566
+ if (error instanceof HTMLRendererError) {
567
+ console.error(`Template error: ${error.message}`)
568
+ }
569
+ }
570
+ ```
571
+
572
+ ### HTMLRendererSyntaxError
573
+
574
+ Thrown when template syntax is invalid.
575
+
576
+ ```ts
577
+ import { HTMLRendererSyntaxError } from '@ui-doc/html-renderer'
578
+
579
+ try {
580
+ renderer.addLayout('bad', {
581
+ source: 'inline',
582
+ content: '{{invalid:syntax',
583
+ })
584
+ } catch (error) {
585
+ if (error instanceof HTMLRendererSyntaxError) {
586
+ console.error(`Syntax error at line ${error.line}, column ${error.column}`)
587
+ console.error(error.message)
588
+ }
589
+ }
590
+ ```
591
+
592
+ Properties:
593
+
594
+ - `message` - Error description
595
+ - `source` - Source identifier
596
+ - `line` - Line number where error occurred
597
+ - `column` - Column number where error occurred
598
+ - `code` - The problematic code snippet
599
+
600
+ ## Custom Templates
601
+
602
+ You can create custom templates to match your design requirements.
603
+
604
+ ### Example Custom Layout
605
+
606
+ ```html
607
+ <!doctype html>
608
+ <html lang="en">
208
609
  <head>
209
- <meta charset="utf-8">
610
+ <meta charset="utf-8" />
611
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
210
612
  <title>{{var:title}}</title>
613
+ {{var:styles}}
614
+ <link rel="stylesheet" href="custom-styles.css" />
211
615
  </head>
212
- <body>
213
- {{page:default}}
214
- </body>
215
- </html>`
616
+ <body class="custom-theme">
617
+ <header class="site-header">
618
+ <nav>{{partial:main-nav}}</nav>
619
+ </header>
216
620
 
217
- const page = `
218
- <h1>{{var:title}}</h1>
621
+ <main class="site-content">
622
+ {{page:page.id page}}
623
+ </main>
219
624
 
220
- {{if:excerpt}}
221
- <div>{{var:excerpt}}</div>
222
- {{/if}}
625
+ <footer class="site-footer">
626
+ <p>&copy; 2024 {{var:name}}</p>
627
+ </footer>
223
628
 
224
- {{for:sections}}
225
- {{partial:section}}
226
- {{/for}}`
629
+ {{var:scripts}}
630
+ <script src="custom-scripts.js"></script>
631
+ </body>
632
+ </html>
633
+ ```
227
634
 
228
- const section = `
229
- <h2>{{var:title}}</h2>
635
+ ### Example Custom Page
636
+
637
+ ```html
638
+ <article class="documentation-page">
639
+ <header class="page-header">
640
+ <h1>{{var:title}}</h1>
641
+ {{if:description}}
642
+ <div class="page-description">{{var:description}}</div>
643
+ {{/if}}
644
+ </header>
645
+
646
+ {{if:sections}}
647
+ <div class="page-sections">
648
+ {{for:sections}}
649
+ {{partial:custom-section}}
650
+ {{/for}}
651
+ </div>
652
+ {{/if}}
653
+ </article>
654
+ ```
230
655
 
231
- {{var:content}}
232
- `
656
+ ## Integration with Build Tools
233
657
 
234
- const renderer = new HtmlRenderer()
658
+ While you can use the HTML renderer directly, it's typically used through build tool plugins:
235
659
 
236
- renderer.addLayout('default', layout)
237
- renderer.addPage('default', page)
238
- renderer.addPartial('section', section)
660
+ - **Rollup** - Use [`@ui-doc/rollup`](../rollup/README.md)
661
+ - **Vite** - Use [`@ui-doc/vite`](../vite/README.md)
239
662
 
240
- renderer.generate({
241
- title: 'Example',
242
- page: {
243
- title: 'Example Page Title',
244
- sections: [
245
- {; content: "<p>Section 1 content</p>" },
246
- {; title: "Section 2"; content: "<p>Section 2 content</p>" },
247
- ],
248
- },
249
- })
663
+ These plugins handle template loading, asset copying, and file watching automatically.
664
+
665
+ ## TypeScript Support
250
666
 
667
+ The package includes full TypeScript definitions. All exported types are available for import:
668
+
669
+ ```ts
670
+ import type {
671
+ Parser,
672
+ RenderContext,
673
+ Renderer,
674
+ SourceInput,
675
+ TagNodeParse,
676
+ } from '@ui-doc/html-renderer'
251
677
  ```
678
+
679
+ ## Requirements
680
+
681
+ - Node.js >= 16.0.0
682
+ - `@ui-doc/core` (peer dependency)
683
+
684
+ ## License
685
+
686
+ See [LICENSE.md](../../LICENSE.md) for license information.