@inglorious/web 4.0.7 → 4.0.9
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 +376 -18
- package/package.json +6 -3
- package/src/index.js +1 -1
- package/src/test.js +2 -0
package/README.md
CHANGED
|
@@ -32,8 +32,8 @@ Unlike modern frameworks that invent their own languages or rely on signals, pro
|
|
|
32
32
|
- **Zero Component State**
|
|
33
33
|
All state lives in the store — never inside components.
|
|
34
34
|
|
|
35
|
-
- **No Signals, No Subscriptions, No Memory Leaks**
|
|
36
|
-
Because every render is triggered by the store, and lit-html handles the rest.
|
|
35
|
+
- **No Signals, No Subscriptions, No Framework-Level Memory Leaks**
|
|
36
|
+
Because every render is triggered by the store, and lit-html handles the rest — no subscription cleanup needed.
|
|
37
37
|
|
|
38
38
|
- **No compilation required**
|
|
39
39
|
Apps can run directly in the browser — no build/compile step is strictly necessary (though you may use bundlers or Vite for convenience in larger projects).
|
|
@@ -60,6 +60,8 @@ Use the scaffolder to create a starter app tailored to your workflow.
|
|
|
60
60
|
|
|
61
61
|
### ✨ **Inglorious Web re-renders the whole template tree on each state change.**
|
|
62
62
|
|
|
63
|
+
**Important:** The DOM itself is not re-created. Only the template function reruns, and lit-html's efficient diffing updates just the changed DOM nodes.
|
|
64
|
+
|
|
63
65
|
Thanks to lit-html's optimized diffing, this is fast, predictable, and surprisingly efficient.
|
|
64
66
|
|
|
65
67
|
This means:
|
|
@@ -89,11 +91,11 @@ It's that simple — and surprisingly fast in practice.
|
|
|
89
91
|
|
|
90
92
|
This framework is ideal for both small apps and large business UIs.
|
|
91
93
|
|
|
92
|
-
|
|
94
|
+
---
|
|
93
95
|
|
|
94
96
|
## When NOT to Use Inglorious Web
|
|
95
97
|
|
|
96
|
-
- You
|
|
98
|
+
- You're frequently mutating thousands of items without virtualization (though our `list` component handles this elegantly)
|
|
97
99
|
- You're building a library that needs to be framework-agnostic
|
|
98
100
|
- Your team is already deeply invested in React/Vue/Angular
|
|
99
101
|
|
|
@@ -125,7 +127,7 @@ These systems are powerful but introduce:
|
|
|
125
127
|
✔ **Every UI update is a full diff pass**
|
|
126
128
|
✔ **Every part of the system is just JavaScript**
|
|
127
129
|
✔ **No special lifecycle**
|
|
128
|
-
✔ **No subscriptions needed**
|
|
130
|
+
✔ **No subscriptions needed**
|
|
129
131
|
✔ **No signals**
|
|
130
132
|
✔ **No cleanup**
|
|
131
133
|
✔ **No surprises**
|
|
@@ -139,13 +141,27 @@ This makes it especially suitable for:
|
|
|
139
141
|
|
|
140
142
|
---
|
|
141
143
|
|
|
142
|
-
|
|
144
|
+
## Comparison with Other Frameworks
|
|
145
|
+
|
|
146
|
+
### TL;DR Quick Comparison
|
|
147
|
+
|
|
148
|
+
| Framework | Reactivity | Compiler | Component State | Bundle Size | Learning Curve |
|
|
149
|
+
| -------------- | -------------- | -------- | --------------- | ----------- | -------------- |
|
|
150
|
+
| Inglorious Web | Event-based | None | No (store only) | Tiny | Very Low |
|
|
151
|
+
| React | VDOM diffing | None | Yes | Large | Medium/High |
|
|
152
|
+
| Vue | Proxy-based | Optional | Yes | Medium | Medium |
|
|
153
|
+
| Svelte | Compiler magic | Required | Yes | Small | Medium |
|
|
154
|
+
| SolidJS | Fine signals | None | No (runs once) | Tiny | Medium/High |
|
|
155
|
+
| Qwik | Resumable | Required | Yes | Small | Very High |
|
|
156
|
+
|
|
157
|
+
<details>
|
|
158
|
+
<summary><strong>Click to expand detailed framework comparisons</strong></summary>
|
|
143
159
|
|
|
144
|
-
Here's how @inglorious/web compares to the major players:
|
|
160
|
+
Here's how @inglorious/web compares to the major players in detail:
|
|
145
161
|
|
|
146
162
|
---
|
|
147
163
|
|
|
148
|
-
|
|
164
|
+
### **React**
|
|
149
165
|
|
|
150
166
|
| Feature | React | Inglorious Web |
|
|
151
167
|
| ------------------------- | ----------------------------- | ---------------------------------- |
|
|
@@ -162,7 +178,7 @@ React is powerful but complicated. Inglorious Web is simpler, lighter, and close
|
|
|
162
178
|
|
|
163
179
|
---
|
|
164
180
|
|
|
165
|
-
|
|
181
|
+
### **Vue (3)**
|
|
166
182
|
|
|
167
183
|
| Feature | Vue | Inglorious Web |
|
|
168
184
|
| --------------- | -------------------------- | ----------------------------------- |
|
|
@@ -176,7 +192,7 @@ Vue reactivity is elegant but complex. Inglorious Web avoids proxies and keeps e
|
|
|
176
192
|
|
|
177
193
|
---
|
|
178
194
|
|
|
179
|
-
|
|
195
|
+
### **Svelte**
|
|
180
196
|
|
|
181
197
|
| Feature | Svelte | Inglorious Web |
|
|
182
198
|
| -------------- | --------------------------- | ------------------ |
|
|
@@ -189,7 +205,7 @@ Svelte is magic; Inglorious Web is explicit.
|
|
|
189
205
|
|
|
190
206
|
---
|
|
191
207
|
|
|
192
|
-
|
|
208
|
+
### **SolidJS**
|
|
193
209
|
|
|
194
210
|
| Feature | Solid | Inglorious Web |
|
|
195
211
|
| ---------- | -------------------- | ------------------ |
|
|
@@ -198,12 +214,12 @@ Svelte is magic; Inglorious Web is explicit.
|
|
|
198
214
|
| Cleanup | Required | None |
|
|
199
215
|
| Behavior | Highly optimized | Highly predictable |
|
|
200
216
|
|
|
201
|
-
Solid is extremely fast but requires a mental model.
|
|
217
|
+
Solid is extremely fast but requires a mental model shift.
|
|
202
218
|
Inglorious Web trades peak performance for simplicity and zero overhead.
|
|
203
219
|
|
|
204
220
|
---
|
|
205
221
|
|
|
206
|
-
|
|
222
|
+
### **Qwik**
|
|
207
223
|
|
|
208
224
|
| Feature | Qwik | Inglorious Web |
|
|
209
225
|
| -------------------- | -------------------- | -------------- |
|
|
@@ -216,13 +232,15 @@ Inglorious Web is minimal, predictable, and tiny.
|
|
|
216
232
|
|
|
217
233
|
---
|
|
218
234
|
|
|
219
|
-
|
|
235
|
+
### **HTMX / Alpine / Vanilla DOM**
|
|
220
236
|
|
|
221
237
|
Inglorious Web is closer philosophically to **HTMX** and **vanilla JS**, but with a declarative rendering model and entity-based state.
|
|
222
238
|
|
|
239
|
+
</details>
|
|
240
|
+
|
|
223
241
|
---
|
|
224
242
|
|
|
225
|
-
|
|
243
|
+
## Why Choose Inglorious Web
|
|
226
244
|
|
|
227
245
|
- Minimalistic
|
|
228
246
|
- Pure JavaScript
|
|
@@ -231,7 +249,7 @@ Inglorious Web is closer philosophically to **HTMX** and **vanilla JS**, but wit
|
|
|
231
249
|
- One render path, no hidden rules
|
|
232
250
|
- No reactivity graphs
|
|
233
251
|
- No per-component subscriptions
|
|
234
|
-
- No memory leaks
|
|
252
|
+
- No framework-level memory leaks
|
|
235
253
|
- No build step required (apps can run in the browser)
|
|
236
254
|
- Works perfectly in hybrid UI/game engine contexts
|
|
237
255
|
- Uses native ES modules and standards
|
|
@@ -260,7 +278,7 @@ import { createStore, html } from "@inglorious/web"
|
|
|
260
278
|
|
|
261
279
|
const types = {
|
|
262
280
|
counter: {
|
|
263
|
-
increment(entity
|
|
281
|
+
increment(entity) {
|
|
264
282
|
entity.value++
|
|
265
283
|
},
|
|
266
284
|
|
|
@@ -313,6 +331,346 @@ The `mount` function subscribes to the store and automatically re-renders your t
|
|
|
313
331
|
|
|
314
332
|
---
|
|
315
333
|
|
|
334
|
+
## Testing
|
|
335
|
+
|
|
336
|
+
One of Inglorious Web's greatest strengths is **testability**. Entity handlers are pure functions (via Mutative.js), and render functions return simple templates. No special testing libraries, no complex setup, no mocking hell.
|
|
337
|
+
|
|
338
|
+
### Testing Utilities
|
|
339
|
+
|
|
340
|
+
Inglorious Web provides two simple utilities for testing via `@inglorious/web/test`:
|
|
341
|
+
|
|
342
|
+
#### `trigger(entity, handler, payload?, api?)`
|
|
343
|
+
|
|
344
|
+
Execute an entity handler and get back the new state plus any events dispatched. Handlers are wrapped in Mutative.js, so they return new immutable state even though you write mutable-looking code.
|
|
345
|
+
|
|
346
|
+
```javascript
|
|
347
|
+
import { trigger } from "@inglorious/web/test"
|
|
348
|
+
import { counter } from "./types/counter.js"
|
|
349
|
+
|
|
350
|
+
test("increment adds to value", () => {
|
|
351
|
+
const { entity, events } = trigger(
|
|
352
|
+
{ type: "counter", id: "counter1", value: 10 },
|
|
353
|
+
counter.increment,
|
|
354
|
+
{ amount: 5 },
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
expect(entity.value).toBe(15)
|
|
358
|
+
expect(events).toEqual([]) // No events dispatched
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
test("increment dispatches overflow event", () => {
|
|
362
|
+
const { entity, events } = trigger(
|
|
363
|
+
{ type: "counter", id: "counter1", value: 99 },
|
|
364
|
+
counter.increment,
|
|
365
|
+
{ amount: 5 },
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
expect(entity.value).toBe(104)
|
|
369
|
+
expect(events).toEqual([{ type: "overflow", payload: { id: "counter1" } }])
|
|
370
|
+
})
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
#### `render(template)`
|
|
374
|
+
|
|
375
|
+
Render a lit-html template to an HTML string for testing. Perfect for testing render output with simple string assertions.
|
|
376
|
+
|
|
377
|
+
```javascript
|
|
378
|
+
import { render } from "@inglorious/web/test"
|
|
379
|
+
import { counter } from "./types/counter.js"
|
|
380
|
+
|
|
381
|
+
test("counter renders correctly", () => {
|
|
382
|
+
const entity = {
|
|
383
|
+
type: "counter",
|
|
384
|
+
id: "counter1",
|
|
385
|
+
value: 42,
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
const mockApi = {
|
|
389
|
+
notify: jest.fn(),
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const template = counter.render(entity, mockApi)
|
|
393
|
+
const html = render(template)
|
|
394
|
+
|
|
395
|
+
expect(html).toContain("Count: 42")
|
|
396
|
+
expect(html).toContain("button")
|
|
397
|
+
})
|
|
398
|
+
|
|
399
|
+
test("counter button has click handler", () => {
|
|
400
|
+
const entity = { type: "counter", id: "counter1", value: 10 }
|
|
401
|
+
const mockApi = { notify: jest.fn() }
|
|
402
|
+
|
|
403
|
+
const template = counter.render(entity, mockApi)
|
|
404
|
+
const html = render(template)
|
|
405
|
+
|
|
406
|
+
expect(html).toContain("onclick")
|
|
407
|
+
})
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### Why Testing is Easy
|
|
411
|
+
|
|
412
|
+
**No special setup required:**
|
|
413
|
+
|
|
414
|
+
```bash
|
|
415
|
+
npm install --save-dev vitest # or jest, or node:test
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
That's it. No `@testing-library/react`, no `renderHook`, no `act()` wrappers.
|
|
419
|
+
|
|
420
|
+
**Pure functions everywhere:**
|
|
421
|
+
|
|
422
|
+
- Entity handlers are pure (thanks to Mutative.js)
|
|
423
|
+
- Render functions are pure (they return templates)
|
|
424
|
+
- No lifecycle hooks to manage
|
|
425
|
+
- No async state updates to wrangle
|
|
426
|
+
|
|
427
|
+
**Simple assertions:**
|
|
428
|
+
|
|
429
|
+
- Test handlers: `expect(entity.value).toBe(15)`
|
|
430
|
+
- Test renders: `expect(html).toContain('expected text')`
|
|
431
|
+
- Test events: `expect(events).toHaveLength(1)`
|
|
432
|
+
|
|
433
|
+
### Testing Patterns
|
|
434
|
+
|
|
435
|
+
#### Unit Test: Handler Logic
|
|
436
|
+
|
|
437
|
+
```javascript
|
|
438
|
+
import { trigger } from "@inglorious/web/test"
|
|
439
|
+
import { todo } from "./types/todo.js"
|
|
440
|
+
|
|
441
|
+
test("toggle changes completed status", () => {
|
|
442
|
+
const { entity } = trigger(
|
|
443
|
+
{ type: "todo", id: "todo1", text: "Buy milk", completed: false },
|
|
444
|
+
todo.toggle,
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
expect(entity.completed).toBe(true)
|
|
448
|
+
})
|
|
449
|
+
|
|
450
|
+
test("delete dispatches remove event", () => {
|
|
451
|
+
const { events } = trigger(
|
|
452
|
+
{ type: "todo", id: "todo1", text: "Buy milk" },
|
|
453
|
+
todo.delete,
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
expect(events).toEqual([{ type: "#todoList:removeTodo", payload: "todo1" }])
|
|
457
|
+
})
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
#### Unit Test: Render Output
|
|
461
|
+
|
|
462
|
+
```javascript
|
|
463
|
+
import { render } from "@inglorious/web/test"
|
|
464
|
+
import { todo } from "./types/todo.js"
|
|
465
|
+
|
|
466
|
+
test("todo renders text and status", () => {
|
|
467
|
+
const entity = {
|
|
468
|
+
type: "todo",
|
|
469
|
+
id: "todo1",
|
|
470
|
+
text: "Buy milk",
|
|
471
|
+
completed: false,
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
const html = render(todo.render(entity, { notify: jest.fn() }))
|
|
475
|
+
|
|
476
|
+
expect(html).toContain("Buy milk")
|
|
477
|
+
expect(html).not.toContain("completed")
|
|
478
|
+
})
|
|
479
|
+
|
|
480
|
+
test("completed todo has completed class", () => {
|
|
481
|
+
const entity = {
|
|
482
|
+
type: "todo",
|
|
483
|
+
id: "todo1",
|
|
484
|
+
text: "Buy milk",
|
|
485
|
+
completed: true,
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
const html = render(todo.render(entity, { notify: jest.fn() }))
|
|
489
|
+
|
|
490
|
+
expect(html).toContain("completed")
|
|
491
|
+
})
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
#### Integration Test: Full Store
|
|
495
|
+
|
|
496
|
+
```javascript
|
|
497
|
+
import { createStore } from "@inglorious/web"
|
|
498
|
+
import { counter } from "./types/counter.js"
|
|
499
|
+
|
|
500
|
+
test("full user interaction flow", () => {
|
|
501
|
+
const store = createStore({
|
|
502
|
+
types: { counter },
|
|
503
|
+
entities: {
|
|
504
|
+
counter1: { type: "counter", id: "counter1", value: 0 },
|
|
505
|
+
},
|
|
506
|
+
})
|
|
507
|
+
|
|
508
|
+
// User clicks increment
|
|
509
|
+
store.notify("#counter1:increment", { amount: 5 })
|
|
510
|
+
expect(store.entities.counter1.value).toBe(5)
|
|
511
|
+
|
|
512
|
+
// User clicks increment again
|
|
513
|
+
store.notify("#counter1:increment", { amount: 3 })
|
|
514
|
+
expect(store.entities.counter1.value).toBe(8)
|
|
515
|
+
})
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
#### Testing Computed State
|
|
519
|
+
|
|
520
|
+
```javascript
|
|
521
|
+
import { createSelector } from "@inglorious/store"
|
|
522
|
+
|
|
523
|
+
test("filtered todos excludes completed", () => {
|
|
524
|
+
const todos = [
|
|
525
|
+
{ id: 1, text: "Buy milk", completed: false },
|
|
526
|
+
{ id: 2, text: "Walk dog", completed: true },
|
|
527
|
+
{ id: 3, text: "Write tests", completed: false },
|
|
528
|
+
]
|
|
529
|
+
|
|
530
|
+
const getActiveTodos = createSelector([() => todos], (todos) =>
|
|
531
|
+
todos.filter((t) => !t.completed),
|
|
532
|
+
)
|
|
533
|
+
|
|
534
|
+
const result = getActiveTodos()
|
|
535
|
+
|
|
536
|
+
expect(result).toHaveLength(2)
|
|
537
|
+
expect(result[0].text).toBe("Buy milk")
|
|
538
|
+
expect(result[1].text).toBe("Write tests")
|
|
539
|
+
})
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
### Comparison with React Testing
|
|
543
|
+
|
|
544
|
+
**React (with hooks):**
|
|
545
|
+
|
|
546
|
+
```javascript
|
|
547
|
+
import { renderHook, act } from "@testing-library/react"
|
|
548
|
+
|
|
549
|
+
test("counter increments", () => {
|
|
550
|
+
const { result } = renderHook(() => useCounter())
|
|
551
|
+
|
|
552
|
+
act(() => {
|
|
553
|
+
result.current.increment()
|
|
554
|
+
})
|
|
555
|
+
|
|
556
|
+
expect(result.current.count).toBe(1)
|
|
557
|
+
})
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
**Inglorious Web:**
|
|
561
|
+
|
|
562
|
+
```javascript
|
|
563
|
+
import { trigger } from "@inglorious/web/test"
|
|
564
|
+
|
|
565
|
+
test("counter increments", () => {
|
|
566
|
+
const { entity } = trigger({ value: 0 }, counter.increment)
|
|
567
|
+
|
|
568
|
+
expect(entity.value).toBe(1)
|
|
569
|
+
})
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
**The difference:**
|
|
573
|
+
|
|
574
|
+
- ❌ React requires `renderHook`, `act()`, special testing library
|
|
575
|
+
- ✅ Inglorious just calls the function directly
|
|
576
|
+
- ❌ React hooks can't be tested in isolation
|
|
577
|
+
- ✅ Inglorious handlers are just functions
|
|
578
|
+
- ❌ React has async timing issues
|
|
579
|
+
- ✅ Inglorious is synchronous and predictable
|
|
580
|
+
|
|
581
|
+
### Testing Type Composition
|
|
582
|
+
|
|
583
|
+
Type composition (like route guards) is also easy to test:
|
|
584
|
+
|
|
585
|
+
```javascript
|
|
586
|
+
import { trigger } from "@inglorious/web/test"
|
|
587
|
+
import { requireAuth } from "./guards/require-auth.js"
|
|
588
|
+
import { adminPage } from "./pages/admin.js"
|
|
589
|
+
|
|
590
|
+
test("requireAuth blocks unauthenticated access", () => {
|
|
591
|
+
// Compose the guard with the page type
|
|
592
|
+
const guardedPage = requireAuth(adminPage)
|
|
593
|
+
|
|
594
|
+
// Mock localStorage.getItem to return null (not logged in)
|
|
595
|
+
const mockApi = {
|
|
596
|
+
notify: jest.fn(),
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
const { events } = trigger(
|
|
600
|
+
{ type: "adminPage", id: "admin" },
|
|
601
|
+
guardedPage.routeChange,
|
|
602
|
+
{ route: "adminPage" },
|
|
603
|
+
mockApi,
|
|
604
|
+
)
|
|
605
|
+
|
|
606
|
+
// Should redirect to login
|
|
607
|
+
expect(events).toContainEqual(
|
|
608
|
+
expect.objectContaining({
|
|
609
|
+
type: "navigate",
|
|
610
|
+
payload: expect.objectContaining({ to: "/login" }),
|
|
611
|
+
}),
|
|
612
|
+
)
|
|
613
|
+
})
|
|
614
|
+
|
|
615
|
+
test("requireAuth allows authenticated access", () => {
|
|
616
|
+
// Mock localStorage.getItem to return user data
|
|
617
|
+
localStorage.setItem("user", JSON.stringify({ id: 1 }))
|
|
618
|
+
|
|
619
|
+
const guardedPage = requireAuth(adminPage)
|
|
620
|
+
const mockApi = { notify: jest.fn() }
|
|
621
|
+
|
|
622
|
+
const { events } = trigger(
|
|
623
|
+
{ type: "adminPage", id: "admin" },
|
|
624
|
+
guardedPage.routeChange,
|
|
625
|
+
{ route: "adminPage" },
|
|
626
|
+
mockApi,
|
|
627
|
+
)
|
|
628
|
+
|
|
629
|
+
// Should NOT redirect
|
|
630
|
+
expect(events).toEqual([])
|
|
631
|
+
|
|
632
|
+
// Cleanup
|
|
633
|
+
localStorage.removeItem("user")
|
|
634
|
+
})
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
### Fast Test Execution
|
|
638
|
+
|
|
639
|
+
Because Inglorious tests don't mount components or manipulate the DOM, they're extremely fast:
|
|
640
|
+
|
|
641
|
+
```bash
|
|
642
|
+
# Typical test suite times
|
|
643
|
+
React: 30-60 seconds for 100 tests
|
|
644
|
+
Inglorious: 1-3 seconds for 100 tests
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
This makes TDD (Test-Driven Development) actually enjoyable. Fast feedback loops mean you'll actually run tests while coding.
|
|
648
|
+
|
|
649
|
+
### Best Practices
|
|
650
|
+
|
|
651
|
+
1. **Test handlers separately from renders** - Unit test logic, integration test UI
|
|
652
|
+
2. **Use descriptive test names** - "increment adds to value" not "test increment"
|
|
653
|
+
3. **Test edge cases** - Empty states, max values, null checks
|
|
654
|
+
4. **Keep tests simple** - One assertion per test when possible
|
|
655
|
+
5. **Don't over-mock** - Only mock what you must (usually just `api.notify`)
|
|
656
|
+
|
|
657
|
+
### When to Write Tests
|
|
658
|
+
|
|
659
|
+
- ✅ **Always test:** Complex business logic, calculations, validations
|
|
660
|
+
- ✅ **Often test:** Event handlers, state transitions, conditional renders
|
|
661
|
+
- ⚠️ **Sometimes test:** Simple getters, trivial renders
|
|
662
|
+
- ❌ **Rarely test:** Third-party components, framework internals
|
|
663
|
+
|
|
664
|
+
### The Bottom Line
|
|
665
|
+
|
|
666
|
+
If your framework makes testing painful, developers won't test. If testing is trivial, they will.
|
|
667
|
+
|
|
668
|
+
**Inglorious Web makes testing so easy that you'll actually write tests.**
|
|
669
|
+
|
|
670
|
+
No special libraries, no complex setup, just pure functions and simple assertions. Testing becomes a natural part of your workflow, not a chore you avoid.
|
|
671
|
+
|
|
672
|
+
---
|
|
673
|
+
|
|
316
674
|
## JSX Support
|
|
317
675
|
|
|
318
676
|
If you prefer JSX syntax over template literals, you can use **[`@inglorious/vite-plugin-jsx`](https://www.npmjs.com/package/@inglorious/vite-plugin-jsx)**.
|
|
@@ -1065,7 +1423,6 @@ import {
|
|
|
1065
1423
|
// from lit-html
|
|
1066
1424
|
mount,
|
|
1067
1425
|
html,
|
|
1068
|
-
render,
|
|
1069
1426
|
svg,
|
|
1070
1427
|
// lit-html directives
|
|
1071
1428
|
choose,
|
|
@@ -1087,6 +1444,7 @@ import {
|
|
|
1087
1444
|
import { list } from "@inglorious/web/list"
|
|
1088
1445
|
import { router } from "@inglorious/web/router"
|
|
1089
1446
|
import { select } from "@inglorious/web/select"
|
|
1447
|
+
import { render, trigger } from "@inglorious/web/test"
|
|
1090
1448
|
import { table } from "@inglorious/web/table"
|
|
1091
1449
|
```
|
|
1092
1450
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inglorious/web",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.9",
|
|
4
4
|
"description": "A new web framework that leverages the power of the Inglorious Store combined with the performance and simplicity of lit-html.",
|
|
5
5
|
"author": "IceOnFire <antony.mistretta@gmail.com> (https://ingloriouscoderz.it)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -46,6 +46,9 @@
|
|
|
46
46
|
"types": "./types/table.d.ts",
|
|
47
47
|
"import": "./src/table/index.js"
|
|
48
48
|
},
|
|
49
|
+
"./test": {
|
|
50
|
+
"import": "./src/test.js"
|
|
51
|
+
},
|
|
49
52
|
"./table/base.css": "./src/table/base.css",
|
|
50
53
|
"./table/theme.css": "./src/table/theme.css",
|
|
51
54
|
"./select/base.css": "./src/select/base.css",
|
|
@@ -65,8 +68,8 @@
|
|
|
65
68
|
"dependencies": {
|
|
66
69
|
"@lit-labs/ssr-client": "^1.1.8",
|
|
67
70
|
"lit-html": "^3.3.1",
|
|
68
|
-
"@inglorious/
|
|
69
|
-
"@inglorious/
|
|
71
|
+
"@inglorious/utils": "3.7.2",
|
|
72
|
+
"@inglorious/store": "9.0.1"
|
|
70
73
|
},
|
|
71
74
|
"devDependencies": {
|
|
72
75
|
"prettier": "^3.6.2",
|
package/src/index.js
CHANGED
|
@@ -3,7 +3,7 @@ export { createStore } from "@inglorious/store"
|
|
|
3
3
|
export { createDevtools } from "@inglorious/store/client/devtools.js"
|
|
4
4
|
export { createSelector } from "@inglorious/store/select.js"
|
|
5
5
|
export { trigger } from "@inglorious/store/test.js"
|
|
6
|
-
export { html,
|
|
6
|
+
export { html, svg } from "lit-html"
|
|
7
7
|
export { choose } from "lit-html/directives/choose.js"
|
|
8
8
|
export { classMap } from "lit-html/directives/class-map.js"
|
|
9
9
|
export { ref } from "lit-html/directives/ref.js"
|
package/src/test.js
ADDED