json-renderers 1.17.7 → 1.18.5

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.
@@ -0,0 +1,1140 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1">
7
+ <meta name="description"
8
+ content="Documentation for KeshavSoft json-renderers: its role, architecture, installation, examples, API, and development workflow.">
9
+ <title>json-renderers — Documentation</title>
10
+ <style>
11
+ :root {
12
+ --bg: #f5f7fb;
13
+ --surface: #fff;
14
+ --ink: #182230;
15
+ --muted: #5b6879;
16
+ --line: #e1e7ef;
17
+ --brand: #3858e9;
18
+ --brand2: #6c45d9;
19
+ --code: #101827;
20
+ --green: #15845b;
21
+ --soft: #eef2ff;
22
+ --shadow: 0 10px 32px rgba(23, 35, 70, .07)
23
+ }
24
+
25
+ * {
26
+ box-sizing: border-box
27
+ }
28
+
29
+ html {
30
+ scroll-behavior: smooth;
31
+ scroll-padding-top: 86px
32
+ }
33
+
34
+ body {
35
+ margin: 0;
36
+ background: var(--bg);
37
+ color: var(--ink);
38
+ font: 16px/1.65 Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif
39
+ }
40
+
41
+ a {
42
+ color: var(--brand);
43
+ text-decoration: none
44
+ }
45
+
46
+ a:hover {
47
+ text-decoration: underline
48
+ }
49
+
50
+ .topbar {
51
+ position: sticky;
52
+ top: 0;
53
+ z-index: 5;
54
+ background: rgba(255, 255, 255, .92);
55
+ backdrop-filter: blur(14px);
56
+ border-bottom: 1px solid var(--line)
57
+ }
58
+
59
+ .topbar-inner {
60
+ max-width: 1200px;
61
+ margin: auto;
62
+ padding: 12px 24px;
63
+ display: flex;
64
+ align-items: center;
65
+ justify-content: space-between;
66
+ gap: 16px
67
+ }
68
+
69
+ .brand {
70
+ display: flex;
71
+ align-items: center;
72
+ gap: 10px;
73
+ color: var(--ink);
74
+ font-weight: 800;
75
+ letter-spacing: -.03em
76
+ }
77
+
78
+ .logo {
79
+ display: grid;
80
+ place-items: center;
81
+ background: linear-gradient(135deg, var(--brand), var(--brand2));
82
+ color: white;
83
+ border-radius: 10px;
84
+ width: 36px;
85
+ height: 36px;
86
+ font-weight: 900
87
+ }
88
+
89
+ .top-links {
90
+ display: flex;
91
+ gap: 18px;
92
+ flex-wrap: wrap;
93
+ font-size: 13px;
94
+ font-weight: 650
95
+ }
96
+
97
+ .wrap {
98
+ max-width: 1200px;
99
+ margin: auto;
100
+ padding: 30px 24px 72px
101
+ }
102
+
103
+ .hero {
104
+ border-radius: 24px;
105
+ padding: clamp(28px, 5vw, 60px);
106
+ background: radial-gradient(circle at 85% 15%, rgba(255, 255, 255, .2), transparent 28%), linear-gradient(120deg, #1b2b65, #3c48bd 55%, #7547ce);
107
+ color: white;
108
+ box-shadow: var(--shadow);
109
+ overflow: hidden;
110
+ position: relative
111
+ }
112
+
113
+ .eyebrow {
114
+ text-transform: uppercase;
115
+ letter-spacing: .15em;
116
+ font-size: 12px;
117
+ font-weight: 800;
118
+ opacity: .8
119
+ }
120
+
121
+ .hero h1 {
122
+ font-size: clamp(34px, 5vw, 60px);
123
+ line-height: 1.08;
124
+ letter-spacing: -.055em;
125
+ max-width: 800px;
126
+ margin: 14px 0
127
+ }
128
+
129
+ .hero p {
130
+ font-size: clamp(16px, 2vw, 20px);
131
+ max-width: 760px;
132
+ color: #e9ecff
133
+ }
134
+
135
+ .hero-links {
136
+ display: flex;
137
+ gap: 12px;
138
+ flex-wrap: wrap;
139
+ margin-top: 26px
140
+ }
141
+
142
+ .hero-links a {
143
+ display: inline-flex;
144
+ padding: 10px 15px;
145
+ border-radius: 11px;
146
+ background: white;
147
+ color: #24316e;
148
+ font-weight: 750;
149
+ font-size: 14px
150
+ }
151
+
152
+ .hero-links a.secondary {
153
+ background: rgba(255, 255, 255, .12);
154
+ color: white;
155
+ border: 1px solid rgba(255, 255, 255, .35)
156
+ }
157
+
158
+ .layout {
159
+ display: grid;
160
+ grid-template-columns: 245px minmax(0, 1fr);
161
+ gap: 26px;
162
+ margin-top: 28px
163
+ }
164
+
165
+ .sidebar {
166
+ align-self: start;
167
+ position: sticky;
168
+ top: 76px;
169
+ background: var(--surface);
170
+ border: 1px solid var(--line);
171
+ border-radius: 16px;
172
+ padding: 18px;
173
+ box-shadow: var(--shadow)
174
+ }
175
+
176
+ .sidebar h3 {
177
+ font-size: 11px;
178
+ letter-spacing: .12em;
179
+ text-transform: uppercase;
180
+ color: var(--muted);
181
+ margin: 0 0 10px
182
+ }
183
+
184
+ .sidebar a {
185
+ display: block;
186
+ padding: 7px 9px;
187
+ border-radius: 8px;
188
+ color: #364254;
189
+ font-size: 13px
190
+ }
191
+
192
+ .sidebar a:hover {
193
+ background: var(--soft);
194
+ text-decoration: none;
195
+ color: var(--brand)
196
+ }
197
+
198
+ main {
199
+ min-width: 0
200
+ }
201
+
202
+ .section {
203
+ background: var(--surface);
204
+ border: 1px solid var(--line);
205
+ border-radius: 18px;
206
+ padding: clamp(20px, 3vw, 34px);
207
+ margin-bottom: 20px;
208
+ box-shadow: var(--shadow)
209
+ }
210
+
211
+ h2 {
212
+ font-size: clamp(24px, 3vw, 32px);
213
+ letter-spacing: -.04em;
214
+ line-height: 1.2;
215
+ margin: 0 0 14px
216
+ }
217
+
218
+ h3 {
219
+ font-size: 19px;
220
+ letter-spacing: -.02em;
221
+ margin: 24px 0 8px
222
+ }
223
+
224
+ p {
225
+ margin: 8px 0 14px
226
+ }
227
+
228
+ .muted {
229
+ color: var(--muted)
230
+ }
231
+
232
+ .lead {
233
+ font-size: 18px;
234
+ color: #435166
235
+ }
236
+
237
+ .pill {
238
+ display: inline-block;
239
+ padding: 4px 9px;
240
+ background: #edf2ff;
241
+ color: #3448bb;
242
+ border-radius: 999px;
243
+ font-size: 12px;
244
+ font-weight: 750;
245
+ margin: 3px 4px 3px 0
246
+ }
247
+
248
+ .grid3 {
249
+ display: grid;
250
+ grid-template-columns: repeat(3, minmax(0, 1fr));
251
+ gap: 12px;
252
+ margin-top: 18px
253
+ }
254
+
255
+ .mini-card {
256
+ border: 1px solid var(--line);
257
+ border-radius: 13px;
258
+ padding: 16px;
259
+ background: #fcfdff
260
+ }
261
+
262
+ .mini-card strong {
263
+ display: block;
264
+ margin-bottom: 5px
265
+ }
266
+
267
+ .mini-card p {
268
+ margin: 0;
269
+ color: var(--muted);
270
+ font-size: 14px
271
+ }
272
+
273
+ .pipeline {
274
+ display: grid;
275
+ grid-template-columns: repeat(4, minmax(0, 1fr));
276
+ gap: 10px;
277
+ margin: 22px 0
278
+ }
279
+
280
+ .step {
281
+ background: #f8f9ff;
282
+ border: 1px solid #dfe4ff;
283
+ border-radius: 13px;
284
+ padding: 15px;
285
+ position: relative
286
+ }
287
+
288
+ .step:not(:last-child):after {
289
+ content: '→';
290
+ position: absolute;
291
+ right: -12px;
292
+ top: 38%;
293
+ z-index: 1;
294
+ color: var(--brand);
295
+ font-weight: 900;
296
+ font-size: 19px
297
+ }
298
+
299
+ .step .num {
300
+ font-size: 11px;
301
+ font-weight: 800;
302
+ color: var(--brand);
303
+ text-transform: uppercase;
304
+ letter-spacing: .08em
305
+ }
306
+
307
+ .step strong {
308
+ display: block;
309
+ margin: 6px 0
310
+ }
311
+
312
+ .step p {
313
+ font-size: 13px;
314
+ color: var(--muted);
315
+ margin: 0
316
+ }
317
+
318
+ .note {
319
+ border-left: 4px solid var(--brand);
320
+ padding: 13px 16px;
321
+ background: #f3f5ff;
322
+ border-radius: 0 10px 10px 0;
323
+ margin: 16px 0
324
+ }
325
+
326
+ .note strong {
327
+ display: block;
328
+ margin-bottom: 3px
329
+ }
330
+
331
+ .codehead {
332
+ display: flex;
333
+ justify-content: space-between;
334
+ align-items: center;
335
+ gap: 12px;
336
+ color: #c8d3e8;
337
+ font-size: 12px;
338
+ font-weight: 750;
339
+ padding: 10px 14px;
340
+ background: #1b2638;
341
+ border-radius: 11px 11px 0 0
342
+ }
343
+
344
+ .codewrap {
345
+ position: relative;
346
+ margin: 12px 0 20px
347
+ }
348
+
349
+ pre {
350
+ margin: 0;
351
+ background: var(--code);
352
+ color: #e4ebf7;
353
+ padding: 18px;
354
+ overflow: auto;
355
+ border-radius: 0 0 11px 11px;
356
+ font: 13px/1.65 ui-monospace, SFMono-Regular, Consolas, monospace;
357
+ tab-size: 2
358
+ }
359
+
360
+ code {
361
+ font-family: ui-monospace, SFMono-Regular, Consolas, monospace
362
+ }
363
+
364
+ .inline-code {
365
+ background: #edf1f7;
366
+ padding: 2px 5px;
367
+ border-radius: 5px;
368
+ font-size: .9em
369
+ }
370
+
371
+ .copy {
372
+ border: 1px solid #45536a;
373
+ background: #26344b;
374
+ color: #fff;
375
+ border-radius: 6px;
376
+ padding: 5px 9px;
377
+ font-size: 11px;
378
+ cursor: pointer
379
+ }
380
+
381
+ .copy:hover {
382
+ background: #374967
383
+ }
384
+
385
+ .table-scroll {
386
+ overflow-x: auto;
387
+ margin: 14px 0
388
+ }
389
+
390
+ table {
391
+ width: 100%;
392
+ border-collapse: collapse;
393
+ font-size: 14px;
394
+ min-width: 560px
395
+ }
396
+
397
+ th,
398
+ td {
399
+ border-bottom: 1px solid var(--line);
400
+ text-align: left;
401
+ vertical-align: top;
402
+ padding: 11px 12px
403
+ }
404
+
405
+ th {
406
+ background: #f7f9fc;
407
+ color: #37455a;
408
+ font-size: 12px;
409
+ text-transform: uppercase;
410
+ letter-spacing: .04em
411
+ }
412
+
413
+ td:first-child {
414
+ font-weight: 700
415
+ }
416
+
417
+ .comparison {
418
+ display: grid;
419
+ grid-template-columns: 1fr 1fr;
420
+ gap: 12px
421
+ }
422
+
423
+ .compare-card {
424
+ border: 1px solid var(--line);
425
+ border-radius: 13px;
426
+ padding: 18px
427
+ }
428
+
429
+ .compare-card h3 {
430
+ margin: 0 0 8px
431
+ }
432
+
433
+ .compare-card ul {
434
+ padding-left: 18px;
435
+ margin: 8px 0
436
+ }
437
+
438
+ .compare-card li {
439
+ margin: 5px 0
440
+ }
441
+
442
+ .flow-list {
443
+ counter-reset: flow;
444
+ list-style: none;
445
+ padding: 0
446
+ }
447
+
448
+ .flow-list li {
449
+ counter-increment: flow;
450
+ display: flex;
451
+ gap: 12px;
452
+ margin: 12px 0
453
+ }
454
+
455
+ .flow-list li:before {
456
+ content: counter(flow);
457
+ width: 27px;
458
+ height: 27px;
459
+ flex: 0 0 27px;
460
+ display: grid;
461
+ place-items: center;
462
+ background: var(--soft);
463
+ color: var(--brand);
464
+ font-weight: 800;
465
+ border-radius: 8px;
466
+ font-size: 12px
467
+ }
468
+
469
+ .footer {
470
+ color: var(--muted);
471
+ text-align: center;
472
+ font-size: 13px;
473
+ padding: 18px
474
+ }
475
+
476
+ .searchbox {
477
+ width: 100%;
478
+ padding: 10px 12px;
479
+ border: 1px solid var(--line);
480
+ border-radius: 9px;
481
+ margin-bottom: 12px;
482
+ font: inherit;
483
+ font-size: 13px
484
+ }
485
+
486
+ .hidden {
487
+ display: none !important
488
+ }
489
+
490
+ @media(max-width:850px) {
491
+ .layout {
492
+ grid-template-columns: 1fr
493
+ }
494
+
495
+ .sidebar {
496
+ position: static;
497
+ display: grid;
498
+ grid-template-columns: 1fr 1fr;
499
+ gap: 0 8px
500
+ }
501
+
502
+ .sidebar h3,
503
+ .searchbox {
504
+ grid-column: 1/-1
505
+ }
506
+
507
+ .grid3 {
508
+ grid-template-columns: 1fr
509
+ }
510
+
511
+ .pipeline {
512
+ grid-template-columns: 1fr 1fr
513
+ }
514
+
515
+ .step:not(:last-child):after {
516
+ display: none
517
+ }
518
+
519
+ .top-links {
520
+ display: none
521
+ }
522
+ }
523
+
524
+ @media(max-width:520px) {
525
+ .wrap {
526
+ padding: 16px 12px 42px
527
+ }
528
+
529
+ .topbar-inner {
530
+ padding: 10px 14px
531
+ }
532
+
533
+ .hero {
534
+ border-radius: 18px
535
+ }
536
+
537
+ .pipeline,
538
+ .comparison {
539
+ grid-template-columns: 1fr
540
+ }
541
+
542
+ .section {
543
+ padding: 20px 16px
544
+ }
545
+
546
+ .sidebar {
547
+ grid-template-columns: 1fr 1fr
548
+ }
549
+ }
550
+ </style>
551
+ </head>
552
+
553
+ <body>
554
+ <header class="topbar">
555
+ <div class="wrap" id="top">
556
+ <section class="hero">
557
+ <div class="eyebrow">KeshavSoft · Browser DOM Runtime</div>
558
+ <h1>Render JSON-driven UI into the browser.</h1>
559
+ <p>A practical guide to <strong>json-renderers</strong> — the runtime that coordinates UI-spec generation, DOM
560
+ creation, and mounting rendered components into a page.</p>
561
+ <div class="hero-links">
562
+ <a href="simpleDoc.html">🌱 Read Simple Guide ↗</a>
563
+ <a class="secondary" href="index.html">📚 SubDoc Hub ↗</a>
564
+ <a class="secondary" href="../index.html">🏠 Main Docs &amp; Workbench ↗</a>
565
+ <a class="secondary" href="https://github.com/keshavsoft/json-renderers" target="_blank" rel="noreferrer">View
566
+ repository ↗</a>
567
+ </div>
568
+ </section>
569
+
570
+ <div class="layout">
571
+ <aside class="sidebar">
572
+ <div style="margin-bottom:12px;padding-bottom:10px;border-bottom:1px solid var(--line);">
573
+ <h3 style="margin-bottom:6px;">Documentation Hub</h3>
574
+ <a href="../index.html" style="font-weight:600;color:var(--ink);">🏠 Main Docs</a>
575
+ <a href="index.html" style="font-weight:600;color:var(--brand);">📚 SubDoc Hub</a>
576
+ <a href="simpleDoc.html" style="font-weight:600;color:#059669;">🌱 Simple Guide</a>
577
+ <a href="advanceDoc.html" style="font-weight:750;background:var(--soft);color:var(--brand);">🚀 Advanced
578
+ Guide</a>
579
+ </div>
580
+ <input class="searchbox" id="navSearch" placeholder="Filter sections…"
581
+ aria-label="Filter documentation sections">
582
+ <h3>Section Index</h3>
583
+ <a class="doc-section-link" href="#overview">What it does</a>
584
+ <a class="doc-section-link" href="#simple-story">Simple story</a>
585
+ <a class="doc-section-link" href="#architecture">Architecture & pipeline</a>
586
+ <a class="doc-section-link" href="#features">Features</a>
587
+ <a class="doc-section-link" href="#installation">Installation</a>
588
+ <a class="doc-section-link" href="#quick-start">Quick start</a>
589
+ <a class="doc-section-link" href="#api">API reference</a>
590
+ <a class="doc-section-link" href="#comparison">Related repository</a>
591
+ <a class="doc-section-link" href="#structure">Project structure</a>
592
+ <a class="doc-section-link" href="#development">Development & build</a>
593
+ <a class="doc-section-link" href="#references">Official references</a>
594
+ </aside>
595
+
596
+ <main>
597
+ <section class="section" id="overview">
598
+ <h2>1. What is json-renderers?</h2>
599
+ <p class="lead"><strong>json-renderers</strong> is the browser runtime layer in the KeshavSoft declarative
600
+ UI
601
+ ecosystem. It accepts render configuration, obtains a JSON description of the requested component, asks
602
+ <span class="inline-code">@keshavsoft/json-to-tag</span> to create DOM nodes, and mounts the result in the
603
+ requested browser container.
604
+ </p>
605
+ <p>It is an orchestration layer rather than the specification compiler itself. The component structure is
606
+ prepared upstream by <span class="inline-code">json-renderers-build</span>; actual element construction is
607
+ delegated to <span class="inline-code">@keshavsoft/json-to-tag</span>.</p>
608
+ <div class="grid3">
609
+ <div class="mini-card"><span class="pill">Input</span><strong>Data + options</strong>
610
+ <p>Rows, option values, component type, target element ID, and optional columns.</p>
611
+ </div>
612
+ <div class="mini-card"><span class="pill">Coordination</span><strong>Build the UI spec</strong>
613
+ <p>The builder assembles the declarative JSON structure for the selected component.</p>
614
+ </div>
615
+ <div class="mini-card"><span class="pill">Output</span><strong>Mounted DOM</strong>
616
+ <p>Real browser elements appear inside the target container.</p>
617
+ </div>
618
+ </div>
619
+ <div class="note"><strong>Key distinction</strong>json-renderers does not hand-code each table or dropdown
620
+ DOM
621
+ tree. It coordinates the pipeline that converts a declarative specification into mounted browser elements.
622
+ </div>
623
+ </section>
624
+
625
+ <section class="section" id="simple-story">
626
+ <h2>2. A simple story everyone can understand</h2>
627
+ <p class="lead">Imagine we are building a house. The same idea helps explain how a UI becomes real HTML on a
628
+ webpage.</p>
629
+ <div class="grid3">
630
+ <div class="mini-card"><span class="pill">1 · The architect</span><strong>json-renderers-build</strong>
631
+ <p>The architect prepares a blueprint. Here, it prepares the JSON structure in the format that the next
632
+ tool expects.</p>
633
+ </div>
634
+ <div class="mini-card"><span class="pill">2 · The construction worker</span><strong>json-to-tag</strong>
635
+ <p>The worker reads the blueprint and builds the actual parts. Here, it converts the JSON specification
636
+ into real HTML DOM elements.</p>
637
+ </div>
638
+ <div class="mini-card"><span class="pill">3 · The site manager</span><strong>json-renderers</strong>
639
+ <p>The manager takes the built parts to the right place. Here, it mounts the created elements inside the
640
+ target container on the webpage.</p>
641
+ </div>
642
+ </div>
643
+ <h3>Example: displaying a student table</h3>
644
+ <ol class="flow-list">
645
+ <li>
646
+ <div><strong>We provide student data.</strong><br><span class="muted">For example: student names and
647
+ their
648
+ cities, plus the ID of the HTML container.</span></div>
649
+ </li>
650
+ <li>
651
+ <div><strong>The architect prepares the blueprint.</strong><br><span
652
+ class="muted"><code>json-renderers-build</code> produces a JSON specification describing the
653
+ table.</span></div>
654
+ </li>
655
+ <li>
656
+ <div><strong>The construction worker builds the table elements.</strong><br><span
657
+ class="muted"><code>json-to-tag</code> reads that specification and creates the HTML DOM
658
+ elements.</span></div>
659
+ </li>
660
+ <li>
661
+ <div><strong>The site manager puts the table in place.</strong><br><span
662
+ class="muted"><code>json-renderers</code> mounts the result inside the target HTML container, so the
663
+ user can see the table.</span></div>
664
+ </li>
665
+ </ol>
666
+ <div class="note"><strong>Easy sentence to remember</strong><code>json-renderers-build</code> prepares the
667
+ blueprint, <code>json-to-tag</code> builds the actual DOM elements, and <code>json-renderers</code> places
668
+ them on the webpage.</div>
669
+ </section>
670
+
671
+ <section class="section" id="architecture">
672
+ <h2>3. Architecture and rendering pipeline</h2>
673
+ <p>The README describes the flow from application inputs to the final browser DOM as a staged pipeline:</p>
674
+ <div class="pipeline">
675
+ <div class="step"><span class="num">Step 01</span><strong>Application data</strong>
676
+ <p>Pass a component type, data, columns, and target HTML ID.</p>
677
+ </div>
678
+ <div class="step"><span class="num">Step 02</span><strong>json-renderers-build</strong>
679
+ <p>Builds a declarative JSON specification for the component.</p>
680
+ </div>
681
+ <div class="step"><span class="num">Step 03</span><strong>json-to-tag</strong>
682
+ <p>Converts the specification into browser DOM nodes.</p>
683
+ </div>
684
+ <div class="step"><span class="num">Step 04</span><strong>json-renderers</strong>
685
+ <p>Mounts the result into the specified container.</p>
686
+ </div>
687
+ </div>
688
+ <ol class="flow-list">
689
+ <li>
690
+ <div><strong>The application calls the render function.</strong><br><span class="muted">The
691
+ configuration
692
+ includes values such as <code>type</code>, <code>targetHtmlId</code>, <code>data</code>, and
693
+ optionally <code>columns</code>.</span></div>
694
+ </li>
695
+ <li>
696
+ <div><strong>The builder prepares the component specification.</strong><br><span class="muted">The
697
+ <code>json-renderers-build</code> package combines the component blueprint with the supplied data
698
+ and
699
+ returns a JSON spec.</span></div>
700
+ </li>
701
+ <li>
702
+ <div><strong>The JSON spec is converted into DOM.</strong><br><span
703
+ class="muted"><code>@keshavsoft/json-to-tag</code> constructs the relevant HTML elements from that
704
+ specification.</span></div>
705
+ </li>
706
+ <li>
707
+ <div><strong>The runtime mounts the generated elements.</strong><br><span class="muted">The renderer
708
+ resolves the destination element and applies its mounting behavior.</span></div>
709
+ </li>
710
+ </ol>
711
+ <div class="note"><strong>Remember this for a technical
712
+ explanation</strong><code>json-renderers-build</code>
713
+ prepares the structure, <code>json-to-tag</code> creates the elements, and <code>json-renderers</code>
714
+ coordinates and mounts the result.</div>
715
+ </section>
716
+
717
+ <section class="section" id="features">
718
+ <h2>3. Main features</h2>
719
+ <div class="grid3">
720
+ <div class="mini-card"><strong>Table rendering</strong>
721
+ <p>Creates a table with headers and rows from the supplied data. The README documents Bootstrap table
722
+ classes.</p>
723
+ </div>
724
+ <div class="mini-card"><strong>Select dropdown</strong>
725
+ <p>Builds a select element and populates it with the provided options.</p>
726
+ </div>
727
+ <div class="mini-card"><strong>Existing select options</strong>
728
+ <p>Can add option elements to an already-existing select element.</p>
729
+ </div>
730
+ <div class="mini-card"><strong>Flexible mounting</strong>
731
+ <p>Supports default content replacement and a <code>prepend</code> option.</p>
732
+ </div>
733
+ <div class="mini-card"><strong>Browser global</strong>
734
+ <p>The README documents a browser bundle that registers under <code>window.ks.jsonRenderers</code>.</p>
735
+ </div>
736
+ <div class="mini-card"><strong>ES module / npm</strong>
737
+ <p>Can be used through the package or a browser ES module bundle.</p>
738
+ </div>
739
+ </div>
740
+ <p class="muted" style="margin-top:15px">Documented renderer types: <code>table</code>, <code>select</code>,
741
+ and <code>selectOptionsOnly</code>.</p>
742
+ </section>
743
+
744
+ <section class="section" id="installation">
745
+ <h2>4. Installation</h2>
746
+ <h3>Option A — npm</h3>
747
+ <p>Install the package in your JavaScript project:</p>
748
+ <div class="codewrap">
749
+ <div class="codehead"><span>Terminal</span><button class="copy"
750
+ data-copy="npm install json-renderers">Copy</button></div>
751
+ <pre><code>npm install json-renderers</code></pre>
752
+ </div>
753
+ <p>Then import the default render function in your JavaScript module:</p>
754
+ <div class="codewrap">
755
+ <div class="codehead"><span>JavaScript</span><button class="copy"
756
+ data-copy='import render from "json-renderers";'>Copy</button></div>
757
+ <pre><code>import render from "json-renderers";</code></pre>
758
+ </div>
759
+ <h3>Option B — browser ES module bundle</h3>
760
+ <p>The README documents loading the v13 bundle from jsDelivr:</p>
761
+ <div class="codewrap">
762
+ <div class="codehead"><span>HTML</span><button class="copy"
763
+ data-copy='<script type="module" src="https://cdn.jsdelivr.net/gh/keshavsoft/json-renderers@main/docs/dist/v13/min.js"></script>'>Copy</button>
764
+ </div>
765
+ <pre><code>&lt;script type="module" src="https://cdn.jsdelivr.net/gh/keshavsoft/json-renderers@main/docs/dist/v13/min.js"&gt;&lt;/script&gt;</code></pre>
766
+ </div>
767
+ <p>According to the README, the browser bundle registers a global API at
768
+ <code>window.ks.jsonRenderers</code>,
769
+ including <code>renderToDom</code>.</p>
770
+ <div class="note"><strong>Choose one setup</strong>Use npm imports in a bundled application, or load the
771
+ documented browser module in a page. Check the live README before publishing a project to confirm the
772
+ currently recommended bundle/version.</div>
773
+ </section>
774
+
775
+ <section class="section" id="quick-start">
776
+ <h2>5. Quick start examples</h2>
777
+ <p>Each example needs a destination element in the HTML and a call to <code>render</code> with the
778
+ corresponding options. The snippets below follow the examples documented in the repository README.</p>
779
+ <h3>Example A — render a table</h3>
780
+ <div class="codewrap">
781
+ <div class="codehead"><span>HTML</span><button class="copy"
782
+ data-copy='<div id="table-container"></div>'>Copy</button></div>
783
+ <pre><code>&lt;div id="table-container"&gt;&lt;/div&gt;</code></pre>
784
+ </div>
785
+ <div class="codewrap">
786
+ <div class="codehead"><span>JavaScript</span><button class="copy"
787
+ data-copy='import render from "json-renderers";\n\nconst records = [\n { id: 101, name: "Alpha Enterprise", city: "Hyderabad" },\n { id: 102, name: "Beta Logistics", city: "Bengaluru" }\n];\n\nrender({\n type: "table",\n targetHtmlId: "table-container",\n data: records,\n columns: ["Name", "City"]\n});'>Copy</button>
788
+ </div>
789
+ <pre><code>import render from "json-renderers";
790
+
791
+ const records = [
792
+ { id: 101, name: "Alpha Enterprise", city: "Hyderabad" },
793
+ { id: 102, name: "Beta Logistics", city: "Bengaluru" }
794
+ ];
795
+
796
+ render({
797
+ type: "table",
798
+ targetHtmlId: "table-container",
799
+ data: records,
800
+ columns: ["Name", "City"]
801
+ });</code></pre>
802
+ </div>
803
+ <p class="muted">Expected result: a table is mounted inside the <code>#table-container</code> element,
804
+ showing
805
+ the selected columns and data rows.</p>
806
+ <h3>Example B — render a select dropdown</h3>
807
+ <div class="codewrap">
808
+ <div class="codehead"><span>HTML</span><button class="copy"
809
+ data-copy='<div id="dropdown-container"></div>'>Copy</button></div>
810
+ <pre><code>&lt;div id="dropdown-container"&gt;&lt;/div&gt;</code></pre>
811
+ </div>
812
+ <div class="codewrap">
813
+ <div class="codehead"><span>JavaScript</span><button class="copy"
814
+ data-copy='import render from "json-renderers";\n\nrender({\n type: "select",\n targetHtmlId: "dropdown-container",\n data: ["Account Receivable", "Account Payable", "Sales Revenue"]\n});'>Copy</button>
815
+ </div>
816
+ <pre><code>import render from "json-renderers";
817
+
818
+ render({
819
+ type: "select",
820
+ targetHtmlId: "dropdown-container",
821
+ data: ["Account Receivable", "Account Payable", "Sales Revenue"]
822
+ });</code></pre>
823
+ </div>
824
+ <p class="muted">Expected result: a select element is generated with the supplied values as options.</p>
825
+ <h3>Example C — add options to an existing select</h3>
826
+ <div class="codewrap">
827
+ <div class="codehead"><span>HTML</span><button class="copy"
828
+ data-copy='<select id="user-role-select" class="form-select">\n <option value="" disabled selected>Select Role...</option>\n</select>'>Copy</button>
829
+ </div>
830
+ <pre><code>&lt;select id="user-role-select" class="form-select"&gt;
831
+ &lt;option value="" disabled selected&gt;Select Role...&lt;/option&gt;
832
+ &lt;/select&gt;</code></pre>
833
+ </div>
834
+ <div class="codewrap">
835
+ <div class="codehead"><span>JavaScript</span><button class="copy"
836
+ data-copy='import render from "json-renderers";\n\nrender({\n type: "selectOptionsOnly",\n targetHtmlId: "user-role-select",\n data: ["Administrator", "Editor", "Viewer"]\n});'>Copy</button>
837
+ </div>
838
+ <pre><code>import render from "json-renderers";
839
+
840
+ render({
841
+ type: "selectOptionsOnly",
842
+ targetHtmlId: "user-role-select",
843
+ data: ["Administrator", "Editor", "Viewer"]
844
+ });</code></pre>
845
+ </div>
846
+ <p class="muted">Expected result: options for Administrator, Editor, and Viewer are added to the existing
847
+ select control.</p>
848
+ </section>
849
+
850
+ <section class="section" id="api">
851
+ <h2>6. API reference</h2>
852
+ <p>The README documents the default export as a render function receiving one options object.</p>
853
+ <div class="codewrap">
854
+ <div class="codehead"><span>Function signature</span><button class="copy"
855
+ data-copy='render({ type, targetHtmlId, data, columns, appendPosition, showLog });'>Copy</button>
856
+ </div>
857
+ <pre><code>render({
858
+ type = "table",
859
+ targetHtmlId,
860
+ data,
861
+ columns,
862
+ appendPosition,
863
+ showLog = false
864
+ });</code></pre>
865
+ </div>
866
+ <div class="table-scroll">
867
+ <table>
868
+ <thead>
869
+ <tr>
870
+ <th>Parameter</th>
871
+ <th>Type</th>
872
+ <th>Default</th>
873
+ <th>Purpose</th>
874
+ </tr>
875
+ </thead>
876
+ <tbody>
877
+ <tr>
878
+ <td><code>type</code></td>
879
+ <td>String</td>
880
+ <td><code>"table"</code></td>
881
+ <td>Selects the renderer: <code>table</code>, <code>select</code>, or
882
+ <code>selectOptionsOnly</code>.
883
+ </td>
884
+ </tr>
885
+ <tr>
886
+ <td><code>targetHtmlId</code></td>
887
+ <td>String</td>
888
+ <td>Not set</td>
889
+ <td>ID of the destination element resolved through <code>document.getElementById(...)</code>.</td>
890
+ </tr>
891
+ <tr>
892
+ <td><code>data</code></td>
893
+ <td>Array</td>
894
+ <td><code>[]</code></td>
895
+ <td>Row objects for a table; string values for select/dropdown option renderers.</td>
896
+ </tr>
897
+ <tr>
898
+ <td><code>columns</code></td>
899
+ <td>Array</td>
900
+ <td>Not set</td>
901
+ <td>Table column headers; the README describes strings or objects such as
902
+ <code>{ title: "Name" }</code>.
903
+ </td>
904
+ </tr>
905
+ <tr>
906
+ <td><code>appendPosition</code></td>
907
+ <td>String</td>
908
+ <td>Not set</td>
909
+ <td>Use <code>"prepend"</code> to prepend content. Otherwise, the documented behavior replaces
910
+ existing container content.</td>
911
+ </tr>
912
+ <tr>
913
+ <td><code>showLog</code></td>
914
+ <td>Boolean</td>
915
+ <td><code>false</code></td>
916
+ <td>Enables debug logging during rendering.</td>
917
+ </tr>
918
+ </tbody>
919
+ </table>
920
+ </div>
921
+ <h3>Return value</h3>
922
+ <p>The README describes the return value as an <code>HTMLElement</code> representing the mounted DOM
923
+ container.</p>
924
+ <div class="note"><strong>Usage check</strong>Make sure the element named by <code>targetHtmlId</code>
925
+ already
926
+ exists in the page before calling the render function. The parameter is an element ID, not a CSS selector.
927
+ </div>
928
+ </section>
929
+
930
+ <section class="section" id="comparison">
931
+ <h2>7. How it differs from json-renderers-build</h2>
932
+ <p>These packages work together, but they have different responsibilities.</p>
933
+ <div class="comparison">
934
+ <div class="compare-card"><span class="pill">Specification stage</span>
935
+ <h3><a href="https://github.com/keshavsoft/json-renderers-build" target="_blank"
936
+ rel="noreferrer">json-renderers-build ↗</a></h3>
937
+ <ul>
938
+ <li>Prepares the JSON component specification.</li>
939
+ <li>Combines component blueprints with input data and options.</li>
940
+ <li>Produces a declarative specification, rather than directly mounting DOM.</li>
941
+ </ul>
942
+ </div>
943
+ <div class="compare-card"><span class="pill">Browser runtime stage</span>
944
+ <h3>json-renderers</h3>
945
+ <ul>
946
+ <li>Coordinates the full render path.</li>
947
+ <li>Passes the spec to <code>json-to-tag</code> for element construction.</li>
948
+ <li>Mounts the resulting nodes into the target browser container.</li>
949
+ </ul>
950
+ </div>
951
+ </div>
952
+ <div class="table-scroll">
953
+ <table>
954
+ <thead>
955
+ <tr>
956
+ <th>Aspect</th>
957
+ <th>json-renderers-build</th>
958
+ <th>json-renderers</th>
959
+ </tr>
960
+ </thead>
961
+ <tbody>
962
+ <tr>
963
+ <td>Primary job</td>
964
+ <td>Build UI specification</td>
965
+ <td>Coordinate and mount rendered UI</td>
966
+ </tr>
967
+ <tr>
968
+ <td>Output / result</td>
969
+ <td>Declarative JSON spec</td>
970
+ <td>Rendered DOM mounted in a page</td>
971
+ </tr>
972
+ <tr>
973
+ <td>DOM mounting</td>
974
+ <td>Not its main responsibility</td>
975
+ <td>Core runtime responsibility</td>
976
+ </tr>
977
+ <tr>
978
+ <td>Typical use</td>
979
+ <td>Build custom or reusable specifications</td>
980
+ <td>Render components in browser applications</td>
981
+ </tr>
982
+ </tbody>
983
+ </table>
984
+ </div>
985
+ </section>
986
+
987
+ <section class="section" id="structure">
988
+ <h2>8. Project structure</h2>
989
+ <p>The README describes the repository as organized around source runtime code, browser documentation/build
990
+ output, and runnable samples.</p>
991
+ <div class="codewrap">
992
+ <div class="codehead"><span>Repository map (from README)</span><button class="copy"
993
+ data-copy='json-renderers/\n├── docs/\n│ ├── dist/\n│ │ ├── min.js\n│ │ └── v13/min.js\n│ └── index.html\n├── samples/\n│ ├── table/\n│ ├── select/\n│ └── selectOptionsOnly/\n├── src/\n│ ├── index.js\n│ └── v13/\n│ ├── buildSpec/\n│ ├── meta.js\n│ ├── registerGlobal.js\n│ └── index.js\n├── package.json\n├── vite.config.js\n└── README.md'>Copy</button>
994
+ </div>
995
+ <pre><code>json-renderers/
996
+ ├── docs/ # Documentation and distribution
997
+ │ ├── dist/ # Built browser bundles
998
+ │ │ ├── min.js
999
+ │ │ └── v13/min.js
1000
+ │ └── index.html # Docs and interactive workbench
1001
+ ├── samples/ # Browser examples
1002
+ │ ├── table/
1003
+ │ ├── select/
1004
+ │ └── selectOptionsOnly/
1005
+ ├── src/ # Source code
1006
+ │ ├── index.js # Package entry
1007
+ │ └── v13/ # Runtime implementation
1008
+ │ ├── buildSpec/
1009
+ │ ├── meta.js
1010
+ │ ├── registerGlobal.js
1011
+ │ └── index.js
1012
+ ├── package.json
1013
+ ├── vite.config.js
1014
+ └── README.md</code></pre>
1015
+ </div>
1016
+ <p class="muted">File paths and bundle names can change over time; use the repository’s current default
1017
+ branch
1018
+ as the source of truth.</p>
1019
+ </section>
1020
+
1021
+ <section class="section" id="development">
1022
+ <h2>9. Development and build</h2>
1023
+ <p>To run the project locally, the README documents the following commands:</p>
1024
+ <div class="codewrap">
1025
+ <div class="codehead"><span>Terminal</span><button class="copy"
1026
+ data-copy='npm install\nnpm run dev\nnpm run build'>Copy</button></div>
1027
+ <pre><code># Install dependencies
1028
+ npm install
1029
+
1030
+ # Start the Vite development server
1031
+ npm run dev
1032
+
1033
+ # Build production bundles
1034
+ npm run build</code></pre>
1035
+ </div>
1036
+ <p>Use <code>npm run dev</code> to work with the project locally, then <code>npm run build</code> to build
1037
+ the
1038
+ production bundles described in the README. Consult <code>package.json</code> for the exact scripts in the
1039
+ current checkout.</p>
1040
+ <h3>Practical troubleshooting</h3>
1041
+ <ul>
1042
+ <li><strong>Nothing renders:</strong> confirm the target container exists and that
1043
+ <code>targetHtmlId</code>
1044
+ matches its ID exactly.</li>
1045
+ <li><strong>Wrong component appears:</strong> check the <code>type</code> value and the shape of
1046
+ <code>data</code>.
1047
+ </li>
1048
+ <li><strong>Table columns are missing:</strong> verify the <code>columns</code> array matches the intended
1049
+ record properties/headers.</li>
1050
+ <li><strong>Unexpectedly replaced content:</strong> review <code>appendPosition</code>; the README
1051
+ describes
1052
+ replacement as the default and <code>prepend</code> as an alternative.</li>
1053
+ </ul>
1054
+ </section>
1055
+
1056
+ <section class="section" id="references">
1057
+ <h2>10. Official links and references</h2>
1058
+ <p>This guide is based on the repository’s README and documentation links available when the page was
1059
+ prepared. Check these sources for the latest implementation details.</p>
1060
+ <div class="grid3">
1061
+ <div class="mini-card"><strong>GitHub repository</strong>
1062
+ <p><a href="https://github.com/keshavsoft/json-renderers" target="_blank" rel="noreferrer">Source code
1063
+ and
1064
+ README ↗</a></p>
1065
+ </div>
1066
+ <div class="mini-card"><strong>Live documentation</strong>
1067
+ <p><a href="https://keshavsoft.github.io/json-renderers/" target="_blank" rel="noreferrer">Docs and
1068
+ interactive workbench ↗</a></p>
1069
+ </div>
1070
+ <div class="mini-card"><strong>Table rendering guide</strong>
1071
+ <p><a href="https://keshavsoft.github.io/json-renderers/table/index.html" target="_blank"
1072
+ rel="noreferrer">HTML table process & architecture ↗</a></p>
1073
+ </div>
1074
+ <div class="mini-card"><strong>Select dropdown guide</strong>
1075
+ <p><a href="https://keshavsoft.github.io/json-renderers/aboutSelect.html" target="_blank"
1076
+ rel="noreferrer">Select component guide ↗</a></p>
1077
+ </div>
1078
+ <div class="mini-card"><strong>Builder repository</strong>
1079
+ <p><a href="https://github.com/keshavsoft/json-renderers-build" target="_blank"
1080
+ rel="noreferrer">json-renderers-build ↗</a></p>
1081
+ </div>
1082
+ <div class="mini-card"><strong>DOM conversion package</strong>
1083
+ <p><a href="https://github.com/keshavsoft/json-to-tag" target="_blank" rel="noreferrer">json-to-tag
1084
+ ↗</a>
1085
+ </p>
1086
+ </div>
1087
+ </div>
1088
+ <p><span class="pill">License</span> The README identifies the project as MIT-licensed. See the repository’s
1089
+ current LICENSE file for the license text.</p>
1090
+ </section>
1091
+ <div class="section" style="background:#f0f7ff;border-color:#bfdbfe;">
1092
+ <h3 style="margin-top:0;color:#1e40af;">Explore More Documentation</h3>
1093
+ <p style="margin:6px 0 16px;color:#334155;font-size:14px;">Looking for a quick conceptual model or
1094
+ interactive
1095
+ live playground?</p>
1096
+ <div style="display:flex;gap:12px;flex-wrap:wrap;">
1097
+ <a href="simpleDoc.html"
1098
+ style="display:inline-flex;align-items:center;gap:6px;padding:9px 15px;border-radius:10px;background:#059669;color:white;font-weight:600;font-size:13px;text-decoration:none;">🌱
1099
+ Read Simple Guide</a>
1100
+ <a href="index.html"
1101
+ style="display:inline-flex;align-items:center;gap:6px;padding:9px 15px;border-radius:10px;background:var(--brand);color:white;font-weight:600;font-size:13px;text-decoration:none;">📚
1102
+ SubDoc Hub</a>
1103
+ <a href="../index.html"
1104
+ style="display:inline-flex;align-items:center;gap:6px;padding:9px 15px;border-radius:10px;background:#1e293b;color:white;font-weight:600;font-size:13px;text-decoration:none;">🏠
1105
+ Main Docs &amp; Workbench</a>
1106
+ </div>
1107
+ </div>
1108
+ <div class="footer">Documentation prepared from the public README for <a
1109
+ href="https://github.com/keshavsoft/json-renderers" target="_blank"
1110
+ rel="noreferrer">keshavsoft/json-renderers</a>.</div>
1111
+ </main>
1112
+ </div>
1113
+ </div>
1114
+ <script>
1115
+ // Copy buttons provide one-click copying for the examples.
1116
+ document.querySelectorAll('.copy').forEach(button => {
1117
+ button.addEventListener('click', async () => {
1118
+ const text = button.dataset.copy || '';
1119
+ try {
1120
+ await navigator.clipboard.writeText(text.replace(/\\n/g, '\n'));
1121
+ const previous = button.textContent;
1122
+ button.textContent = 'Copied!';
1123
+ setTimeout(() => button.textContent = previous, 1200);
1124
+ } catch {
1125
+ button.textContent = 'Select code';
1126
+ const pre = button.closest('.codewrap')?.querySelector('pre');
1127
+ if (pre) { const range = document.createRange(); range.selectNodeContents(pre); const selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(range); }
1128
+ }
1129
+ });
1130
+ });
1131
+ // Filter the sidebar section links by their visible text.
1132
+ const search = document.getElementById('navSearch');
1133
+ search.addEventListener('input', () => {
1134
+ const q = search.value.trim().toLowerCase();
1135
+ document.querySelectorAll('.sidebar a.doc-section-link').forEach(a => a.classList.toggle('hidden', !a.textContent.toLowerCase().includes(q)));
1136
+ });
1137
+ </script>
1138
+ </body>
1139
+
1140
+ </html>