@ape-egg/vibe 2.3.0 → 3.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 +14 -4
- package/boot.js +4 -4
- package/component.js +27 -29
- package/hot-module-refresh.js +4 -4
- package/index.js +10 -15
- package/llms.txt +8 -6
- package/package.json +19 -14
- package/runtime/affected.js +159 -36
- package/runtime/cleanup.js +45 -1
- package/runtime/component.js +312 -99
- package/runtime/conditionals.js +111 -14
- package/runtime/debug.js +24 -0
- package/runtime/dispatch.js +172 -0
- package/runtime/hydrate.js +251 -111
- package/runtime/index.js +180 -71
- package/runtime/iterate.js +125 -50
- package/runtime/iteration-utils.js +59 -8
- package/runtime/manifest.js +77 -2
- package/runtime/parse.js +69 -5
- package/runtime/pre-compiled-iterations.js +19 -6
- package/runtime/pre-compiled-manifest.js +13 -4
- package/runtime/staging.js +153 -0
- package/runtime/state.js +31 -0
- package/runtime/tracking.js +173 -0
- package/runtime/utils.js +155 -78
- package/spa.js +77 -14
- package/vibe.css +8 -4
- package/CHANGELOG.md +0 -1196
- package/ROADMAP.md +0 -397
- package/compiler/bin/vibe-compile.js +0 -121
- package/compiler/native/.gitkeep +0 -0
- package/compiler/native/vibe-compiler-darwin-arm64 +0 -0
- package/compiler/native/vibe-compiler-linux-x64 +0 -0
- package/compiler/src/Cargo.lock +0 -2023
- package/compiler/src/Cargo.toml +0 -38
- package/compiler/src/compiler/PRE-RENDERING-IMPLEMENTATION.md +0 -241
- package/compiler/src/compiler/binding_case.rs +0 -88
- package/compiler/src/compiler/compile.rs +0 -2880
- package/compiler/src/compiler/component_tagger.rs +0 -469
- package/compiler/src/compiler/iteration_optimizer.rs +0 -455
- package/compiler/src/compiler/js_analyzer.rs +0 -715
- package/compiler/src/compiler/manifest_builder.rs +0 -693
- package/compiler/src/compiler/mod.rs +0 -16
- package/compiler/src/compiler/name_binding_protect.rs +0 -207
- package/compiler/src/compiler/reassignment_analyzer.rs +0 -456
- package/compiler/src/compiler/spa.rs +0 -477
- package/compiler/src/compiler/state_extractor.rs +0 -263
- package/compiler/src/compiler/value_stamper.rs +0 -921
- package/compiler/src/compiler/watcher.rs +0 -1278
- package/compiler/src/config.rs +0 -279
- package/compiler/src/main.rs +0 -358
- package/compiler/src/parser/element.rs +0 -96
- package/compiler/src/parser/html.rs +0 -1004
- package/compiler/src/parser/mod.rs +0 -8
- package/runtime/pre-compiled-manifest.test.mjs +0 -58
- package/runtime/scope.js +0 -50
- package/test-results/.last-run.json +0 -4
package/README.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# Vibe
|
|
2
2
|
|
|
3
|
-
**Version
|
|
3
|
+
**Version 3.0.1** — Runtime-first reactivity for plain HTML. Drop a script tag into any page and get reactive bindings, control flow, and URL-loaded components — no build step required. Compile later if you want; the compiler is a separate, optional package (`@ape-egg/vibe-compiler`).
|
|
4
|
+
|
|
5
|
+
## Security model & CSP
|
|
6
|
+
|
|
7
|
+
Vibe escapes by default: `@[expr]` renders as text, never markup. The one deliberate exception is `@[$.unsafe(trustedHtml)]`, which sets `innerHTML` and is for trusted input only.
|
|
8
|
+
|
|
9
|
+
What you must know before adopting: **Vibe's engine evaluates binding expressions with `new Function` and uses inline `on*` attributes as its event model.** A site running Vibe therefore needs a Content-Security-Policy that allows `'unsafe-eval'` and inline event handlers — i.e. it cannot deploy a strict CSP. Vibe itself is not an XSS vector, but strict CSP is a browser-level safety net against *other* injection bugs anywhere on a page, and Vibe requires that net loosened.
|
|
10
|
+
|
|
11
|
+
If you ship to an environment that mandates strict CSP (banks, healthcare, government, security-reviewed enterprise), Vibe is currently the wrong tool. For everything else — personal sites, games, dashboards, internal tools, most product work — this is the same posture as running Vue's in-browser template compiler or Alpine.js, and it is a documented trade-off, not an accident.
|
|
4
12
|
|
|
5
13
|
No virtual DOM. No build step required. Just modern JavaScript. When you need production optimizations, add the optional Rust-based compiler.
|
|
6
14
|
|
|
@@ -212,7 +220,7 @@ Multi-segment paths (`@[this.user.profile.name]`), conditionals (`<!-- if this.e
|
|
|
212
220
|
How it works:
|
|
213
221
|
|
|
214
222
|
1. `component({...})` claims the nearest unprocessed `<component>` (or `<div class="component">`) wrapper, registers state at `$[id]`, and tags the wrapper with `data-vibe-component-id`
|
|
215
|
-
2. Internally it
|
|
223
|
+
2. Internally it triggers the boot pipeline, which initializes `window.$`, parses the DOM, hydrates bindings, and starts the MutationObserver — exactly once, even if multiple `<component>` blocks call `component()`
|
|
216
224
|
3. From there, `@[this.X]`, `onclick="this.fn()"`, and `<!-- if this.X -->` work as documented
|
|
217
225
|
|
|
218
226
|
Multiple drop-in blocks on the same page each get their own state bucket. They can read each other's state via global `$['_c0'].count` if they need to coordinate, but in most drop-in cases they're independent.
|
|
@@ -350,9 +358,11 @@ No need for immutable update patterns or spread operators. Just mutate and Vibe
|
|
|
350
358
|
1. **Proxy-based state** — `window.$` intercepts property changes
|
|
351
359
|
2. **Deep reactivity** — Nested mutations trigger updates automatically (`$.obj.nested.prop = x`)
|
|
352
360
|
3. **DOM parsing** — Finds all `@[...]` bindings on load
|
|
353
|
-
4. **
|
|
361
|
+
4. **Auto-tracked subscriptions** — Every binding, conditional, and iteration records which state keys its expression read during evaluation; a write dispatches exactly its subscribers — O(what changed), no tree walk, no virtual DOM
|
|
354
362
|
5. **MutationObserver** — Tracks dynamically added elements
|
|
355
363
|
|
|
364
|
+
One contract follows from #4: **an expression that should react must read reactive state.** `@[items.map(format)]` re-renders when `$.items` changes because `items` was read from `$` — but if `format` is a window global that you later *reassign*, nothing re-renders, because assigning a global is not a state write. Values that change over time belong in `$`. (Helpers defined by component scripts are safe: mounts re-settle their directives once their scripts have run.)
|
|
365
|
+
|
|
356
366
|
---
|
|
357
367
|
|
|
358
368
|
## Vibe Compiler
|
|
@@ -729,7 +739,7 @@ ISC
|
|
|
729
739
|
- `runtime/affected.js:~122` — `shouldAffect = noMatch || ...` fallback for unmatched expressions
|
|
730
740
|
- `runtime/affected.js:~248` — same fallback for name bindings
|
|
731
741
|
|
|
732
|
-
|
|
742
|
+
As of 3.0.0 this is solved — not by static extraction (which lies for helper calls) but by the subscription engine: every binding records the state keys it actually reads during evaluation, live at the proxy's get trap, so a write notifies exactly its subscribers. Update cost is O(change), and it costs zero authoring syntax.
|
|
733
743
|
|
|
734
744
|
### HTML lowercases attribute names — breaks name binding matching
|
|
735
745
|
|
package/boot.js
CHANGED
|
@@ -25,8 +25,8 @@ export const boot = () => {
|
|
|
25
25
|
booted = true;
|
|
26
26
|
|
|
27
27
|
// Merge all state: global + components
|
|
28
|
-
const globalState = window.
|
|
29
|
-
const componentStates = window.
|
|
28
|
+
const globalState = window.__vibe?.state || {};
|
|
29
|
+
const componentStates = window.__vibe?.components || {};
|
|
30
30
|
|
|
31
31
|
const mergedState = {
|
|
32
32
|
...globalState,
|
|
@@ -34,8 +34,8 @@ export const boot = () => {
|
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
// Get config and targetSelector (first caller wins)
|
|
37
|
-
const config = window.
|
|
38
|
-
const targetSelector =
|
|
37
|
+
const config = window.__vibe?.config || {};
|
|
38
|
+
const targetSelector = config.target || '';
|
|
39
39
|
|
|
40
40
|
// Boot with merged state
|
|
41
41
|
window.$ = main(mergedState, config, targetSelector);
|
package/component.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// <component>
|
|
4
4
|
// <script type="module">
|
|
5
5
|
// import component from 'vibe/component.js';
|
|
6
|
-
// component({ count: 0 }, { debug: false
|
|
6
|
+
// component({ count: 0 }, { debug: false, target: 'body' });
|
|
7
7
|
// </script>
|
|
8
8
|
// <div>@[this.count]</div>
|
|
9
9
|
// </component>
|
|
@@ -14,28 +14,31 @@
|
|
|
14
14
|
import { generateComponentId } from './runtime/component.js';
|
|
15
15
|
import { ensureBoot } from './boot.js';
|
|
16
16
|
|
|
17
|
-
const component = (state = {}, config
|
|
17
|
+
const component = (state = {}, config) => {
|
|
18
18
|
// Initialize component registry
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
19
|
+
const ns = (window.__vibe ??= {});
|
|
20
|
+
if (!ns.components) ns.components = {};
|
|
22
21
|
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
22
|
+
// Pair this call with its wrapper. Module scripts execute in document
|
|
23
|
+
// order, so the K-th component() call belongs to the K-th wrapper whose own
|
|
24
|
+
// direct <script type="module"> calls component( — the runtime mirror of
|
|
25
|
+
// the build tagger's registers_state predicate. Wrappers without such a
|
|
26
|
+
// script (no local state, or a compiler-neutered vibe-module script that
|
|
27
|
+
// registers through boot) can never claim a call, so they're excluded —
|
|
28
|
+
// otherwise a stateless wrapper earlier in the document absorbs a later
|
|
29
|
+
// section's claim and every pairing after it is cross-wired. In compiled
|
|
30
|
+
// pages the claimed wrapper is already build-tagged: register under its id.
|
|
31
|
+
// Supports: <component> or <div class="component">; <component src> mounts
|
|
32
|
+
// register through the fetch pipeline instead.
|
|
27
33
|
const allWrappers = Array.from(document.querySelectorAll('component:not([src]), div.component:not([src])'));
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return existingId && !window.__vibeComponents[existingId];
|
|
37
|
-
});
|
|
38
|
-
}
|
|
34
|
+
const wrapper = allWrappers.find((el) => {
|
|
35
|
+
const ownsCall = Array.from(el.children).some(
|
|
36
|
+
(child) => child.matches?.('script[type="module"]') && /component\s*\(/.test(child.textContent),
|
|
37
|
+
);
|
|
38
|
+
if (!ownsCall) return false;
|
|
39
|
+
const existingId = el.getAttribute('data-vibe-component-id');
|
|
40
|
+
return !existingId || !ns.components[existingId];
|
|
41
|
+
});
|
|
39
42
|
|
|
40
43
|
if (!wrapper) {
|
|
41
44
|
console.warn('[vibe] component() must be called inside <component> or <div class="component">');
|
|
@@ -50,16 +53,11 @@ const component = (state = {}, config, targetSelector) => {
|
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
// Register component state in shared registry
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
// Store config (first caller wins)
|
|
56
|
-
if (config && !window.__vibeConfig) {
|
|
57
|
-
window.__vibeConfig = config;
|
|
58
|
-
}
|
|
56
|
+
ns.components[componentId] = state;
|
|
59
57
|
|
|
60
|
-
// Store
|
|
61
|
-
if (
|
|
62
|
-
|
|
58
|
+
// Store config (first caller wins); config.target scopes the boot.
|
|
59
|
+
if (config && !ns.config) {
|
|
60
|
+
ns.config = config;
|
|
63
61
|
}
|
|
64
62
|
|
|
65
63
|
// Ensure boot happens
|
package/hot-module-refresh.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
//
|
|
7
7
|
// SOFT DEPENDENCY: nothing in Vibe's runtime imports this, it imports nothing
|
|
8
8
|
// from Vibe, and deleting it leaves a working framework. It depends solely on
|
|
9
|
-
// the runtime global `window.$` (reconcile /
|
|
9
|
+
// the runtime global `window.$` (reconcile / _renderComponent /
|
|
10
10
|
// clearComponentCache), so it ships as a flat module a plain static server can
|
|
11
11
|
// serve as-is — no bundler, no Vite.
|
|
12
12
|
//
|
|
@@ -267,7 +267,7 @@ export const setupHotModuleRefresh = ({ debug = false, subscribe }) => {
|
|
|
267
267
|
// Component file changed. Strategy:
|
|
268
268
|
// 1. Fetch the raw template once per update; hash its <script type="module">
|
|
269
269
|
// contents. Script hash unchanged + not inside an iteration → surgical
|
|
270
|
-
// path: $.
|
|
270
|
+
// path: $._renderComponent produces the processed HTML (props + slot
|
|
271
271
|
// substituted, componentIds reused) and $.reconcile diffs it against
|
|
272
272
|
// the live wrapper's children. DOM identity, focus, and component
|
|
273
273
|
// state are preserved.
|
|
@@ -295,7 +295,7 @@ export const setupHotModuleRefresh = ({ debug = false, subscribe }) => {
|
|
|
295
295
|
const rawUrl = path + (path.includes('?') ? '&' : '?') + '_t=' + Date.now();
|
|
296
296
|
const rawHtml = await fetch(rawUrl, { cache: 'no-store' }).then((r) => r.text());
|
|
297
297
|
const scriptHash = hashScripts(rawHtml);
|
|
298
|
-
const canSurgical = typeof window.$?.
|
|
298
|
+
const canSurgical = typeof window.$?._renderComponent === 'function'
|
|
299
299
|
&& typeof window.$?.reconcile === 'function';
|
|
300
300
|
|
|
301
301
|
let surgical = 0;
|
|
@@ -314,7 +314,7 @@ export const setupHotModuleRefresh = ({ debug = false, subscribe }) => {
|
|
|
314
314
|
? el._vibePluginSlot
|
|
315
315
|
: (el._vibeSlotContent || '');
|
|
316
316
|
const props = el._vibeProps || {};
|
|
317
|
-
const processedHtml = window.$.
|
|
317
|
+
const processedHtml = window.$._renderComponent(rawHtml, props, slot, { componentIds });
|
|
318
318
|
const summary = await window.$.reconcile(el, processedHtml);
|
|
319
319
|
el._vibeScriptHash = scriptHash;
|
|
320
320
|
el._vibeRawSource = rawHtml;
|
package/index.js
CHANGED
|
@@ -43,7 +43,7 @@ export const applyDefaults = (target, state) => {
|
|
|
43
43
|
return target;
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
-
const vibe = (state = {}, config
|
|
46
|
+
const vibe = (state = {}, config) => {
|
|
47
47
|
if (isBooted()) {
|
|
48
48
|
// Already booted: initial state declared late seeds missing keys only —
|
|
49
49
|
// on a fresh document load this branch never runs, so MPA behavior is
|
|
@@ -57,24 +57,19 @@ const vibe = (state = {}, config, targetSelector) => {
|
|
|
57
57
|
vibeInstance = createVibeInstance();
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
// Not booted yet - accumulate in
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
Object.assign(window.__vibeGlobalState, state);
|
|
65
|
-
|
|
66
|
-
// Store config (first caller wins)
|
|
67
|
-
if (config && !window.__vibeConfig) {
|
|
68
|
-
window.__vibeConfig = config;
|
|
69
|
-
}
|
|
60
|
+
// Not booted yet - accumulate in the reserved namespace's state registry
|
|
61
|
+
const ns = (window.__vibe ??= {});
|
|
62
|
+
if (!ns.state) ns.state = {};
|
|
63
|
+
Object.assign(ns.state, state);
|
|
70
64
|
|
|
71
|
-
// Store
|
|
72
|
-
|
|
73
|
-
|
|
65
|
+
// Store config (first caller wins). `config.target` scopes the boot to a
|
|
66
|
+
// selector (the old third positional argument, folded into config at 3.0.0).
|
|
67
|
+
if (config && !ns.config) {
|
|
68
|
+
ns.config = config;
|
|
74
69
|
}
|
|
75
70
|
|
|
76
71
|
// Explicit boot call (no state passed means "boot now with accumulated state")
|
|
77
|
-
if (Object.keys(state).length === 0 && Object.keys(
|
|
72
|
+
if (Object.keys(state).length === 0 && Object.keys(ns.state).length > 0) {
|
|
78
73
|
return boot();
|
|
79
74
|
}
|
|
80
75
|
|
package/llms.txt
CHANGED
|
@@ -88,6 +88,8 @@ $.config.theme.colors.primary = "#007bff";
|
|
|
88
88
|
|
|
89
89
|
Vibe uses recursive proxies to detect changes at any nesting level automatically.
|
|
90
90
|
|
|
91
|
+
**Reactivity model (3.0.0):** every binding, conditional, and iteration subscribes to the state keys its expression read during evaluation; a state write dispatches exactly its subscribers. Consequence: an expression only re-evaluates when reactive state it read changes. Window globals, module values, and other non-state sources are read once — reassigning them re-renders nothing. Anything that changes over time belongs in `$`. Helpers defined by component scripts are picked up automatically (mounts re-settle once their scripts have run).
|
|
92
|
+
|
|
91
93
|
## Control Flow
|
|
92
94
|
|
|
93
95
|
### Iteration
|
|
@@ -201,7 +203,7 @@ Multi-segment paths, conditionals (`<!-- if this.editing -->`), and iterations (
|
|
|
201
203
|
|
|
202
204
|
Mechanism:
|
|
203
205
|
1. `component({...})` claims the nearest unprocessed `<component>` (or `<div class="component">`) wrapper
|
|
204
|
-
2. It
|
|
206
|
+
2. It triggers the internal boot, which initializes `window.$`, parses the DOM, hydrates bindings, and starts the MutationObserver — exactly once per page, even if multiple drop-in blocks call `component()`
|
|
205
207
|
3. `@[this.X]`, `onclick="this.fn()"`, `<!-- if this.X -->`, etc. resolve against that block's bucket
|
|
206
208
|
|
|
207
209
|
Multiple drop-in blocks on the same page each get their own state and run independently. They can still read each other's state via global `$['<id>']` if coordination is needed.
|
|
@@ -245,7 +247,7 @@ A standalone router maintaining `$.page = { path, route, params, src }`; a react
|
|
|
245
247
|
|
|
246
248
|
Rules: tables are pre-sorted most-specific-first, first match wins. Clicks are claimed only for same-origin, unmodified, untargeted links whose pathname matches a real route (`'*'` never claims) — everything else navigates natively, so mixed MPA/SPA output works. Route titles swap `document.title`. `resolve(location, routes)` is pure. A custom `onNavigate` makes it a pure router without Vibe.
|
|
247
249
|
|
|
248
|
-
State semantics under SPA: `vibe()` state is app-lifetime, `component()` state is mount-lifetime (resets per visit).
|
|
250
|
+
State semantics under SPA: `vibe()` state is app-lifetime, `component()` state is mount-lifetime (resets per visit). `vibe()` itself has defaults semantics once booted — it sets only keys that don't exist yet on `$`, so re-running page scripts (SPA fragment re-mounts) never clobber live state. The compiler's SPA mode (`"spa": true` in `vibe-compiler` config, or `--spa`) compiles an MPA `pages/` tree into page fragments under `/components/vibe-spa/`, a generated route table, and a composed `/index.html` shell wired to this router — deploy with one rewrite: every route → `/index.html`.
|
|
249
251
|
|
|
250
252
|
## Special Attributes
|
|
251
253
|
|
|
@@ -328,15 +330,15 @@ Imported from `@ape-egg/vibe/component`. Registers a component-local state bucke
|
|
|
328
330
|
|
|
329
331
|
### `$.on(event, callback)`
|
|
330
332
|
|
|
331
|
-
Register a lifecycle listener. Events: `'ready'`, `'afterUpdate'`, `'afterDomMutation'`. Listeners registered before boot are queued and replayed once vibe is ready.
|
|
333
|
+
Register a lifecycle listener. Events: `'ready'`, `'afterUpdate'`, `'afterDomMutation'`, `'unmount'`. Listeners registered before boot are queued and replayed once vibe is ready. A `'ready'` listener registered AFTER boot (a fetched fragment's script) fires once its mount settles — same timing as `await $.ready`. `'unmount'` is scope-resolved: inside a component script it fires on that component's unmount (and before an HMR re-run); at page level it fires on pagehide.
|
|
332
334
|
|
|
333
335
|
### `$.ready`
|
|
334
336
|
|
|
335
337
|
A Promise that resolves once vibe has finished initial parse + hydrate + component loading.
|
|
336
338
|
|
|
337
|
-
### `$.reconcile(el, html)`
|
|
339
|
+
### `$.reconcile(el, html)` (advanced)
|
|
338
340
|
|
|
339
|
-
Subtree reconciliation
|
|
341
|
+
Subtree reconciliation used by `@ape-egg/vite-plugin-vibe` for surgical HMR: diffs `el`'s children against fresh `html` while preserving DOM identity, focus, and selection; vibe-managed regions (iterations, conditionals, components, slot pairs) are treated as opaque. Treat as plumbing — shape may evolve. (Internal renders/registration live on underscore-prefixed `$` members and are not API.)
|
|
340
342
|
|
|
341
343
|
## Scoped Variables in Iterations
|
|
342
344
|
|
|
@@ -397,7 +399,7 @@ Vibe consists of these core runtime modules (in `runtime/`):
|
|
|
397
399
|
|
|
398
400
|
- **No computed values primitive**: derived state can be done with `Object.defineProperty($, 'x', { get })` or with `afterUpdate` listeners; a first-class `computed` API isn't shipped
|
|
399
401
|
- **Expression security**: `new Function()` evaluation — don't bind untrusted input
|
|
400
|
-
- **HTML binding**: `@[expr]` always sets `textContent` (escape-safe).
|
|
402
|
+
- **HTML binding**: `@[expr]` always sets `textContent` (escape-safe). For trusted HTML, `@[$.unsafe(trustedHtml)]` sets `innerHTML` when it is the element's sole content (no sanitizing — trusted input only; injected markup is inert)
|
|
401
403
|
|
|
402
404
|
## Best Practices
|
|
403
405
|
|
package/package.json
CHANGED
|
@@ -1,35 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ape-egg/vibe",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "Runtime-first reactivity
|
|
5
|
+
"description": "Runtime-first reactivity for plain HTML — no build step, no virtual DOM, no new syntax to learn",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"homepage": "https://vibe.korte.kim",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/kkortes/vibe.git"
|
|
11
|
+
},
|
|
8
12
|
"exports": {
|
|
9
13
|
".": "./index.js",
|
|
10
|
-
"./boot": "./boot.js",
|
|
11
14
|
"./component": "./component.js",
|
|
12
|
-
"./hot-module-refresh": "./hot-module-refresh.js",
|
|
13
15
|
"./spa": "./spa.js",
|
|
14
|
-
"./
|
|
15
|
-
"./compiler": "./compiler/bin/vibe-compile.js"
|
|
16
|
-
},
|
|
17
|
-
"bin": {
|
|
18
|
-
"vibe": "./compiler/bin/vibe-compile.js"
|
|
16
|
+
"./hot-module-refresh": "./hot-module-refresh.js"
|
|
19
17
|
},
|
|
18
|
+
"files": [
|
|
19
|
+
"index.js",
|
|
20
|
+
"boot.js",
|
|
21
|
+
"component.js",
|
|
22
|
+
"spa.js",
|
|
23
|
+
"hot-module-refresh.js",
|
|
24
|
+
"runtime",
|
|
25
|
+
"vibe.css",
|
|
26
|
+
"llms.txt"
|
|
27
|
+
],
|
|
20
28
|
"keywords": [
|
|
21
29
|
"reactive",
|
|
22
30
|
"framework",
|
|
23
31
|
"frontend",
|
|
24
32
|
"ui",
|
|
33
|
+
"no-build",
|
|
25
34
|
"mutation-observer",
|
|
26
35
|
"proxy",
|
|
27
|
-
"minimalistic"
|
|
28
|
-
"compiler"
|
|
36
|
+
"minimalistic"
|
|
29
37
|
],
|
|
30
|
-
"scripts": {
|
|
31
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
32
|
-
},
|
|
33
38
|
"author": "kkortes",
|
|
34
39
|
"license": "ISC",
|
|
35
40
|
"publishConfig": {
|