@ape-egg/vibe 1.0.5 → 1.1.2
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 +112 -0
- package/README.md +228 -23
- package/compiler/bin/vibe-compile.js +109 -0
- package/compiler/native/.gitkeep +0 -0
- package/compiler/native/vibe-compiler-darwin-arm64 +0 -0
- package/compiler/src/Cargo.lock +1885 -0
- package/compiler/src/Cargo.toml +29 -0
- package/compiler/src/compiler/compile.rs +1209 -0
- package/compiler/src/compiler/mod.rs +5 -0
- package/compiler/src/config.rs +184 -0
- package/compiler/src/main.rs +284 -0
- package/compiler/src/parser/element.rs +96 -0
- package/compiler/src/parser/html.rs +335 -0
- package/compiler/src/parser/mod.rs +8 -0
- package/index.js +2 -248
- package/package.json +26 -3
- package/{affected.js → runtime/affected.js} +64 -4
- package/runtime/cleanup.js +59 -0
- package/runtime/component.js +116 -0
- package/{conditionals.js → runtime/conditionals.js} +25 -11
- package/{constants.js → runtime/constants.js} +23 -3
- package/runtime/debug.js +91 -0
- package/{hydrate.js → runtime/hydrate.js} +57 -7
- package/runtime/index.js +614 -0
- package/{iterate.js → runtime/iterate.js} +53 -45
- package/{iteration-utils.js → runtime/iteration-utils.js} +11 -1
- package/{parse.js → runtime/parse.js} +37 -7
- package/runtime/state.js +52 -0
- package/ROADMAP.md +0 -289
- package/llms.txt +0 -279
- package/state.js +0 -26
- /package/{_vibe-compiled-iteration-batch.js → runtime/_vibe-compiled-iteration-batch.js} +0 -0
- /package/{link.js → runtime/manifest.js} +0 -0
- /package/{utils.js → runtime/utils.js} +0 -0
- /package/{vibe.css → runtime/vibe.css} +0 -0
package/llms.txt
DELETED
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
# Vibe - Complete Documentation
|
|
2
|
-
|
|
3
|
-
> Runtime-first reactivity. No virtual DOM. No build step.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
Vibe is a lightweight reactive library that uses Proxy-based state and MutationObserver for fine-grained DOM updates. It works directly in the browser with zero compilation required.
|
|
8
|
-
|
|
9
|
-
**Key characteristics:**
|
|
10
|
-
- Proxy-based reactive state (`window.$`)
|
|
11
|
-
- Surgical DOM updates (only affected elements re-render)
|
|
12
|
-
- MutationObserver for dynamic element tracking
|
|
13
|
-
- Works with vanilla HTML - no special file format
|
|
14
|
-
|
|
15
|
-
## Installation
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
npm install @ape-egg/vibe
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## Quick Start
|
|
22
|
-
|
|
23
|
-
```html
|
|
24
|
-
<script type="module">
|
|
25
|
-
import state from "@ape-egg/vibe";
|
|
26
|
-
window.$ = state({ name: "World", count: 0 });
|
|
27
|
-
</script>
|
|
28
|
-
|
|
29
|
-
<h1>Hello, @[name]!</h1>
|
|
30
|
-
<button onclick="$.count++">Clicked @[count] times</button>
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Core Syntax
|
|
34
|
-
|
|
35
|
-
### Reactive Bindings
|
|
36
|
-
|
|
37
|
-
Use `@[property]` syntax anywhere in HTML or CSS:
|
|
38
|
-
|
|
39
|
-
```html
|
|
40
|
-
<!-- Text content -->
|
|
41
|
-
<div>@[firstName]</div>
|
|
42
|
-
|
|
43
|
-
<!-- Expressions -->
|
|
44
|
-
<div>@[firstName + ' ' + lastName]</div>
|
|
45
|
-
<div>@[count * 2]</div>
|
|
46
|
-
|
|
47
|
-
<!-- Attributes -->
|
|
48
|
-
<input value="@[inputValue]">
|
|
49
|
-
<button disabled="@[isLoading]">Submit</button>
|
|
50
|
-
|
|
51
|
-
<!-- CSS -->
|
|
52
|
-
<style>
|
|
53
|
-
.box { background: @[themeColor]; }
|
|
54
|
-
</style>
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
⚠️ **Important**: Bindings are evaluated using `new Function()`. Do not bind untrusted user input.
|
|
58
|
-
|
|
59
|
-
### State Access
|
|
60
|
-
|
|
61
|
-
State is accessed globally via `window.$`:
|
|
62
|
-
|
|
63
|
-
```javascript
|
|
64
|
-
// Read
|
|
65
|
-
console.log($.firstName);
|
|
66
|
-
|
|
67
|
-
// Write (triggers re-render)
|
|
68
|
-
$.firstName = "John";
|
|
69
|
-
|
|
70
|
-
// Increment
|
|
71
|
-
$.count++;
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Control Flow
|
|
75
|
-
|
|
76
|
-
### Iteration
|
|
77
|
-
|
|
78
|
-
```html
|
|
79
|
-
<!-- each items as item -->
|
|
80
|
-
<li>@[item]</li>
|
|
81
|
-
<!-- /each -->
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
With index:
|
|
85
|
-
|
|
86
|
-
```html
|
|
87
|
-
<!-- each items as item, index -->
|
|
88
|
-
<li>@[index]: @[item]</li>
|
|
89
|
-
<!-- /each -->
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### Nested Iteration
|
|
93
|
-
|
|
94
|
-
Use dot paths for nested arrays:
|
|
95
|
-
|
|
96
|
-
```html
|
|
97
|
-
<!-- each categories as category -->
|
|
98
|
-
<h2>@[category.name]</h2>
|
|
99
|
-
<!-- each category.items as item -->
|
|
100
|
-
<span>@[item.name]</span>
|
|
101
|
-
<!-- /each -->
|
|
102
|
-
<!-- /each -->
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
### Conditionals
|
|
106
|
-
|
|
107
|
-
```html
|
|
108
|
-
<!-- if isLoggedIn -->
|
|
109
|
-
<span>Welcome, @[username]!</span>
|
|
110
|
-
<!-- else -->
|
|
111
|
-
<span>Please log in</span>
|
|
112
|
-
<!-- /if -->
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
Conditionals can be nested inside iterations and vice versa.
|
|
116
|
-
|
|
117
|
-
## Special Attributes
|
|
118
|
-
|
|
119
|
-
### Dehydrate
|
|
120
|
-
|
|
121
|
-
Skip reactive processing for an element and its children:
|
|
122
|
-
|
|
123
|
-
```html
|
|
124
|
-
<code dehydrate>@[this] displays literally, not parsed</code>
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
Use cases:
|
|
128
|
-
- Displaying `@[...]` syntax in documentation
|
|
129
|
-
- Static content that shouldn't be reactive
|
|
130
|
-
- Performance optimization for large static sections
|
|
131
|
-
|
|
132
|
-
### Boolean Attributes
|
|
133
|
-
|
|
134
|
-
Attributes not in the value whitelist are removed when falsy:
|
|
135
|
-
|
|
136
|
-
```html
|
|
137
|
-
<button disabled="@[isLoading]">Submit</button>
|
|
138
|
-
<!-- When isLoading is false, disabled attribute is removed entirely -->
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
## Events
|
|
142
|
-
|
|
143
|
-
Use standard inline event handlers:
|
|
144
|
-
|
|
145
|
-
```html
|
|
146
|
-
<button onclick="$.count++">Increment</button>
|
|
147
|
-
<input oninput="$.text = this.value">
|
|
148
|
-
<form onsubmit="event.preventDefault(); handleSubmit()">
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
## Styling
|
|
152
|
-
|
|
153
|
-
### CSS Bindings
|
|
154
|
-
|
|
155
|
-
Reactive values work inside `<style>` tags:
|
|
156
|
-
|
|
157
|
-
```html
|
|
158
|
-
<style>
|
|
159
|
-
.box {
|
|
160
|
-
background: @[backgroundColor];
|
|
161
|
-
color: @[textColor];
|
|
162
|
-
width: @[width]px;
|
|
163
|
-
}
|
|
164
|
-
</style>
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
### Preventing FOUC
|
|
168
|
-
|
|
169
|
-
Hide content until hydration completes:
|
|
170
|
-
|
|
171
|
-
```html
|
|
172
|
-
<body style="visibility: hidden;">
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
Or use the included CSS:
|
|
176
|
-
|
|
177
|
-
```html
|
|
178
|
-
<link rel="stylesheet" href="@ape-egg/vibe/vibe.css">
|
|
179
|
-
<body vibe>
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
## Dynamic Elements
|
|
183
|
-
|
|
184
|
-
Elements added via JavaScript are automatically hydrated through MutationObserver:
|
|
185
|
-
|
|
186
|
-
```javascript
|
|
187
|
-
const div = document.createElement('div');
|
|
188
|
-
div.innerHTML = '<span>Hello, @[name]!</span>';
|
|
189
|
-
document.body.appendChild(div);
|
|
190
|
-
// Automatically becomes reactive
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
## API Reference
|
|
194
|
-
|
|
195
|
-
### `state(initialState, afterUpdate?)`
|
|
196
|
-
|
|
197
|
-
Creates reactive state and initializes the framework.
|
|
198
|
-
|
|
199
|
-
```javascript
|
|
200
|
-
import state from "@ape-egg/vibe";
|
|
201
|
-
|
|
202
|
-
window.$ = state(
|
|
203
|
-
{ count: 0, user: { name: "Alice" } },
|
|
204
|
-
(newState, oldState) => {
|
|
205
|
-
console.log("State updated:", newState);
|
|
206
|
-
}
|
|
207
|
-
);
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
**Parameters:**
|
|
211
|
-
- `initialState` - Object containing initial state values
|
|
212
|
-
- `afterUpdate` - Optional callback after each state change (receives read-only snapshots)
|
|
213
|
-
|
|
214
|
-
**Returns:** Proxy object for reactive state access
|
|
215
|
-
|
|
216
|
-
## Scoped Variables
|
|
217
|
-
|
|
218
|
-
Inside `<!-- each -->` blocks, these variables are available:
|
|
219
|
-
- `item` (or custom name) - current array element
|
|
220
|
-
- `index` (or custom name) - current index
|
|
221
|
-
- Parent state remains accessible via `$`
|
|
222
|
-
|
|
223
|
-
```html
|
|
224
|
-
<!-- each users as user, i -->
|
|
225
|
-
<div>@[i]: @[user.name] (total: @[users.length])</div>
|
|
226
|
-
<!-- /each -->
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
## Architecture
|
|
230
|
-
|
|
231
|
-
Vibe consists of these core modules:
|
|
232
|
-
|
|
233
|
-
- **state.js** - Proxy-based reactive state container
|
|
234
|
-
- **parse.js** - DOM parser that finds `@[...]` bindings
|
|
235
|
-
- **link.js** - Maps elements to parsed tree nodes
|
|
236
|
-
- **hydrate.js** - Updates DOM with current state values
|
|
237
|
-
- **affected.js** - Determines which elements need updating
|
|
238
|
-
- **iterate.js** - Array rendering with efficient diffing
|
|
239
|
-
- **conditionals.js** - Conditional block rendering
|
|
240
|
-
|
|
241
|
-
## How It Works
|
|
242
|
-
|
|
243
|
-
```
|
|
244
|
-
1. state() initializes the Proxy and framework
|
|
245
|
-
2. parse.js scans DOM for @[...], <!-- each -->, <!-- if -->
|
|
246
|
-
3. link.js maps elements to the parsed tree
|
|
247
|
-
4. hydrate.js replaces bindings with values
|
|
248
|
-
5. iterate.js renders <!-- each --> loops
|
|
249
|
-
6. conditionals.js renders <!-- if --> blocks
|
|
250
|
-
7. MutationObserver watches for new elements
|
|
251
|
-
8. On state change: affected.js finds changed elements → hydrate.js updates them
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
## Current Limitations
|
|
255
|
-
|
|
256
|
-
- **Top-level reactivity only**: `$.nested.prop = value` doesn't trigger updates (must replace parent object)
|
|
257
|
-
- **No computed values**: Derived state must be calculated manually
|
|
258
|
-
- **No two-way binding sugar**: Must wire input events manually
|
|
259
|
-
- **Expression security**: `new Function()` evaluation - don't bind untrusted input
|
|
260
|
-
|
|
261
|
-
## Best Practices
|
|
262
|
-
|
|
263
|
-
1. **Initialize state before DOM**: Place `<script>` in `<head>` or before reactive elements
|
|
264
|
-
2. **Use dehydrate for docs**: When showing `@[...]` syntax examples
|
|
265
|
-
3. **Prevent FOUC**: Use `visibility: hidden` on body until hydration
|
|
266
|
-
4. **Keep expressions simple**: Complex logic belongs in JavaScript, not templates
|
|
267
|
-
5. **Replace objects for deep updates**: `$.user = { ...$.user, name: "New" }`
|
|
268
|
-
|
|
269
|
-
## Browser Support
|
|
270
|
-
|
|
271
|
-
Modern browsers with:
|
|
272
|
-
- Proxy (ES6)
|
|
273
|
-
- MutationObserver
|
|
274
|
-
- ES Modules
|
|
275
|
-
|
|
276
|
-
## Resources
|
|
277
|
-
|
|
278
|
-
- **Homepage**: https://vibe.korte.kim
|
|
279
|
-
- **npm**: https://www.npmjs.com/package/@ape-egg/vibe
|
package/state.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
export default (state, rerender) =>
|
|
2
|
-
new Proxy(state, {
|
|
3
|
-
set(obj, prop, value) {
|
|
4
|
-
const ref = Reflect.set(...arguments);
|
|
5
|
-
rerender({
|
|
6
|
-
[prop]: value,
|
|
7
|
-
});
|
|
8
|
-
// console.info("state change", { obj, prop, value });
|
|
9
|
-
return ref;
|
|
10
|
-
},
|
|
11
|
-
get(target, prop) {
|
|
12
|
-
// if (typeof target[prop] === 'function') {
|
|
13
|
-
// const inputString = target[prop].toString();
|
|
14
|
-
// const regex = /\$\.\w+/g;
|
|
15
|
-
// let match;
|
|
16
|
-
// while ((match = regex.exec(inputString))) {
|
|
17
|
-
// const varName = match[0].split('.')[1];
|
|
18
|
-
// console.log(varName, state[varName]);
|
|
19
|
-
// }
|
|
20
|
-
// console.log(arguments)
|
|
21
|
-
|
|
22
|
-
// }
|
|
23
|
-
|
|
24
|
-
return Reflect.get(...arguments);
|
|
25
|
-
},
|
|
26
|
-
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|