bitwrench 2.0.18 → 2.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +86 -81
  2. package/dist/bitwrench-bccl.cjs.js +221 -48
  3. package/dist/bitwrench-bccl.cjs.min.js +3 -3
  4. package/dist/bitwrench-bccl.esm.js +221 -48
  5. package/dist/bitwrench-bccl.esm.min.js +3 -3
  6. package/dist/bitwrench-bccl.umd.js +221 -48
  7. package/dist/bitwrench-bccl.umd.min.js +3 -3
  8. package/dist/bitwrench-code-edit.cjs.js +7 -9
  9. package/dist/bitwrench-code-edit.cjs.min.js +5 -7
  10. package/dist/bitwrench-code-edit.es5.js +6 -8
  11. package/dist/bitwrench-code-edit.es5.min.js +5 -7
  12. package/dist/bitwrench-code-edit.esm.js +7 -9
  13. package/dist/bitwrench-code-edit.esm.min.js +5 -7
  14. package/dist/bitwrench-code-edit.umd.js +7 -9
  15. package/dist/bitwrench-code-edit.umd.min.js +5 -7
  16. package/dist/bitwrench-debug.js +268 -0
  17. package/dist/bitwrench-debug.min.js +3 -0
  18. package/dist/bitwrench-lean.cjs.js +250 -1574
  19. package/dist/bitwrench-lean.cjs.min.js +6 -6
  20. package/dist/bitwrench-lean.es5.js +344 -1661
  21. package/dist/bitwrench-lean.es5.min.js +4 -4
  22. package/dist/bitwrench-lean.esm.js +250 -1574
  23. package/dist/bitwrench-lean.esm.min.js +6 -6
  24. package/dist/bitwrench-lean.umd.js +250 -1574
  25. package/dist/bitwrench-lean.umd.min.js +6 -6
  26. package/dist/bitwrench-util-css.cjs.js +1 -1
  27. package/dist/bitwrench-util-css.cjs.min.js +1 -1
  28. package/dist/bitwrench-util-css.es5.js +1 -1
  29. package/dist/bitwrench-util-css.es5.min.js +1 -1
  30. package/dist/bitwrench-util-css.esm.js +1 -1
  31. package/dist/bitwrench-util-css.esm.min.js +1 -1
  32. package/dist/bitwrench-util-css.umd.js +1 -1
  33. package/dist/bitwrench-util-css.umd.min.js +1 -1
  34. package/dist/bitwrench.cjs.js +510 -1660
  35. package/dist/bitwrench.cjs.min.js +7 -7
  36. package/dist/bitwrench.css +80 -33
  37. package/dist/bitwrench.es5.js +569 -1694
  38. package/dist/bitwrench.es5.min.js +5 -5
  39. package/dist/bitwrench.esm.js +510 -1660
  40. package/dist/bitwrench.esm.min.js +7 -7
  41. package/dist/bitwrench.min.css +1 -1
  42. package/dist/bitwrench.umd.js +510 -1660
  43. package/dist/bitwrench.umd.min.js +7 -7
  44. package/dist/builds.json +133 -111
  45. package/dist/bwserve.cjs.js +2 -2
  46. package/dist/bwserve.esm.js +2 -2
  47. package/dist/sri.json +46 -44
  48. package/package.json +5 -3
  49. package/readme.html +86 -75
  50. package/src/bitwrench-bccl-entry.js +3 -4
  51. package/src/bitwrench-bccl.js +217 -43
  52. package/src/bitwrench-code-edit.js +6 -8
  53. package/src/bitwrench-debug.js +245 -0
  54. package/src/bitwrench-styles.js +35 -8
  55. package/src/bitwrench.js +212 -1563
  56. package/src/cli/attach.js +53 -21
  57. package/src/cli/serve.js +179 -3
  58. package/src/version.js +3 -3
package/README.md CHANGED
@@ -3,10 +3,11 @@
3
3
  [![License](https://img.shields.io/badge/License-BSD%202--Clause-blue.svg)](https://opensource.org/licenses/BSD-2-Clause)
4
4
  [![NPM version](https://img.shields.io/npm/v/bitwrench.svg?style=flat-square)](https://www.npmjs.com/package/bitwrench)
5
5
  [![CI](https://github.com/deftio/bitwrench/actions/workflows/ci.yml/badge.svg)](https://github.com/deftio/bitwrench/actions/workflows/ci.yml)
6
+ [![Coverage](https://img.shields.io/badge/coverage-96.3%25-brightgreen.svg)](https://github.com/deftio/bitwrench)
6
7
 
7
8
  [![bitwrench](./images/bitwrench-logo-med.png)](https://deftio.github.io/bitwrench/pages/)
8
9
 
9
- Bitwrench builds UI from plain JavaScript objects one format for components, styling, state, and server rendering, with no build step and zero dependencies. In bitwrench structure, styles, and state (including client/server) are rendered and managed as javascript objects.
10
+ Bitwrench builds UI from plain JavaScript objects -- one format for components, styling, state, and server rendering, with no build step and zero dependencies.
10
11
 
11
12
  ```javascript
12
13
  // Describe UI as a JavaScript object (a "TACO")
@@ -19,28 +20,28 @@ var page = {
19
20
  ]
20
21
  };
21
22
 
22
- bw.DOM('#app', page); // live DOM
23
- bw.html(page); // HTML string (Node.js, emails, SSR)
23
+ bw.DOM('#app', page); // -> live DOM
24
+ bw.html(page); // -> HTML string (Node.js, emails, SSR)
24
25
  ```
25
26
 
26
- Each object has four keys: **t** (tag), **a** (attributes), **c** (content), **o** (options for state/lifecycle). Nest them, loop them, compose them it's just JavaScript.
27
+ Each object has four keys: **t** (tag), **a** (attributes), **c** (content), **o** (options for state/lifecycle). Nest them, loop them, compose them -- it's just JavaScript.
27
28
 
28
29
  ![Hero example output](./images/hero-example.png)
29
30
 
30
31
  ### Why bitwrench?
31
32
 
32
- **One file, everywhere.** At ~39KB gzipped with zero dependencies, bitwrench runs on anything with a browser phones, tablets, Raspberry Pi, even ESP32 microcontrollers. The device serves a single HTML page and pushes data as JSON; bitwrench handles all rendering, styling, and state on the client. No Node.js, no build step, no internet connection required.
33
+ **One file, everywhere.** At ~38KB gzipped with zero dependencies, bitwrench runs on anything with a browser -- phones, tablets, Raspberry Pi, even ESP32 microcontrollers. The device serves a single HTML page and pushes data as JSON; bitwrench handles all rendering, styling, and state on the client. No Node.js, no build step, no internet connection required.
33
34
 
34
35
  Structure, styling, state, and server rendering are all handled as JavaScript objects:
35
36
 
36
- - **No build toolchain** works with a `<script>` tag
37
- - **50+ ready-made components** buttons, tables, modals, forms, charts, toasts one `make*()` call each, returns a composable TACO
38
- - **CSS from JavaScript** `bw.css()` generates stylesheets, `bw.s()` composes inline styles, `bw.loadStyles()` or `bw.makeStyles()` derives a complete theme from 2 seed colors
39
- - **Reactive state** `bw.component()` provides `.get()/.set()` with `${template}` bindings; `bw.pub()`/`bw.sub()` for cross-component messaging
40
- - **Dual rendering** same object renders to live DOM (`bw.DOM()`) or HTML string (`bw.html()`) for SSR, emails, or static sites
41
- - **Server-driven UI** push UI updates from any backend (Python, C, Rust, Go) over SSE; `client.screenshot()` captures the page back as PNG/JPEG
42
- - **CLI** `bwcli` converts Markdown, HTML, and JSON to styled standalone pages
43
- - **Utilities** color interpolation, random data, lorem ipsum, cookies, URL params, file I/O
37
+ - **No build toolchain** -- works with a `<script>` tag
38
+ - **50+ ready-made components** -- buttons, tables, modals, forms, charts, toasts -- one `make*()` call each, returns a composable TACO
39
+ - **CSS from JavaScript** -- `bw.css()` generates stylesheets, `bw.s()` composes inline styles, `bw.loadStyles()` derives a complete design system from 2 seed colors
40
+ - **Reactive state** -- `o.state` + `o.render` + `bw.update()` for stateful components; `bw.pub()`/`bw.sub()` for cross-component messaging
41
+ - **Dual rendering** -- same object renders to live DOM (`bw.DOM()`) or HTML string (`bw.html()`) for SSR, emails, or static sites
42
+ - **Server-driven UI** -- push UI updates from any backend (Python, C, Rust, Go) over SSE; `client.screenshot()` captures the page back as PNG/JPEG
43
+ - **CLI** -- `bwcli` converts Markdown, HTML, and JSON to styled standalone pages
44
+ - **Utilities** -- color interpolation, random data, lorem ipsum, cookies, URL params, file I/O
44
45
 
45
46
 
46
47
 
@@ -50,14 +51,14 @@ Bitwrench uses JavaScript equivalents for most forms of front-end development. H
50
51
 
51
52
  | You're using | For | Bitwrench equivalent |
52
53
  |---|---|---|
53
- | React / Vue / Svelte | Components + reactivity | `{t, a, c, o}` objects + `bw.component()` |
54
- | JSX / templates | Markup-in-JS | Native JS objects no compiler |
54
+ | React / Vue / Svelte | Components + reactivity | `{t, a, c, o}` objects + `o.state` + `o.render` |
55
+ | JSX / templates | Markup-in-JS | Native JS objects -- no compiler |
55
56
  | Tailwind / CSS-in-JS | Styling | `bw.css()`, `bw.s()` style composition |
56
57
  | Sass / PostCSS | CSS generation | `bw.css()` from JS objects (supports @media, @keyframes) |
57
58
  | ThemeProvider / CSS vars | Theming | `bw.loadStyles()` / `bw.makeStyles()` from 2 seed colors |
58
- | Streamlit / Gradio | Server-driven UI | bwserve SSE from any language (Python, Go, C, Rust) |
59
- | Redux / Zustand / Pinia | State management | `bw.component()` `.get()/.set()` + `bw.pub()/sub()` |
60
- | Vite / webpack / Babel | Build tooling | Not needed open the HTML file |
59
+ | Streamlit / Gradio | Server-driven UI | bwserve SSE -- from any language (Python, Go, C, Rust) |
60
+ | Redux / Zustand / Pinia | State management | `o.state` + `bw.update()` + `bw.pub()/sub()` |
61
+ | Vite / webpack / Babel | Build tooling | Not needed -- open the HTML file |
61
62
 
62
63
  See the [Framework Translation Table](docs/framework-translation-table.md) for side-by-side code comparisons across 22 operations.
63
64
 
@@ -116,32 +117,34 @@ Or include directly in a page:
116
117
 
117
118
  ## Adding State
118
119
 
119
- Wrap any TACO in `bw.component()` to get a reactive component with `.get()`, `.set()`, and template bindings:
120
+ Add `o.state` and `o.render` to any TACO to make it stateful. The render function is called with the DOM element, and state lives on `el._bw_state`. Call `bw.update(el)` to re-render:
120
121
 
121
122
  ```javascript
122
- var counter = bw.component({
123
- t: 'div', c: [
124
- { t: 'span', c: 'Count: ${count}' },
125
- { t: 'button', c: '+1', a: {
126
- onclick: function() { counter.set('count', counter.get('count') + 1); }
127
- }}
128
- ],
123
+ var counter = {
124
+ t: 'div',
129
125
  o: {
130
126
  state: { count: 0 },
131
- methods: {
132
- reset: function(comp) { comp.set('count', 0); }
127
+ render: function(el) {
128
+ var s = el._bw_state;
129
+ bw.DOM(el, {
130
+ t: 'div', c: [
131
+ { t: 'h3', c: 'Count: ' + s.count },
132
+ bw.makeButton({ text: '+1', onclick: function() {
133
+ s.count++;
134
+ bw.update(el);
135
+ }})
136
+ ]
137
+ });
133
138
  }
134
139
  }
135
- });
140
+ };
136
141
 
137
142
  bw.DOM('#app', counter);
138
- counter.set('count', 42); // DOM updates automatically
139
- counter.reset(); // methods from o.methods are callable on the handle
140
143
  ```
141
144
 
142
- > **Important: event handlers go in `a: { onclick: fn }`, not in `o.mounted`.** Handlers attached via `addEventListener` in `o.mounted` are silently lost when a component re-renders. Always use `onclick`/`onchange`/etc. inside `a:` bitwrench re-attaches them on every render automatically.
145
+ > **Important: event handlers go in `a: { onclick: fn }`, not in `o.mounted`.** Handlers attached via `addEventListener` in `o.mounted` are silently lost when a component re-renders. Always use `onclick`/`onchange`/etc. inside `a:` -- bitwrench re-attaches them on every render automatically.
143
146
 
144
- For low-level control, you can also use `o.render` + `bw.update()` directly — see the [State Management guide](docs/state-management.md).
147
+ See the [State Management guide](docs/state-management.md) for the full three-level component model.
145
148
 
146
149
  For communication between components, use pub/sub:
147
150
 
@@ -176,7 +179,7 @@ bw.responsive('.hero', {
176
179
 
177
180
  ## Theming
178
181
 
179
- `bw.loadStyles()` derives a design system buttons, alerts, badges, cards, forms, tables, hover states, focus rings from two seed colors. Themes are scoped to DOM subtrees, so different sections of a page can use different themes. `toggleStyles()` switches between primary and alternate palettes:
182
+ `bw.loadStyles()` derives a complete design system -- buttons, alerts, badges, cards, forms, tables, hover states, focus rings -- from two seed colors. Styles can be scoped to DOM subtrees, so different sections of a page can use different themes. `bw.toggleStyles()` switches between primary and alternate palettes:
180
183
 
181
184
  ```javascript
182
185
  bw.loadStyles({
@@ -192,22 +195,24 @@ bw.toggleStyles(); // switch between primary and alternate palettes
192
195
 
193
196
  | Function | Description |
194
197
  |---|---|
195
- | `bw.html(obj)` | Convert an object to an HTML string |
196
- | `bw.DOM(selector, obj)` | Mount an object to a DOM element |
198
+ | `bw.html(obj)` | Convert a TACO to an HTML string |
199
+ | `bw.DOM(selector, obj)` | Mount a TACO to a DOM element |
200
+ | `bw.mount(selector, obj)` | Like `bw.DOM()` but returns the root element for `el.bw` access |
197
201
  | `bw.raw(str)` | Mark a string as pre-escaped HTML (no double-escaping) |
198
- | `bw.component(taco)` | Wrap a TACO in a ComponentHandle with `.get()/.set()` reactive API |
199
202
  | `bw.css(rules)` | Generate CSS from a JS object |
200
203
  | `bw.s(...objs)` | Compose inline style objects into a style string |
201
204
  | `bw.responsive(sel, breakpoints)` | Generate `@media` CSS rules from JS |
202
- | `bw.loadStyles()` | Inject the built-in stylesheet (or pass config to theme) |
203
- | `bw.makeStyles(config)` | Generate a scoped theme from seed colors (returns styles object) |
205
+ | `bw.loadStyles(config?)` | Load structural CSS (no args) or generate + apply a theme from seed colors |
206
+ | `bw.makeStyles(config)` | Generate a theme from seed colors (returns styles object) |
207
+ | `bw.applyStyles(styles)` | Inject a generated styles object's CSS into the document |
204
208
  | `bw.toggleStyles()` | Switch between primary and alternate palettes |
205
- | `bw.patch(id, content)` | Update a specific element by UUID |
209
+ | `bw.clearStyles()` | Remove injected theme styles |
210
+ | `bw.patch(id, content)` | Update a specific element by id or UUID |
206
211
  | `bw.update(el)` | Re-render via the element's `o.render` function |
207
- | `bw.message(target, action, data)` | Send a message to a component by tag name |
212
+ | `bw.message(target, action, data)` | Dispatch a method call to a component's `el.bw` handle |
208
213
  | `bw.pub(topic, detail)` | Publish a message to subscribers |
209
214
  | `bw.sub(topic, handler)` | Subscribe to a topic; returns an unsub function |
210
- | `bw.inspect(target)` | Debug a component in the browser console |
215
+ | `bw.inspect(target)` | Debug a component's state, handles, and metadata in the console |
211
216
  | `bw.apply(msg)` | Apply a bwserve protocol message to the DOM |
212
217
 
213
218
  See the full [API Reference](https://deftio.github.io/bitwrench/pages/08-api-reference.html) for all functions.
@@ -231,7 +236,7 @@ Flags: `--output/-o`, `--standalone/-s`, `--cdn`, `--theme/-t`, `--css/-c`, `--t
231
236
 
232
237
  ### Pipe Server
233
238
 
234
- `bwcli serve` turns any language into a bwserve backend send JSON protocol messages via HTTP POST or stdin, and connected browsers update in real time:
239
+ `bwcli serve` turns any language into a bwserve backend -- send JSON protocol messages via HTTP POST or stdin, and connected browsers update in real time:
235
240
 
236
241
  ```bash
237
242
  bwcli serve --port 8080 --input-port 9000
@@ -253,72 +258,72 @@ All formats include source maps. A separate CSS file (`bitwrench.css`) is also a
253
258
 
254
259
  **Start here:**
255
260
 
256
- - **[Thinking in Bitwrench](docs/thinking-in-bitwrench.md)** the complete guide. Covers TACO, styling (`bw.css`, `bw.s`, `bw.responsive`), composition, events, the three-level component model, bwserve, and common patterns
257
- - **[LLM Guide](docs/llm-bitwrench-guide.md)** compact single-file reference with all APIs, patterns, and rules. Designed for AI-assisted development but works as a cheat sheet for anyone
261
+ - **[Thinking in Bitwrench](docs/thinking-in-bitwrench.md)** -- the complete guide. Covers TACO, styling (`bw.css`, `bw.s`, `bw.responsive`), composition, events, the three-level component model, bwserve, and common patterns
262
+ - **[LLM Guide](docs/llm-bitwrench-guide.md)** -- compact single-file reference with all APIs, patterns, and rules. Designed for AI-assisted development but works as a cheat sheet for anyone
258
263
 
259
264
  **Reference guides** (in `docs/`):
260
265
 
261
- - [TACO Format](docs/taco-format.md) the `{t, a, c, o}` object format
262
- - [State Management](docs/state-management.md) three-level component model, ComponentHandle, reactive state
263
- - [Component Library](docs/component-library.md) all 50+ `make*()` functions with signatures and examples
264
- - [Theming](docs/theming.md) palette-driven theme generation, presets, design tokens
265
- - [CLI](docs/cli.md) the `bwcli` command for file conversion and pipe server
266
- - [bwserve](docs/bwserve.md) server-driven UI protocol (SSE, actions, embedded devices)
266
+ - [TACO Format](docs/taco-format.md) -- the `{t, a, c, o}` object format
267
+ - [State Management](docs/state-management.md) -- three-level component model, stateful TACO, reactive state
268
+ - [Component Library](docs/component-library.md) -- all 50+ `make*()` functions with signatures and examples
269
+ - [Theming](docs/theming.md) -- palette-driven theme generation, presets, design tokens
270
+ - [CLI](docs/cli.md) -- the `bwcli` command for file conversion and pipe server
271
+ - [bwserve](docs/bwserve.md) -- server-driven UI protocol (SSE, actions, embedded devices)
267
272
 
268
273
  **Tutorials:**
269
274
 
270
- - [Build a Website](docs/tutorial-website.md) multi-section landing page from TACO objects
271
- - [bwserve Dashboard](docs/tutorial-bwserve.md) Streamlit-style server-push dashboard
272
- - [ESP32 IoT Dashboard](docs/tutorial-embedded.md) embedded sensor dashboard with C macros
275
+ - [Build a Website](docs/tutorial-website.md) -- multi-section landing page from TACO objects
276
+ - [bwserve Dashboard](docs/tutorial-bwserve.md) -- Streamlit-style server-push dashboard
277
+ - [ESP32 IoT Dashboard](docs/tutorial-embedded.md) -- embedded sensor dashboard with C macros
273
278
 
274
279
  **Interactive demos** (live site):
275
280
 
276
- - [Quick Start](https://deftio.github.io/bitwrench/pages/00-quick-start.html) first steps with `bw.DOM()`
277
- - [Components](https://deftio.github.io/bitwrench/pages/01-components.html) all 50+ UI components with live demos
278
- - [Styling & Theming](https://deftio.github.io/bitwrench/pages/03-styling.html) CSS generation, `bw.s()`, and theming strategies
279
- - [State & Interactivity](https://deftio.github.io/bitwrench/pages/05-state.html) state patterns and ComponentHandle
280
- - [Tic Tac Toe Tutorial](https://deftio.github.io/bitwrench/pages/06-tic-tac-toe-tutorial.html) step-by-step game with state management
281
- - [Framework Comparison](https://deftio.github.io/bitwrench/pages/07-framework-comparison.html) bitwrench vs React, Vue, Svelte
282
- - [Themes](https://deftio.github.io/bitwrench/pages/10-themes.html) interactive theme generator with presets and CSS export
281
+ - [Quick Start](https://deftio.github.io/bitwrench/pages/00-quick-start.html) -- first steps with `bw.DOM()`
282
+ - [Components](https://deftio.github.io/bitwrench/pages/01-components.html) -- all 50+ UI components with live demos
283
+ - [Styling & Theming](https://deftio.github.io/bitwrench/pages/03-styling.html) -- CSS generation, `bw.s()`, and theming strategies
284
+ - [State & Interactivity](https://deftio.github.io/bitwrench/pages/05-state.html) -- state patterns and stateful TACO
285
+ - [Tic Tac Toe Tutorial](https://deftio.github.io/bitwrench/pages/06-tic-tac-toe-tutorial.html) -- step-by-step game with state management
286
+ - [Framework Comparison](https://deftio.github.io/bitwrench/pages/07-framework-comparison.html) -- bitwrench vs React, Vue, Svelte
287
+ - [Themes](https://deftio.github.io/bitwrench/pages/10-themes.html) -- interactive theme generator with presets and CSS export
283
288
 
284
289
  **Example apps** (in `examples/`):
285
290
 
286
- - [Ember & Oak Coffee Co.](examples/ember-and-oak/) full landing page: theme, cart, search, charts, accordion, timeline
287
- - [SunForge Landing Page](examples/landing-page/) polished marketing page with zero reactive state, pure BCCL composition
288
- - [Todo App](examples/todo-app/) bw.component() with pub/sub
289
- - [Metrics Dashboard](examples/dashboard/) live stat cards, bar chart, pub/sub, responsive layout
290
- - [Signup Wizard](examples/wizard/) multi-step form, state transitions, bw.raw()
291
- - [Live Feed](examples/live-feed/) real-time stream, bw.patch(), slide-in animation
292
- - [IoT Dashboard](examples/embedded/) ESP32-style sensor dashboard with SSE
293
- - [bwserve Counter](examples/client-server/) server-driven UI demo
294
- - [LLM Chat](examples/llm-chat/) streaming chat via bwserve + Ollama/OpenAI
291
+ - [Ember & Oak Coffee Co.](examples/ember-and-oak/) -- full landing page: theme, cart, search, charts, accordion, timeline
292
+ - [SunForge Landing Page](examples/landing-page/) -- polished marketing page with zero reactive state, pure BCCL composition
293
+ - [Todo App](examples/todo-app/) -- stateful TACO with pub/sub
294
+ - [Metrics Dashboard](examples/dashboard/) -- live stat cards, bar chart, pub/sub, responsive layout
295
+ - [Signup Wizard](examples/wizard/) -- multi-step form, state transitions, bw.raw()
296
+ - [Live Feed](examples/live-feed/) -- real-time stream, bw.patch(), slide-in animation
297
+ - [IoT Dashboard](examples/embedded/) -- ESP32-style sensor dashboard with SSE
298
+ - [bwserve Counter](examples/client-server/) -- server-driven UI demo
299
+ - [LLM Chat](examples/llm-chat/) -- streaming chat via bwserve + Ollama/OpenAI
295
300
 
296
301
  ## FAQ
297
302
 
298
- **Is this a framework?** No. Bitwrench is a library (~39KB gzipped). No lifecycle to learn, no project structure to follow. Import it, call functions, done.
303
+ **Is this a framework?** -- No. Bitwrench is a library (~38KB gzipped). No lifecycle to learn, no project structure to follow. Import it, call functions, done.
299
304
 
300
- **Does it scale to large apps?** Bitwrench targets single-page tools, dashboards, prototypes, embedded UIs, and content sites apps where a single HTML file or a handful of files is the right form factor. For a 500-route SPA with team-scale state management, React or Vue is a better fit.
305
+ **Does it scale to large apps?** -- Bitwrench targets single-page tools, dashboards, prototypes, embedded UIs, and content sites -- apps where a single HTML file or a handful of files is the right form factor. For a 500-route SPA with team-scale state management, React or Vue is a better fit.
301
306
 
302
- **How does bitwrench compare to React/Vue?** They solve different problems at different scales. React and Vue provide a component model, virtual DOM, and ecosystem for large team-built SPAs. Bitwrench provides rendering and state primitives in a single file with no build step, aimed at single-page tools, dashboards, embedded devices, and server-driven UIs. They coexist fine use whichever fits the job.
307
+ **How does bitwrench compare to React/Vue?** -- They solve different problems at different scales. React and Vue provide a component model, virtual DOM, and ecosystem for large team-built SPAs. Bitwrench provides rendering and state primitives in a single file with no build step, aimed at single-page tools, dashboards, embedded devices, and server-driven UIs. They coexist fine -- use whichever fits the job.
303
308
 
304
- **How does CSS work?** Bitwrench doesn't own your CSS. Use any external stylesheet, Tailwind, or CSS file you want bitwrench doesn't interfere. On top of that, `bw.css()` generates CSS from JS objects (with `@media`, `@keyframes`, pseudo-classes), `bw.s()` composes inline style objects, and `bw.loadStyles()` or `bw.makeStyles()` derives a complete theme from 2 seed colors. You can use all three together or none at all.
309
+ **How does CSS work?** -- Bitwrench doesn't own your CSS. Use any external stylesheet, Tailwind, or CSS file you want -- bitwrench doesn't interfere. On top of that, `bw.css()` generates CSS from JS objects (with `@media`, `@keyframes`, pseudo-classes), `bw.s()` composes inline style objects, and `bw.loadStyles()` derives a complete design system from 2 seed colors. You can use all three together or none at all.
305
310
 
306
- **What's the difference between `bw.DOM()` and `bw.html()`?** Same TACO input, two outputs. `bw.DOM('#app', taco)` mounts live DOM elements in a browser. `bw.html(taco)` returns an HTML string use it in Node.js scripts, email generators, static site builds, or anywhere you need markup without a browser. One object format, two rendering modes.
311
+ **What's the difference between `bw.DOM()` and `bw.html()`?** -- Same TACO input, two outputs. `bw.DOM('#app', taco)` mounts live DOM elements in a browser. `bw.html(taco)` returns an HTML string -- use it in Node.js scripts, email generators, static site builds, or anywhere you need markup without a browser. One object format, two rendering modes.
307
312
 
308
- **What is bwserve?** bwserve lets any server push UI updates to a browser over SSE. The server sends TACO objects as JSON; the browser renders them. It's language-agnostic the server can be Python, Go, Rust, C, or a shell script. Anything that can write JSON to an HTTP response can drive a bitwrench UI. See the [bwserve docs](docs/bwserve.md).
313
+ **What is bwserve?** -- bwserve lets any server push UI updates to a browser over SSE. The server sends TACO objects as JSON; the browser renders them. It's language-agnostic -- the server can be Python, Go, Rust, C, or a shell script. Anything that can write JSON to an HTTP response can drive a bitwrench UI. See the [bwserve docs](docs/bwserve.md).
309
314
 
310
- **Can I use bitwrench on embedded devices?** Yes this is a primary use case. An ESP32 or Raspberry Pi serves one HTML page with bitwrench loaded, then pushes sensor data as JSON patches over SSE. The device never generates HTML. See the [ESP32 tutorial](docs/tutorial-embedded.md).
315
+ **Can I use bitwrench on embedded devices?** -- Yes -- this is a primary use case. An ESP32 or Raspberry Pi serves one HTML page with bitwrench loaded, then pushes sensor data as JSON patches over SSE. The device never generates HTML. See the [ESP32 tutorial](docs/tutorial-embedded.md).
311
316
 
312
- **Can I use it with TypeScript?** Yes. Type declarations are included. TACO objects are plain JSON-compatible objects that TypeScript infers naturally.
317
+ **Can I use it with TypeScript?** -- Yes. Type declarations are included. TACO objects are plain JSON-compatible objects that TypeScript infers naturally.
313
318
 
314
- **What about accessibility?** BCCL components emit semantic HTML with ARIA attributes where applicable. You can add any `aria-*` attribute via `a: { 'aria-label': '...' }`.
319
+ **What about accessibility?** -- BCCL components emit semantic HTML with ARIA attributes where applicable. You can add any `aria-*` attribute via `a: { 'aria-label': '...' }`.
315
320
 
316
321
  ## Development
317
322
 
318
323
  ```bash
319
324
  npm install # install dev dependencies
320
325
  npm run build # build all dist formats (UMD, ESM, CJS, ES5)
321
- npm test # run unit tests (1000+ tests)
326
+ npm test # run unit tests (1400+ tests, 96% coverage)
322
327
  npm run test:cli # run CLI tests
323
328
  npm run test:e2e # run Playwright browser tests
324
329
  npm run lint # run ESLint
@@ -327,4 +332,4 @@ npm run cleanbuild # full production build with SRI hashes
327
332
 
328
333
  ## License
329
334
 
330
- [BSD-2-Clause](./LICENSE.txt) (c) M. A. Chatterjee / [deftio](https://github.com/deftio)
335
+ [BSD-2-Clause](./LICENSE.txt) -- (c) M. A. Chatterjee / [deftio](https://github.com/deftio)