@hyperfixi/vite-plugin 3.3.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,19 +1,21 @@
1
1
  # @hyperfixi/vite-plugin
2
2
 
3
- Zero-config Vite plugin that automatically generates minimal LokaScript bundles based on detected hyperscript usage.
3
+ Zero-config Vite plugin that emits a bundle on [`@hyperfixi/engine`](../engine/README.md) registering only the grammar modules your hyperscript uses.
4
4
 
5
5
  ## Features
6
6
 
7
7
  - **Zero-config**: Just add the plugin and it works
8
8
  - **Automatic detection**: Scans HTML, Vue, Svelte, JSX/TSX for `_="..."` attributes
9
- - **Minimal bundles**: Only includes commands and blocks you actually use
9
+ - **Minimal bundles**: Registers only the engine modules your commands and blocks need (17.9 KB gzipped for three commands, 34.4 KB for everything)
10
+ - **Upstream's grammar**: The engine is gated by `_hyperscript`'s own test suite, so what works on `hyperfixi-hs.js` works in the generated bundle
11
+ - **Multilingual**: Non-English scripts are translated as the engine reads them (the attribute stays as written)
10
12
  - **HMR support**: Re-generates bundle when you add new hyperscript
11
13
  - **Framework agnostic**: Works with any Vite-based project
12
14
 
13
15
  ## Installation
14
16
 
15
17
  ```bash
16
- npm install @hyperfixi/vite-plugin @hyperfixi/core
18
+ npm install @hyperfixi/vite-plugin @hyperfixi/engine
17
19
  ```
18
20
 
19
21
  ## Quick Start
@@ -29,7 +31,7 @@ export default {
29
31
 
30
32
  ```javascript
31
33
  // main.js
32
- import 'hyperfixi'; // Auto-generated minimal bundle
34
+ import 'hyperfixi'; // the generated bundle: the engine + your modules
33
35
  ```
34
36
 
35
37
  ```html
@@ -40,47 +42,44 @@ import 'hyperfixi'; // Auto-generated minimal bundle
40
42
  ## How It Works
41
43
 
42
44
  1. **Scans** your HTML/Vue/Svelte/JSX files for `_="..."` attributes
43
- 2. **Detects** which commands, blocks, and expressions you use
44
- 3. **Generates** a minimal bundle with only the features you need
45
+ 2. **Detects** which commands, blocks, and expression kinds you use
46
+ 3. **Emits** a bundle on [`@hyperfixi/engine`](../engine/README.md) that registers only
47
+ the grammar modules those need — a bundle on the engine is the list passed to
48
+ `register()`, so there is one tier: the modules. The emitted module is a few
49
+ lines; Vite bundles the engine's modules into it.
45
50
  4. **Regenerates** on HMR when you add new hyperscript
46
51
 
47
- ## Compile Mode (Minimal Bundle Size)
48
-
49
- When bundle size is the priority, use **compile mode** to pre-compile hyperscript to JavaScript at build time:
50
-
51
52
  ```javascript
52
- hyperfixi({
53
- mode: 'compile', // ~500 bytes gzip vs ~8KB for interpret mode
54
- });
53
+ // What the virtual module looks like for a page using toggle, add and an if block
54
+ import {
55
+ api,
56
+ boot,
57
+ register,
58
+ on,
59
+ conversions,
60
+ add,
61
+ toggle,
62
+ ifCommand,
63
+ toggleElement,
64
+ } from '@hyperfixi/engine';
65
+ register(on, conversions, add, toggle, ifCommand, toggleElement);
66
+ window.hyperfixi = api; // the same object boot() installs as window._hyperscript
67
+ boot();
68
+ export default api;
55
69
  ```
56
70
 
57
- **Trade-offs:**
58
-
59
- | Feature | Interpret (default) | Compile |
60
- | ------------------- | ------------------- | --------------- |
61
- | Bundle size | ~8 KB gzip | ~500 bytes gzip |
62
- | Dynamic `execute()` | ✓ | ✗ |
63
- | Block commands | ✓ | ✗ |
64
- | Build complexity | Lower | Higher |
65
-
66
- **When to use compile mode:**
67
-
68
- - Landing pages with simple interactions (toggles, shows, hides)
69
- - Performance-critical apps where every KB matters
70
- - Static sites where hyperscript is just for UI polish
71
+ The engine's parser is upstream `_hyperscript`'s grammar (its vendored test suite
72
+ is the gate), so a generated bundle reads exactly what `hyperfixi-hs.js` reads;
73
+ only the command set differs. Scanning is by word, so a name the engine has no
74
+ module for (a false positive in a string, or a form the engine dropped) selects
75
+ nothing; `debug: true` lists them.
71
76
 
72
- **When NOT to use compile mode:**
77
+ ## Compile Mode (removed in 4.0)
73
78
 
74
- - Apps using `if`, `repeat`, `fetch`, or `for each` blocks
75
- - Dynamic hyperscript generation at runtime via `execute()`
76
- - Apps that need the full hyperscript power
77
-
78
- **Supported commands in compile mode:**
79
- toggle, add, remove, show, hide, focus, blur, set, get, put, increment, decrement, log, send, trigger, wait
80
-
81
- **Positional expressions:** next, previous, parent, first, last, closest
82
-
83
- **Animations:** Use CSS transitions - toggling classes triggers them automatically. No special `transition` command needed.
79
+ `mode: 'compile'` pre-compiled handlers to JavaScript with `@hyperfixi/core`'s hybrid
80
+ parser (~500 bytes for a page of toggles). It was parked with the AOT compiler (owner
81
+ decision 2026-10-03) and left with core's parser in 4.0. Selecting it logs a warning and
82
+ builds the engine-module bundle above, which is the product.
84
83
 
85
84
  ## Multilingual & Semantic Parsing
86
85
 
@@ -158,40 +157,44 @@ per language, so the final size depends on Vite's tree-shaking; for reference, t
158
157
  prebuilt standalone semantic bundles range from ~90 KB (no languages) to ~260 KB
159
158
  (all 24 languages) gzipped, measured locally — see `docs/BROWSER_BUNDLES.md` in the repo.
160
159
 
161
- ### Tiered Bundle Architecture
162
-
163
- ```text
164
- Level 0: Base HybridParser (default)
165
- ↓ semantic: true
166
- Level 1: + Semantic English
167
- ↓ languages detected/specified
168
- Level 2: + Regional Semantic Bundle
169
- ↓ grammar: true
170
- Level 3: + translateHyperscript() (semantic's translate)
171
- ```
172
-
173
- Each level adds bundle weight; the plugin picks the lowest level that covers the
174
- features and languages it detects in your source.
175
-
176
- ## htmx v4 reactive / streaming surface
160
+ ### How the multilingual bundle works
177
161
 
178
- The scanner detects `hx-live`, `sse-connect` / `sse-swap`, `ws-connect` / `ws-send`, and `bind <var> to <expr>.<prop>` inside `_=` bodies. When any of those is found in the project, the generated bundle is the `hyperfixi-hx-v4.js` premade bundle (full runtime + `@hyperfixi/reactivity` + htmx-compat auto-installed + SSE/WS).
179
-
180
- ```html
181
- <!-- Triggers the hx-v4 fallback automatically -->
182
- <div hx-live="put $count into me"></div>
183
- <div sse-connect="/stream" sse-swap="tick" hx-target="#out"></div>
184
- <form ws-send><input name="msg" /></form>
185
- <input _="on input bind $val to me.value" />
186
- ```
187
-
188
- The slim minimal-bundle generator can't satisfy these features (its parser/runtime doesn't know `live`/`when`/`bind`, doesn't route writes through `notifyGlobalWrite`, and doesn't ship the SSE/WS modules), so the plugin opts into the full hx-v4 bundle for correctness over size. If size matters more, drop the v4 attributes and use plain `_=` / v1-v2 htmx attributes.
162
+ Text is the interchange. When semantic parsing is enabled the emitted bundle imports
163
+ `@lokascript/semantic/core` plus one `@lokascript/semantic/languages/<code>` module
164
+ per language and installs a **source transform** on the engine
165
+ (`api.addSourceTransform`): a non-English script is parsed in its language and
166
+ rendered to English as the engine reads it, and the element's attribute stays as
167
+ written. The language comes from `data-lang`, `data-hyperscript-lang`, the nearest
168
+ `lang` ancestor, or the document's `lang`. English scripts pass through untouched.
169
+
170
+ The API gains `translateSource(src, element)` (what the transform does, for one
171
+ script) and, with `grammar: true`, `translateHyperscript(code, from, to)`.
172
+
173
+ Measured 2026-10-03, gzipped: three commands + Spanish is ~209 KB, of which the
174
+ engine is 18 KB — the rest is semantic's parser and the language. Keep the language
175
+ list to what the page uses.
176
+
177
+ ## Reactivity, htmx, and streaming
178
+
179
+ `live … end`, `when … changes`, `bind` and `^var` inside `_=` bodies are the
180
+ engine's reactive features: the scanner detects them and the bundle registers the
181
+ engine's `reactivity` and `liveTemplates` modules (+2 KB gzipped). No separate
182
+ bundle, no separate package.
183
+
184
+ htmx is not bundled. Load htmx 4 beside the generated bundle for `hx-get` and
185
+ friends, `hx-sse` / `hx-ws` for streams, and
186
+ [`@lokascript/htmx-adapter`](../htmx-adapter/README.md) for localized attribute
187
+ names (the two stacks in [docs/BROWSER_BUNDLES.md](../../docs/BROWSER_BUNDLES.md)).
188
+ When the scan finds htmx attributes (or `htmx: true` is set) the bundle hands
189
+ swapped-in content to the engine on `htmx:load` / `htmx:afterSettle`. A
190
+ hyperscript-bodied `hx-live` attribute is a `_="live … end"` block on the engine;
191
+ `sse-connect` / `ws-connect` are htmx 4's `hx-sse` / `hx-ws`.
189
192
 
190
193
  ## Options
191
194
 
192
195
  ```javascript
193
196
  hyperfixi({
194
- // Bundle mode: 'interpret' (default) or 'compile'
197
+ // Bundle mode: 'interpret' (default; 'compile' was removed in 4.0, see above)
195
198
  mode: 'interpret',
196
199
 
197
200
  // Extra commands to always include (for dynamic hyperscript)
@@ -201,9 +204,12 @@ hyperfixi({
201
204
  // Always include positional expressions
202
205
  positional: true,
203
206
 
204
- // Enable htmx attribute compatibility
207
+ // Hand htmx-swapped content to the engine (on by default when hx-* attributes are found)
205
208
  htmx: true,
206
209
 
210
+ // Dev-server bundle: 'everything' (the whole engine, faster rebuilds) or 'auto' (the module list)
211
+ devFallback: 'auto',
212
+
207
213
  // Debug logging
208
214
  debug: true,
209
215
 
@@ -228,18 +234,13 @@ hyperfixi({
228
234
 
229
235
  ## Detected Features
230
236
 
231
- ### Commands
232
-
233
- toggle, add, remove, removeClass, show, hide, set, get, put, append, take,
234
- increment, decrement, log, send, trigger, wait, transition, go, call, focus, blur, return
235
-
236
- ### Blocks (5)
237
-
238
- if, repeat, for, while, fetch
239
-
240
- ### Positional Expressions (6)
241
-
242
- first, last, next, previous, closest, parent
237
+ The scanner's word list is **derived from the engine** at load: every command and
238
+ feature keyword its modules register (`add`, `call`, `for`, `tell`, `make`, …).
239
+ Blocks: `if`, `repeat`, `for`, `while`, `fetch`. Expression kinds that select the
240
+ engine's optional `expressionsExtra` module: `first`, `last`, `next`, `previous`,
241
+ `closest`, `parent`, `random`, `where`, `sorted by`, `mapped to`, `split by`,
242
+ `joined by`, `some`, `beep!`. Also `new X(…)` (the engine's `construct`
243
+ addition) and `cookies`. `on` and the `as` conversions are always registered.
243
244
 
244
245
  ## Virtual Module
245
246
 
@@ -262,12 +263,22 @@ When you add new hyperscript to your HTML files, the plugin:
262
263
 
263
264
  ## Bundle Size Comparison
264
265
 
265
- | Usage | Generated Size (gzip) | vs Full Bundle |
266
- | ------------------- | --------------------- | -------------- |
267
- | 3 commands | ~5 KB | 90% smaller |
268
- | 6 commands | ~6.5 KB | 85% smaller |
269
- | 9 commands + blocks | ~8 KB | 80% smaller |
270
- | All features | ~40 KB | same |
266
+ Measured 2026-10-03 (esbuild, minified, gzipped; `@hyperfixi/engine` 3.3.0):
267
+
268
+ | Usage | Generated size (gzip) |
269
+ | ---------------------------------------------------- | --------------------- |
270
+ | 3 commands (toggle, add, remove) | 17.9 KB |
271
+ | 7 commands (+ show, hide, put, set) | 18.7 KB |
272
+ | 5 commands + `if` / `repeat` | 19.6 KB |
273
+ | 10 commands + `if` / `repeat` / `fetch` + positional | 22.8 KB |
274
+ | + reactivity (`live` / `when` / `bind`) | 20.3 KB |
275
+ | everything (the dev fallback; = `hyperfixi-hs.js`) | 34.4 KB |
276
+
277
+ The engine's fixed cost (tokenizer, parser, the core expression kinds, runtime) is
278
+ 13.8 KB, so there is no sub-5 KB tier any more: the 3.x generator's regex "lite"
279
+ parser emitted 3.9 KB for three commands, its hybrid parser 12–16 KB, and any page
280
+ using `fetch` or one of twenty other commands fell back to the 352 KB `hyperfixi.js`.
281
+ What you get in exchange is one grammar, gated by upstream's own test suite.
271
282
 
272
283
  ## Edge Cases
273
284
 
@@ -297,23 +308,17 @@ hyperfixi({
297
308
 
298
309
  ## Monorepo Development
299
310
 
300
- When developing in the hyperfixi monorepo:
311
+ When developing in the hyperfixi monorepo, point the plugin at its source; the
312
+ emitted bundle's `@hyperfixi/engine` import resolves through the workspace
313
+ (build the engine first: `npm run build --prefix packages/engine`):
301
314
 
302
315
  ```javascript
303
316
  // vite.config.js
304
317
  import { hyperfixi } from '../../packages/vite-plugin/src/index.ts';
305
- import path from 'path';
306
318
 
307
319
  export default {
308
320
  plugins: [hyperfixi({ debug: true })],
309
- resolve: {
310
- alias: {
311
- '@hyperfixi/core/parser/hybrid': path.resolve(
312
- __dirname,
313
- '../../packages/core/src/parser/hybrid'
314
- ),
315
- },
316
- },
321
+ optimizeDeps: { exclude: ['hyperfixi', 'virtual:hyperfixi'] },
317
322
  };
318
323
  ```
319
324