lightview 2.4.4 → 2.4.7

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.
@@ -161,9 +161,14 @@
161
161
  class="btn btn-outline btn-benchmark border-slate-300">Run Raw oDOM</button>
162
162
  <button onclick="runBenchmark('vDOM')"
163
163
  class="btn btn-outline btn-benchmark border-slate-300">Run Lightview vDOM</button>
164
+ <button onclick="runBenchmark('JurisODOM')"
165
+ class="btn btn-outline btn-benchmark border-slate-300">Run JurisJS oDOM</button>
164
166
  <button onclick="runBenchmark('TaggedScript')"
165
167
  class="btn btn-outline btn-benchmark border-slate-300">Run Lightview Tagged
166
168
  Script</button>
169
+ <button onclick="runBenchmark('BauTaggedScript')"
170
+ class="btn btn-outline btn-benchmark border-slate-300">Run Bau Tagged
171
+ Script</button>
167
172
  <div class="divider"></div>
168
173
  <button onclick="runAll()" class="btn btn-primary text-white">Run All Benchmarks</button>
169
174
  <button onclick="clearTarget()" class="btn btn-ghost">Clear Target</button>
@@ -303,6 +308,31 @@
303
308
  </div>
304
309
  </div>
305
310
 
311
+ <div class="result-card" id="res-JurisODOM">
312
+ <div class="flex justify-between items-start mb-2">
313
+ <h3 class="font-bold text-slate-500 uppercase text-xs tracking-widest">JurisJS oDOM</h3>
314
+ <div class="flex flex-col items-end gap-1">
315
+ <div class="badge badge-outline badge-xs opacity-50"><span class="size">--</span> KB
316
+ </div>
317
+ <div class="badge badge-accent badge-xs text-white opacity-70"><span
318
+ class="gzip-size">--</span> KB gzip</div>
319
+ <div class="badge badge-ghost badge-sm opacity-50">ms</div>
320
+ </div>
321
+ </div>
322
+ <div class="text-3xl font-black text-slate-800 mb-4"><span class="time">--</span></div>
323
+
324
+ <div class="grid grid-cols-4 gap-2 text-[10px] uppercase font-bold text-slate-400 mb-3">
325
+ <div>Min <span class="min block text-slate-600">--</span></div>
326
+ <div>Avg <span class="avg block text-slate-600">--</span></div>
327
+ <div>Max <span class="max block text-slate-600">--</span></div>
328
+ <div class="text-right">±SD <span class="std block text-slate-600">--</span></div>
329
+ </div>
330
+
331
+ <div class="progress-bar-custom">
332
+ <div class="progress-fill" id="fill-JurisODOM"></div>
333
+ </div>
334
+ </div>
335
+
306
336
  <div class="result-card" id="res-TaggedScript">
307
337
  <div class="flex justify-between items-start mb-2">
308
338
  <h3 class="font-bold text-slate-500 uppercase text-xs tracking-widest">Lightview Tagged
@@ -328,6 +358,32 @@
328
358
  <div class="progress-fill" id="fill-TaggedScript"></div>
329
359
  </div>
330
360
  </div>
361
+
362
+ <div class="result-card" id="res-BauTaggedScript">
363
+ <div class="flex justify-between items-start mb-2">
364
+ <h3 class="font-bold text-slate-500 uppercase text-xs tracking-widest">Bau Tagged
365
+ Script</h3>
366
+ <div class="flex flex-col items-end gap-1">
367
+ <div class="badge badge-outline badge-xs opacity-50"><span class="size">--</span> KB
368
+ </div>
369
+ <div class="badge badge-accent badge-xs text-white opacity-70"><span
370
+ class="gzip-size">--</span> KB gzip</div>
371
+ <div class="badge badge-ghost badge-sm opacity-50">ms</div>
372
+ </div>
373
+ </div>
374
+ <div class="text-3xl font-black text-slate-800 mb-4"><span class="time">--</span></div>
375
+
376
+ <div class="grid grid-cols-4 gap-2 text-[10px] uppercase font-bold text-slate-400 mb-3">
377
+ <div>Min <span class="min block text-slate-600">--</span></div>
378
+ <div>Avg <span class="avg block text-slate-600">--</span></div>
379
+ <div>Max <span class="max block text-slate-600">--</span></div>
380
+ <div class="text-right">±SD <span class="std block text-slate-600">--</span></div>
381
+ </div>
382
+
383
+ <div class="progress-bar-custom">
384
+ <div class="progress-fill" id="fill-BauTaggedScript"></div>
385
+ </div>
386
+ </div>
331
387
  </div>
332
388
 
333
389
  <div class="card bg-white shadow-sm border border-slate-200">
@@ -347,6 +403,7 @@
347
403
  <!-- Core Libraries -->
348
404
  <script src="/lightview.js"></script>
349
405
  <script src="/lightview-x.js"></script>
406
+ <script src="https://cdn.jsdelivr.net/npm/juris@0.9.0/juris.min.js"></script>
350
407
 
351
408
  <script>
352
409
  function generateHTML(count) {
@@ -468,6 +525,55 @@
468
525
  return el;
469
526
  }
470
527
 
528
+ function odomToDOM_Juris(onode) {
529
+ if (typeof onode !== 'object' || onode === null) {
530
+ return document.createTextNode(onode);
531
+ }
532
+
533
+ // Create a temporary container for Juris to render into
534
+ const tempContainer = document.createElement('div');
535
+
536
+ // Temporarily disable all console methods to prevent Juris logging from affecting benchmark
537
+ const originalConsole = {
538
+ log: console.log,
539
+ dir: console.dir,
540
+ warn: console.warn,
541
+ error: console.error,
542
+ info: console.info,
543
+ debug: console.debug
544
+ };
545
+ const noop = () => { };
546
+ console.log = noop;
547
+ console.dir = noop;
548
+ console.warn = noop;
549
+ console.error = noop;
550
+ console.info = noop;
551
+ console.debug = noop;
552
+
553
+ try {
554
+ // Create a Juris instance with the oDOM structure as the layout
555
+ const jurisInstance = new Juris({
556
+ debug: false, // Disable logging for performance
557
+ layout: onode
558
+ });
559
+
560
+ // Render to the temporary container
561
+ jurisInstance.render(tempContainer);
562
+ } finally {
563
+ // Restore original console methods
564
+ console.log = originalConsole.log;
565
+ console.dir = originalConsole.dir;
566
+ console.warn = originalConsole.warn;
567
+ console.error = originalConsole.error;
568
+ console.info = originalConsole.info;
569
+ console.debug = originalConsole.debug;
570
+ }
571
+
572
+ // Return the first child (the actual rendered content)
573
+ return tempContainer.firstChild || tempContainer;
574
+ }
575
+
576
+
471
577
  async function getGzipSize(str) {
472
578
  try {
473
579
  const stream = new Blob([str]).stream();
@@ -518,7 +624,7 @@
518
624
  function clearTarget() {
519
625
  target.replaceChildren();
520
626
  target.innerHTML = '<div class="p-8 text-center text-slate-400 italic">Target is empty.</div>';
521
- ['innerHTML', 'DOMParser', 'vDOM', 'RawVDOM', 'RawoDOM', 'TaggedScript'].forEach(id => {
627
+ ['innerHTML', 'DOMParser', 'vDOM', 'RawVDOM', 'RawoDOM', 'JurisODOM', 'TaggedScript', 'BauTaggedScript'].forEach(id => {
522
628
  const card = document.getElementById(`res-${id}`);
523
629
  card.classList.remove('active');
524
630
  card.querySelector('.time').innerText = '--';
@@ -568,6 +674,12 @@
568
674
  const domEl = odomToDOM(json);
569
675
  target.replaceChildren(domEl);
570
676
  time = performance.now() - start;
677
+ } else if (type === 'JurisODOM') {
678
+ const start = performance.now();
679
+ const json = JSON.parse(data);
680
+ const domEl = odomToDOM_Juris(json);
681
+ target.replaceChildren(domEl);
682
+ time = performance.now() - start;
571
683
  } else if (type === 'TaggedScript') {
572
684
  const existing = document.getElementById('tagged-script-tag');
573
685
  if (existing) existing.remove();
@@ -580,6 +692,19 @@
580
692
  document.body.appendChild(script);
581
693
  });
582
694
  time = window.__taggedBenchmarkTime;
695
+ } else if (type === 'BauTaggedScript') {
696
+ const existing = document.getElementById('bau-tagged-script-tag');
697
+ if (existing) existing.remove();
698
+
699
+ await new Promise(resolve => {
700
+ window.__resolveBauTaggedBenchmark = resolve;
701
+ const script = document.createElement('script');
702
+ script.type = 'module';
703
+ script.id = 'bau-tagged-script-tag';
704
+ script.src = `./benchmarks/bau-tagged-fragment.js?count=${count}&t=${Date.now()}`;
705
+ document.body.appendChild(script);
706
+ });
707
+ time = window.__bauTaggedBenchmarkTime;
583
708
  }
584
709
  return time;
585
710
  }
@@ -592,10 +717,10 @@
592
717
  let data = preGeneratedData;
593
718
 
594
719
  // 1. Preparation phase (outside of timing)
595
- if (!data && type !== 'TaggedScript') {
720
+ if (!data && type !== 'TaggedScript' && type !== 'BauTaggedScript') {
596
721
  if (type === 'innerHTML' || type === 'DOMParser') data = generateHTML(count);
597
722
  if (type === 'vDOM' || type === 'RawVDOM') data = generateVDOM(count);
598
- if (type === 'RawoDOM') data = generateODOM(count);
723
+ if (type === 'RawoDOM' || type === 'JurisODOM') data = generateODOM(count);
599
724
  }
600
725
 
601
726
  console.log(`Starting ${cycles} cycles for ${type}...`);
@@ -628,7 +753,9 @@
628
753
  { id: 'RawVDOM', data: vdomData },
629
754
  { id: 'RawoDOM', data: odomData },
630
755
  { id: 'vDOM', data: vdomData },
631
- { id: 'TaggedScript', data: null }
756
+ { id: 'JurisODOM', data: odomData },
757
+ { id: 'TaggedScript', data: null },
758
+ { id: 'BauTaggedScript', data: null }
632
759
  ];
633
760
 
634
761
  for (const config of configs) {
@@ -15,6 +15,7 @@
15
15
  <button class="btn btn-secondary step-btn" onclick="switchStep(4)">4. Hypermedia</button>
16
16
  <button class="btn btn-secondary step-btn" onclick="switchStep(5)">5. Components</button>
17
17
  <button class="btn btn-secondary step-btn" onclick="switchStep(6)">6. Gating</button>
18
+ <button class="btn btn-secondary step-btn" onclick="switchStep(7)">7. cDOM</button>
18
19
  </div>
19
20
 
20
21
  <!-- Tutorial Layout: Preview on top, Code & Concepts below -->
@@ -679,6 +680,45 @@ $('#app').content(App);`,
679
680
  <li style="margin-bottom: 0.75rem;"><strong>Write your own</strong> — Write your own functions and add the to <code>globalThis</code> to make them available to all templates. They have access to <code>this</code> (the element) and can accept arguments like <code>event</code>.</li>
680
681
  </ul>
681
682
  <p><strong>Try it:</strong> Click the Spam Me button rapidly, or type quickly into the search box to see the limiters in action!</p>`
683
+ },
684
+ 7: {
685
+ options: {
686
+ autoRun: true
687
+ },
688
+ code: `// STEP 7: cDOM - Compressed DOM & JPRX
689
+ await import('/lightview-cdom.js');
690
+ const { parseJPRX, hydrate } = globalThis.LightviewCDOM;
691
+ const { $ } = Lightview;
692
+
693
+ const cdomString = \`{
694
+ div: {
695
+ onmount: =signal(0,"count"),
696
+ children: [
697
+ { h3: ["Standard JPRX Counter"] },
698
+ { p: { children: ["Count: ", =/count] }},
699
+ { div: { children: [
700
+ { button: { onclick: =decrement(/count), children: ["-"] } },
701
+ { button: { onclick: =/count++, children: ["+"] } }
702
+ ]}}
703
+ ]
704
+ }
705
+ }\`;
706
+
707
+ const hydrated = hydrate(parseJPRX(cdomString));
708
+ $('#app').content(hydrated);`,
709
+ concepts: `
710
+ <h3 style="margin-top: 0; color: var(--site-primary);">Step 7: cDOM & JPRX</h3>
711
+ <p><strong><a href="/docs/cdom.html">cDOM</a></strong> (compressed DOM) combined with <strong><a href="/docs/cdom.html#JPRX">JPRX</a></strong> (JSON Path Reactive eXpressions) allows you to define entire reactive UIs as pure JSON-compatible strings.</p>
712
+
713
+ <h4>Key Concepts:</h4>
714
+ <ul style="padding-left: 1.25rem; color: var(--site-text-secondary);">
715
+ <li style="margin-bottom: 0.75rem;"><strong>Portability</strong> — Since the UI is a string, it can be easily stored in databases, sent over the wire, or generated by an LLM without security risks of <code>eval()</code>.</li>
716
+ <li style="margin-bottom: 0.75rem;"><strong>JPRX Expressions</strong> — Use <code>=</code> to denote reactive expressions within the string. For example, <code>=/count</code> binds to a signal.</li>
717
+ <li style="margin-bottom: 0.75rem;"><strong>Flexible Syntax</strong> — Operators and helpers can be called as functions (<code>=decrement(/count)</code>) or using prefix (<code>=--/count</code>), infix (<code>=/count - 1</code>), or postfix (<code>=/count--</code>) notation.</li>
718
+ <li style="margin-bottom: 0.75rem;"><strong>Hydration</strong> — <code>hydrate()</code> turns the parsed JPRX into a live, reactive DOM tree.</li>
719
+ </ul>
720
+ <p><strong>Try it:</strong> Edit the <code>cdomString</code> to change the labels or add new elements!</p>
721
+ `
682
722
  }
683
723
  };
684
724
 
package/docs/index.html CHANGED
@@ -11,7 +11,7 @@
11
11
  More power. Less energy.
12
12
  <br>
13
13
  <a id="link-hero-ai-safe" href="#ai-safe"
14
- style="color: var(--site-primary); font-size: 1.25rem; font-weight: 700; text-decoration: none; display: inline-block; margin-top: 0.5rem; border-bottom: 2px solid var(--site-primary); padding-bottom: 2px;">AI
14
+ style="color: var(--site-primary); font-size: 1.25rem; font-weight: 700; text-decoration: none; display: inline-block; margin-top: 0.25rem; border-bottom: 2px solid var(--site-primary); padding-bottom: 2px;">AI
15
15
  Safe</a>
16
16
  </p>
17
17
  <div class="hero-actions">
@@ -23,12 +23,15 @@
23
23
  <div class="hero-stat-label">Build Steps</div>
24
24
  </div>
25
25
  <div class="hero-stat">
26
- <div class="hero-stat-value">4</div>
26
+ <div class="hero-stat-value"><a id="link-hero-ways-to-build"
27
+ href="http://localhost:3000/docs/api/elements"
28
+ style="color: inherit; text-decoration: none;">5</a></div>
27
29
  <div class="hero-stat-label">Ways to Build</div>
28
30
  </div>
29
31
  <div class="hero-stat">
30
32
  <div class="hero-stat-value">40+</div>
31
- <div class="hero-stat-label">Components</div>
33
+ <div class="hero-stat-label"><a id="link-hero-components" href="http://localhost:3000/docs/components/"
34
+ style="color: inherit; text-decoration: none;">Components</a></div>
32
35
  </div>
33
36
  </div>
34
37
  </div>
@@ -38,79 +41,84 @@
38
41
  <section class="section">
39
42
  <div class="section-content">
40
43
  <div class="section-header">
41
- <h2 class="section-title">Heavy? Not Our Thing.</h2>
42
- <p class="section-subtitle">
43
- Have fun, stay light.
44
- </p>
44
+ <h2 class="section-title">Why Lightview</h2>
45
45
  </div>
46
46
  <div class="feature-grid">
47
- <div class="feature-card">
47
+ <a id="link-feature-signals" href="./api/signals.html" class="feature-card">
48
48
  <div class="feature-icon">
49
49
  <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2">
50
50
  <circle cx="12" cy="12" r="10" />
51
51
  <path d="M12 6v6l4 2" />
52
52
  </svg>
53
53
  </div>
54
- <h3><a id="link-feature-signals" href="./api/signals.html" class="feature-title">Signals and Object
55
- State Reactivity</a></h3>
54
+ <h3 class="feature-title">Signals and Object State Reactivity</h3>
56
55
  <p class="feature-description">
57
- Fine-grained reactivity with signals and obejct state. Updates propagate automatically—no virtual
58
- DOM diffing needed. As a bonus, session and local storage are also supported.
56
+ Fine-grained reactivity with signals and object state. Updates propagate automatically—no virtual
57
+ DOM diffing needed. Arrays and Dates are directly reactive without destructing or copying. As a
58
+ bonus, session and local storage are also supported.
59
59
  </p>
60
- </div>
61
- <div class="feature-card">
60
+ </a>
61
+ <a id="link-feature-elements" href="./api/elements.html" class="feature-card">
62
62
  <div class="feature-icon">
63
63
  <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2">
64
64
  <rect x="3" y="3" width="18" height="18" rx="2" />
65
65
  <path d="M3 9h18M9 21V9" />
66
66
  </svg>
67
67
  </div>
68
- <h3><a id="link-feature-elements" href="./api/elements.html" class="feature-title">Multiple Syntaxes</a>
69
- </h3>
68
+ <h3 class="feature-title">Multiple Syntaxes</h3>
70
69
  <p class="feature-description">
71
70
  Tagged API, vDOM, Object DOM, HTML. Pick your style—they all work together.
72
71
  </p>
73
- </div>
74
- <div class="feature-card">
72
+ </a>
73
+ <a id="link-feature-hypermedia" href="/docs/hypermedia/" class="feature-card">
75
74
  <div class="feature-icon">
76
75
  <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2">
77
76
  <path
78
77
  d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.66 0 3-4 3-9s-1.34-9-3-9m0 18c-1.66 0-3-4-3-9s1.34-9 3-9" />
79
78
  </svg>
80
79
  </div>
81
- <h3><a id="link-feature-hypermedia" href="/docs/hypermedia/" class="feature-title">Hypermedia
82
- Ready</a></h3>
80
+ <h3 class="feature-title">Hypermedia Ready</h3>
83
81
  <p class="feature-description">
84
82
  Fetch HTML, vDOM, or Object DOM with the <code>src</code> attribute. HTMX-like patterns for
85
83
  <code>src</code> and <code>href</code> built right
86
84
  in.
87
85
  </p>
88
- </div>
89
- <div class="feature-card">
86
+ </a>
87
+ <a id="link-feature-components" href="./components/index.html" class="feature-card">
90
88
  <div class="feature-icon">
91
89
  <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2">
92
90
  <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" />
93
91
  </svg>
94
92
  </div>
95
- <h3><a id="link-feature-components" href="./components/index.html" class="feature-title">Component
96
- Library</a></h3>
93
+ <h3 class="feature-title">Component Library</h3>
97
94
  <p class="feature-description">
98
95
  Beautiful, accessible components ready to use. Buttons, modals, forms, charts, and more.
99
96
  </p>
100
- </div>
101
- <div class="feature-card">
97
+ </a>
98
+ <a id="link-feature-zerobuild" href="./getting-started/index.html" class="feature-card">
102
99
  <div class="feature-icon">
103
100
  <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2">
104
101
  <path
105
102
  d="M14.7 6.3a1 1 0 000 1.4l1.6 1.6a1 1 0 001.4 0l3.77-3.77a6 6 0 01-7.94 7.94l-6.91 6.91a2.12 2.12 0 01-3-3l6.91-6.91a6 6 0 017.94-7.94l-3.76 3.76z" />
106
103
  </svg>
107
104
  </div>
108
- <h3><a id="link-feature-zerobuild" href="./getting-started/index.html" class="feature-title">Zero Build
109
- Step</a></h3>
105
+ <h3 class="feature-title">Zero Build Step</h3>
110
106
  <p class="feature-description">
111
107
  No bundler required. Drop in a script tag and start building. Works everywhere.
112
108
  </p>
113
- </div>
109
+ </a>
110
+ <a id="link-feature-aisafe" href="#ai-safe" class="feature-card">
111
+ <div class="feature-icon">
112
+ <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2">
113
+ <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
114
+ </svg>
115
+ </div>
116
+ <h3 class="feature-title">AI Safe</h3>
117
+ <p class="feature-description">
118
+ Build reactive UIs with pure JSON or JSON like data. No eval(), no risky code generation. Safe for
119
+ AI agents.
120
+ </p>
121
+ </a>
114
122
 
115
123
  </div>
116
124
  </div>
@@ -150,7 +158,8 @@
150
158
  <h3 style="color: white; font-size: 1.5rem; margin-bottom: 1rem;">Execution Safety</h3>
151
159
  <p style="color: rgba(255, 255, 255, 0.75); line-height: 1.6;">AI-generated UIs usually require
152
160
  risky JavaScript strings. cDOM creates reactive interfaces using <strong>pure JSON
153
- data</strong> and <a id="link-ai-safe-cdom-helpers" href="/docs/cdom.html#helpers"
161
+ or JSON like data</strong> and <a id="link-ai-safe-cdom-helpers"
162
+ href="/docs/cdom.html#helpers"
154
163
  style="color: #a78bfa; text-decoration: underline; font-weight: 600;">over 50 built-in
155
164
  functions</a> that bring spreadsheet-like
156
165
  functionality to the DOM. No <code>eval()</code>, no <code>new Function()</code>, and <strong>no
@@ -223,7 +232,7 @@
223
232
  <section class="section">
224
233
  <div class="section-content">
225
234
  <div class="section-header">
226
- <h2 class="section-title">Heavy, Complex Frameworks? Lighten Up.</h2>
235
+ <h2 class="section-title">Lighten Up.</h2>
227
236
  <p class="section-subtitle">
228
237
  Get started in minutes. No npm install. No webpack or vite build process. Just code.
229
238
  </p>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "lightview",
3
- "version": "2.4.4",
4
- "description": "An reactive UI library with features of Bau, Juris, and HTMX plus safe LLM UI generation",
3
+ "version": "2.4.7",
4
+ "description": "A reactive UI library with features of Bau, Juris, and HTMX plus safe LLM UI generation",
5
5
  "main": "lightview.js",
6
6
  "workspaces": [
7
7
  "jprx"