@ape-egg/vibe 1.3.2 → 1.6.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,182 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.6.0] - 2026-02-12
4
+
5
+ ### Added
6
+
7
+ - **Watch mode** - Compiler now supports file watching with incremental compilation
8
+ - New `--watch` flag monitors source files for changes and automatically recompiles
9
+ - Intelligent change detection tracks affected files and their dependencies
10
+ - Transitive dependency tracking: changes to components trigger recompilation of pages using them
11
+ - Blacklist support: watch mode respects SKIP_FILES patterns (tests/, node_modules/, etc.)
12
+ - Debounced file events (300ms) prevent excessive compilation during rapid changes
13
+ - Outputs only changed files for fast incremental builds
14
+ - First compile shows full output, subsequent compiles show only deltas
15
+ - **Reserved element validation** - Compiler now prevents component naming conflicts
16
+ - New `reservedElements` config option (replaces `excludeTags`)
17
+ - Defaults to all HTML5 elements plus "component" keyword
18
+ - User-provided values append to defaults (not replace)
19
+ - Case-sensitive validation: `nav.html` → Error, `Nav.html` → OK
20
+ - Compile-time error with clear message showing conflicting filename
21
+ - Prevents runtime confusion between HTML elements and custom components
22
+ - **Component path case-sensitivity** - Component paths are now treated as case-sensitive
23
+ - `<component src="path/to/MyComponent.html">` and `<component src="path/to/mycomponent.html">` are different
24
+ - Both runtime and compiler preserve exact case in paths
25
+ - Cache keys include full case-sensitive path
26
+ - Enables PascalCase naming convention for components while supporting any casing
27
+
28
+ ### Changed
29
+
30
+ - **Component inlining architecture** - Complete rewrite from iterative to recursive fetching
31
+ - Removed MAX_ITERATIONS constant and loop-based approach
32
+ - `fetch_component_recursive()` now returns fully resolved content with all nested components inlined
33
+ - Components are cached only after being fully resolved (prevents incomplete content in cache)
34
+ - `inline_component_elements()` now does single pass (no loops)
35
+ - Significant performance improvement: sub-100ms compilation for complex nested components
36
+ - **Framework element handling** - `<component>` is now recognized as a framework element
37
+ - Never transformed to `<div>` regardless of `--elements-as-is` flag
38
+ - Custom elements (e.g., `<card>`, `<text>`) are transformed when `elements_as_is: false`
39
+ - Framework elements vs custom elements properly distinguished in compiler
40
+ - Wrapper `<component>` tags remain after inlining (expected by runtime)
41
+ - **Component inlining behavior** - Custom elements are always inlined
42
+ - `<card>` → transformed to `<component>` → inlined even with `--components-as-is`
43
+ - `--components-as-is` only affects explicit `<component src="...">` tags
44
+ - Consistent behavior: custom elements compile away, framework elements remain
45
+ - **Path normalization** - Component paths now consistently normalized
46
+ - All paths start with `/` (unless external URL)
47
+ - Cache uses normalized paths to prevent duplicates (`/components/nav.html` vs `./components/nav.html`)
48
+ - Fixes cache pollution from different path formats for same component
49
+ - **Config naming** - `excludeTags` renamed to `reservedElements` throughout codebase
50
+ - Better describes purpose (reserved from use as component names)
51
+ - Updated in Rust compiler, config files, and documentation
52
+ - Backward compatible: old config key still works but deprecated
53
+
54
+ ### Fixed
55
+
56
+ - Watch mode was compiling blacklisted files (tests/, node_modules/)
57
+ - Component inlining created infinite nested wrappers (100+ levels)
58
+ - Empty headlines in tests due to broken external component fetching
59
+ - Path case normalization could cause duplicates in component cache
60
+ - Accessibility transformation incorrectly converting `<component>` to divs
61
+ - Test expectations mismatched actual framework element behavior
62
+
63
+ ### Performance
64
+
65
+ - Watch mode incremental compilation: ~100ms for typical changes
66
+ - First full compilation: ~300-500ms
67
+ - Component fetching: recursive approach 10x faster than iterative (no MAX_ITERATIONS overhead)
68
+ - Path normalization prevents redundant fetches of same component
69
+
70
+ ---
71
+
72
+ ## [1.5.0] - 2026-02-09
73
+
74
+ ### Added
75
+
76
+ - **Nested iteration compilation** - Compiler now handles infinitely nested `<!-- each -->` blocks
77
+ - Recursive processing in `iteration_optimizer.rs` with depth counting for comment pair matching
78
+ - Nested loops compile to IIFEs (Immediately Invoked Function Expressions) with template literals
79
+ - Inner iterations inlined directly into outer batch functions for optimal performance
80
+ - Example: `<!-- each categories as cat --><!-- each cat.items as item -->` compiles to single optimized function
81
+ - **QuickJS JavaScript runtime** - Full expression evaluation at compile time
82
+ - Embedded QuickJS engine (`rquickjs = "0.6"`) for JavaScript evaluation in Rust
83
+ - No external dependencies - increases binary size by ~1-2MB
84
+ - Evaluates any JavaScript expression: `@[categories.length]`, `@[items[0]]`, `@[user.name.toUpperCase()]`
85
+ - State set in global scope: `Object.assign(globalThis, $)` matches Vibe runtime behavior
86
+ - Fast evaluation: ~160ms overhead for 35 files (~5ms per file)
87
+ - **Complete pre-rendering** - Zero FOUC with all bindings pre-rendered for SEO
88
+ - All `@[expression]` bindings evaluated and stamped into HTML at compile time
89
+ - Handles property access (`@[user.name]`), array methods (`@[categories.length]`), and complex expressions
90
+ - Nested iterations fully pre-rendered with merged state for each iteration context
91
+ - Falls back gracefully: undefined expressions left as `@[...]` for runtime hydration
92
+ - New test: `stamp_array_length` validates `.length` property evaluation
93
+
94
+ ### Changed
95
+
96
+ - **Value stamper rewrite** (`value_stamper.rs`) - Complete overhaul to use QuickJS
97
+ - Replaced JSON path resolution with JavaScript expression evaluation
98
+ - `eval_expression()` handles any valid JavaScript with state in scope
99
+ - `eval_array_path()` evaluates array paths for iteration rendering
100
+ - Iteration rendering creates merged state (parent + item + index) for nested context
101
+ - Removed manual property traversal code - JavaScript engine handles it all
102
+ - **Compiled iteration updates** - Always use compiled path when available (`iterate.js:364`)
103
+ - Previously only used compiled updates for edge cases (empty↔full, large arrays >100)
104
+ - Now uses compiled batch functions for ALL updates when manifest has `compiled.iterations.batchFn`
105
+ - Fixes issue where small array updates (3→4 items) fell through to incompatible runtime path
106
+ - Ensures consistent performance regardless of array size or transition type
107
+ - **State extraction improvements** (`state_extractor.rs`) - Better error handling
108
+ - Silently skips unparseable state objects instead of failing compilation
109
+ - Enables graceful degradation when state contains functions or complex expressions
110
+
111
+ ### Fixed
112
+
113
+ - Compiled iterations not updating when array size changes (e.g., add/remove items)
114
+ - Pre-rendering skipped for JavaScript expressions like `@[categories.length]`
115
+ - Nested iteration values showing as `@[item]` instead of actual data
116
+ - Runtime path attempting to handle compiled iterations incorrectly
117
+
118
+ ### Performance
119
+
120
+ - Pre-rendering adds ~160ms to compilation for 35 files (~435ms total, up from ~310ms)
121
+ - QuickJS evaluation: ~1-5ms per binding
122
+ - Compiled nested iterations: Same performance as shallow iterations (no recursion overhead at runtime)
123
+ - Zero runtime cost for pre-rendered bindings - HTML arrives with values already stamped
124
+
125
+ ---
126
+
127
+ ## [1.4.0] - 2026-02-09
128
+
129
+ ### Added
130
+
131
+ - **Iteration optimization** - Compiler now generates optimized batch functions for `<!-- each -->` loops
132
+ - New `iteration_optimizer.rs` module generates string-based batch render functions
133
+ - Provides 2-3x performance improvement for iteration rendering (15-17ms vs 40ms for 1000 rows)
134
+ - Only applies to shallow iterations (nested iterations still use runtime path)
135
+ - Compiled batch functions are stored in manifest and executed at runtime
136
+ - **Pre-compiled iterations runtime** (`runtime/pre-compiled-iterations.js`)
137
+ - Production implementation of compiled iteration rendering
138
+ - Uses pre-compiled batch functions from manifest generated at build time
139
+ - Based on the prototype in `_vibe-compiled-iteration-batch.js`
140
+ - Automatically falls back to runtime rendering for nested iterations or missing batch functions
141
+ - **Compiler configuration** - New `iterationsAsIs` flag
142
+ - Set to `true` in `vibe-compiler` config to skip iteration optimization
143
+ - Iterations pass through unchanged and are handled entirely by runtime
144
+ - Default: `false` (iterations are optimized)
145
+ - **Hyperspeed benchmark** - New benchmark page for measuring pre-compiled performance
146
+ - Tests iteration optimization with 1000 rows
147
+ - Compares runtime vs compiled iteration rendering
148
+ - Available at `e2e-runtime/hyperspeed-benchmark.html`
149
+ - **Compiler test coverage** for iteration compilation
150
+ - `tests/compiler/iterations/` - Tests iteration optimization is applied
151
+ - `tests/compiler/iterations-as-is/` - Tests `iterationsAsIs` flag skips optimization
152
+ - E2E tests verify compiled iterations render correctly
153
+
154
+ ### Changed
155
+
156
+ - **Renamed `runtime/hyperspeed.js` → `runtime/pre-compiled-manifest.js`**
157
+ - Better naming to reflect that it handles all pre-compiled features, not just "hyperspeed"
158
+ - Updated all imports and references throughout codebase
159
+ - **Enhanced manifest merging** - Compiler manifest now preserves compiled iteration data
160
+ - Iteration nodes retain `compiled.iterations.batchFn` from manifest during runtime merge
161
+ - Prevents compiled data from being discarded when merging with runtime tree
162
+ - **Debug logging improvements**
163
+ - Added manifest filename to debug output ("Loaded index.manifest.js, page is pre-compiled")
164
+ - Shows compiled feature count (e.g., "3 iterations optimized")
165
+ - Better visibility into which optimizations are active
166
+ - **Runtime iteration handling** - Iterations check for compiled batch functions before falling back
167
+ - `canUseCompiled()` determines if iteration can use batch function
168
+ - Falls back to runtime rendering for nested structures or missing compiled data
169
+ - Seamless integration between compiled and runtime paths
170
+
171
+ ### Fixed
172
+
173
+ - Runtime cleanup now properly handles compiled iteration nodes
174
+ - Manifest merge no longer discards compiled data from iteration nodes
175
+ - Debug logging visibility flag now correctly propagates through manifest loading
176
+ - Iteration restoration respects compiled batch functions
177
+
178
+ ---
179
+
3
180
  ## [1.3.2] - 2025-02-06
4
181
 
5
182
  ### Fixed
package/README.md CHANGED
@@ -124,6 +124,103 @@ Skip reactive processing for an element:
124
124
  <code dehydrate>@[this] displays literally</code>
125
125
  ```
126
126
 
127
+ ### Reserved Words & Gotchas
128
+
129
+ Vibe uses specific patterns and keywords that have special meaning. Avoid using these for other purposes to prevent unexpected behavior:
130
+
131
+ #### Classes & Attributes
132
+
133
+ - **`vibe-fouc`** — Class or attribute for FOUC (Flash of Unstyled Content) prevention. Automatically removed after hydration completes.
134
+ ```html
135
+ <body vibe-fouc> <!-- or class="vibe-fouc" -->
136
+ ```
137
+
138
+ - **`vibe-dehydrate`** — Class or attribute to skip reactive processing. Useful for displaying literal `@[...]` syntax in documentation.
139
+ ```html
140
+ <code vibe-dehydrate>@[variable]</code> <!-- or class="vibe-dehydrate" -->
141
+ ```
142
+
143
+ #### Element Names & Classes
144
+
145
+ - **`<component>`** — Element name for component system. Used with `src` attribute for runtime component loading, or as a wrapper for inlined components.
146
+ ```html
147
+ <component src="/path/to/component.html"></component>
148
+ ```
149
+
150
+ - **`class="component"`** — Alternative syntax for components using standard HTML elements. Useful for HTML validation or accessibility.
151
+ ```html
152
+ <div class="component" src="/path/to/component.html"></div>
153
+ ```
154
+
155
+ - **`<slot>`** — Element name for component content injection. Gets replaced with content passed between component tags.
156
+ ```html
157
+ <!-- In component file -->
158
+ <slot></slot>
159
+
160
+ <!-- Usage -->
161
+ <component src="...">
162
+ <p>This replaces the slot</p>
163
+ </component>
164
+ ```
165
+
166
+ #### Comment Syntax
167
+
168
+ - **`<!-- each -->`** / **`<!-- /each -->`** — Iteration block markers.
169
+ ```html
170
+ <!-- each items as item -->
171
+ <!-- /each -->
172
+ ```
173
+
174
+ - **`<!-- if -->`** / **`<!-- else -->`** / **`<!-- /if -->`** — Conditional block markers.
175
+ ```html
176
+ <!-- if condition -->
177
+ <!-- else -->
178
+ <!-- /if -->
179
+ ```
180
+
181
+ #### Binding Syntax
182
+
183
+ - **`@[...]`** — Reactive binding syntax. Reserved for state references.
184
+ ```html
185
+ <div>@[variable]</div>
186
+ ```
187
+
188
+ #### Global Properties
189
+
190
+ - **`window.$`** — Global reactive state object. All reactive data should be accessed through this.
191
+ ```javascript
192
+ window.$ = state({ count: 0 });
193
+ $.count++; // Triggers reactive updates
194
+ ```
195
+
196
+ - **`window.__vibeManifest`** — Internal manifest data. Used by the compiler for optimization. Don't modify.
197
+
198
+ - **`window.__vibeCompiling`** — Internal flag. Set to `true` when running in compiler context.
199
+
200
+ #### Data Attributes
201
+
202
+ - **`data-vibe-component-id`** — Internal attribute for component scoping. Automatically added to component elements. Don't use manually.
203
+
204
+ #### Event Names
205
+
206
+ - **`vibe:ready`** — Custom event fired when Vibe completes initial hydration.
207
+ ```javascript
208
+ document.addEventListener('vibe:ready', () => {
209
+ console.log('Vibe is ready');
210
+ });
211
+ ```
212
+
213
+ #### Special Attribute Meanings
214
+
215
+ - **`src`** on **`<component>`** or **`<div class="component">`** — Triggers runtime component fetching. Components without `src` are treated as inline wrappers.
216
+ ```html
217
+ <!-- Both work the same way -->
218
+ <component src="/components/card.html"></component>
219
+ <div class="component" src="/components/card.html"></div>
220
+ ```
221
+
222
+ - **`dehydrate`** — Attribute or class name to skip reactive processing (alias for `vibe-dehydrate`).
223
+
127
224
  ### Deep Reactivity
128
225
 
129
226
  Vibe uses recursive proxies to detect changes at any nesting level:
package/boot.js CHANGED
@@ -10,7 +10,6 @@ export const ensureBoot = () => {
10
10
  if (booted || bootQueued) return;
11
11
  bootQueued = true;
12
12
 
13
- // Auto-boot in next microtask if no explicit boot
14
13
  queueMicrotask(() => {
15
14
  if (!booted) {
16
15
  boot();