@ryupold/vode 0.9.4 → 0.9.5

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.
@@ -1,25 +1,24 @@
1
- name: Publish to https://registry.npmjs.org
2
-
3
- on:
4
- push:
5
- branches:
6
- - 'main'
7
-
8
- jobs:
9
- build:
10
- runs-on: ubuntu-latest
11
- permissions:
12
- contents: read
13
- id-token: write
14
- steps:
15
- - uses: actions/checkout@v4
16
- - uses: actions/setup-node@v4
17
- with:
18
- node-version: '22.x'
19
- registry-url: 'https://registry.npmjs.org'
20
- - uses: oven-sh/setup-bun@v2
21
- - run: bun install
22
- - run: bun run build
23
- - run: bun publish --provenance --access public
24
- env:
25
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
1
+ name: Publish to https://registry.npmjs.org
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - 'main'
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: read
13
+ id-token: write
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/setup-node@v4
17
+ with:
18
+ node-version: '22.x'
19
+ registry-url: 'https://registry.npmjs.org'
20
+ - uses: oven-sh/setup-bun@v2
21
+ - run: bun run build
22
+ - run: bun publish --provenance --access public
23
+ env:
24
+ NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Michael Scherbakow
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Michael Scherbakow
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,127 +1,127 @@
1
- # vode
2
-
3
- Small web framework for minimal websites.
4
- Each vode app has its own state and renders a tree of HTML elements.
5
- The state is a singleton object that can be updated, and the UI will re-render when a patch is supplied. Nesting vode-apps is undefined behavior for now.
6
-
7
- ## Install
8
-
9
- ```bash
10
- npm install @ryupold/vode --save
11
- ```
12
-
13
- ## Patch
14
-
15
- The `patch` function returned by `app(...)` is a function that can be passed an object called `Patch` this object is used to update the state and re-render the UI. It takes a `Patch` object that describes the changes to be made to the state in a "trickle down manner". The `Patch` can be a simple object or a function that returns a new `Patch` to the current state. It can also be an async and/or genrator function that yields `Patch`es. Events also can return a `Patch`. When a number | boolean | string | null | undefined is applied as a `Patch`, it will be ignored.
16
-
17
- ## Usage
18
-
19
- index.html
20
-
21
- ```html
22
- <html>
23
- <head>
24
- <title>Vode Example</title>
25
- <script type="module" src="main.js"></script>
26
- </head>
27
- <body>
28
- <div id="app"></div>
29
- </body>
30
- </html>
31
- ```
32
-
33
- main.ts
34
- ```ts
35
- // import { app, createState} from 'vode.js';
36
- // import { BR, DIV, INPUT, SPAN } from 'vode-tags.js';
37
- import { app, createState, BR, DIV, INPUT, SPAN } from '@ryupold/vode';
38
-
39
-
40
- const init = createState({
41
- counter: 0,
42
- });
43
-
44
- type State = typeof init;
45
-
46
- const appNode = document.getElementById('app');
47
-
48
- app<State>(appNode, init,
49
- (s: State) => [DIV,
50
- [INPUT, {
51
- type: 'button',
52
- onclick: { counter: s.counter + 1 },
53
- value: 'Click me',
54
- }],
55
- [BR],
56
- [SPAN, { style: { color: 'red' } }, `${s.counter}`],
57
- ]
58
- );
59
- ```
60
-
61
- ## Claude
62
-
63
- > Prompt: "what can you tell me about the overall design philosophy of the vode library based on what you see in `src/vode.ts`"
64
-
65
-
66
- Based on my analysis of `src/vode.ts`, here's the overall design philosophy of the vode library:
67
-
68
- ### Core Design Philosophy
69
-
70
- **Functional Virtual DOM with Minimal Abstractions**
71
- - Uses array-based virtual nodes (`[tag, props?, ...children]`) instead of object-based structures
72
- - Prioritizes simplicity and performance over complex abstractions
73
-
74
- **State-Centric Architecture**
75
- - Central state object with patch-based updates
76
- - Immutable-style state management with deep merging
77
- - Single source of truth pattern
78
-
79
- **Zero-Dependency Minimalism**
80
- - Pure TypeScript/JavaScript implementation
81
- - No external dependencies or build tools required
82
- - Direct DOM manipulation without heavy runtime
83
-
84
- ### Key Architectural Decisions
85
-
86
- #### Virtual DOM Structure
87
- ```typescript
88
- // Simple array-based nodes
89
- ["div", { class: "container" }, "Hello", ["span", "World"]]
90
- ```
91
- - Minimal memory footprint
92
- - Easy serialization/debugging
93
- - Type-safe with TypeScript generics
94
-
95
- #### Reactive State Management
96
- ```typescript
97
- state.patch(newData) // Direct updates
98
- state.patch([effect, payload]) // Function-based effects
99
- state.patch(promise) // Async support
100
- ```
101
- - Unified patch system for all state changes
102
- - Built-in async/generator support
103
- - Functional effects pattern
104
-
105
- #### Performance Optimizations
106
- - **Memoization**: `memo()` for component caching
107
- - **Reconciliation**: Intelligent DOM diffing
108
- - **Batched Updates**: RequestAnimationFrame-based rendering
109
- - **Memory Management**: Proper cleanup with mount/unmount hooks
110
-
111
- #### Developer Experience
112
- - **Type Safety**: Full TypeScript support with generics
113
- - **Debugging**: Built-in performance statistics
114
- - **Flexibility**: Support for HTML, SVG, and MathML
115
- - **Composability**: Functional component model
116
-
117
- ### Philosophy Summary
118
-
119
- Vode follows a **"less is more"** philosophy, providing a lightweight alternative to heavyweight frameworks while maintaining modern reactive patterns. It emphasizes:
120
-
121
- 1. **Explicitness over magic** - Clear, predictable behavior
122
- 2. **Performance by design** - Minimal overhead, efficient updates
123
- 3. **Developer control** - Direct state manipulation without hidden abstractions
124
- 4. **Functional paradigms** - Immutable updates, pure components
125
- 5. **Modern web standards** - Leverages native browser APIs effectively
126
-
1
+ # vode
2
+
3
+ Small web framework for minimal websites.
4
+ Each vode app has its own state and renders a tree of HTML elements.
5
+ The state is a singleton object that can be updated, and the UI will re-render when a patch is supplied. Nesting vode-apps is undefined behavior for now.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @ryupold/vode --save
11
+ ```
12
+
13
+ ## Patch
14
+
15
+ The `patch` function returned by `app(...)` is a function that can be passed an object called `Patch` this object is used to update the state and re-render the UI. It takes a `Patch` object that describes the changes to be made to the state in a "trickle down manner". The `Patch` can be a simple object or a function that returns a new `Patch` to the current state. It can also be an async and/or genrator function that yields `Patch`es. Events also can return a `Patch`. When a number | boolean | string | null | undefined is applied as a `Patch`, it will be ignored.
16
+
17
+ ## Usage
18
+
19
+ index.html
20
+
21
+ ```html
22
+ <html>
23
+ <head>
24
+ <title>Vode Example</title>
25
+ <script type="module" src="main.js"></script>
26
+ </head>
27
+ <body>
28
+ <div id="app"></div>
29
+ </body>
30
+ </html>
31
+ ```
32
+
33
+ main.ts
34
+ ```ts
35
+ // import { app, createState} from 'vode.js';
36
+ // import { BR, DIV, INPUT, SPAN } from 'vode-tags.js';
37
+ import { app, createState, BR, DIV, INPUT, SPAN } from '@ryupold/vode';
38
+
39
+
40
+ const init = createState({
41
+ counter: 0,
42
+ });
43
+
44
+ type State = typeof init;
45
+
46
+ const appNode = document.getElementById('app');
47
+
48
+ app<State>(appNode, init,
49
+ (s: State) => [DIV,
50
+ [INPUT, {
51
+ type: 'button',
52
+ onclick: { counter: s.counter + 1 },
53
+ value: 'Click me',
54
+ }],
55
+ [BR],
56
+ [SPAN, { style: { color: 'red' } }, `${s.counter}`],
57
+ ]
58
+ );
59
+ ```
60
+
61
+ ## Claude
62
+
63
+ > Prompt: "what can you tell me about the overall design philosophy of the vode library based on what you see in `src/vode.ts`"
64
+
65
+
66
+ Based on my analysis of `src/vode.ts`, here's the overall design philosophy of the vode library:
67
+
68
+ ### Core Design Philosophy
69
+
70
+ **Functional Virtual DOM with Minimal Abstractions**
71
+ - Uses array-based virtual nodes (`[tag, props?, ...children]`) instead of object-based structures
72
+ - Prioritizes simplicity and performance over complex abstractions
73
+
74
+ **State-Centric Architecture**
75
+ - Central state object with patch-based updates
76
+ - Immutable-style state management with deep merging
77
+ - Single source of truth pattern
78
+
79
+ **Zero-Dependency Minimalism**
80
+ - Pure TypeScript/JavaScript implementation
81
+ - No external dependencies or build tools required
82
+ - Direct DOM manipulation without heavy runtime
83
+
84
+ ### Key Architectural Decisions
85
+
86
+ #### Virtual DOM Structure
87
+ ```typescript
88
+ // Simple array-based nodes
89
+ ["div", { class: "container" }, "Hello", ["span", "World"]]
90
+ ```
91
+ - Minimal memory footprint
92
+ - Easy serialization/debugging
93
+ - Type-safe with TypeScript generics
94
+
95
+ #### Reactive State Management
96
+ ```typescript
97
+ state.patch(newData) // Direct updates
98
+ state.patch([effect, payload]) // Function-based effects
99
+ state.patch(promise) // Async support
100
+ ```
101
+ - Unified patch system for all state changes
102
+ - Built-in async/generator support
103
+ - Functional effects pattern
104
+
105
+ #### Performance Optimizations
106
+ - **Memoization**: `memo()` for component caching
107
+ - **Reconciliation**: Intelligent DOM diffing
108
+ - **Batched Updates**: RequestAnimationFrame-based rendering
109
+ - **Memory Management**: Proper cleanup with mount/unmount hooks
110
+
111
+ #### Developer Experience
112
+ - **Type Safety**: Full TypeScript support with generics
113
+ - **Debugging**: Built-in performance statistics
114
+ - **Flexibility**: Support for HTML, SVG, and MathML
115
+ - **Composability**: Functional component model
116
+
117
+ ### Philosophy Summary
118
+
119
+ Vode follows a **"less is more"** philosophy, providing a lightweight alternative to heavyweight frameworks while maintaining modern reactive patterns. It emphasizes:
120
+
121
+ 1. **Explicitness over magic** - Clear, predictable behavior
122
+ 2. **Performance by design** - Minimal overhead, efficient updates
123
+ 3. **Developer control** - Direct state manipulation without hidden abstractions
124
+ 4. **Functional paradigms** - Immutable updates, pure components
125
+ 5. **Modern web standards** - Leverages native browser APIs effectively
126
+
127
127
  The library appears designed for developers who want React-like reactivity without the complexity and bundle size of modern frameworks.
package/index.ts CHANGED
@@ -1,3 +1,3 @@
1
- export * from "./src/vode.js";
2
- export * from "./src/vode-tags.js";
1
+ export * from "./src/vode.js";
2
+ export * from "./src/vode-tags.js";
3
3
  export * from "./src/html.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryupold/vode",
3
- "version": "0.9.4",
3
+ "version": "0.9.5",
4
4
  "description": "Small web framework for minimal websites",
5
5
  "author": "Michael Scherbakow (ryupold)",
6
6
  "license": "MIT",
@@ -23,7 +23,7 @@
23
23
  "module": "index.ts",
24
24
  "scripts": {
25
25
  "build": "bun build index.ts --outfile index.js",
26
- "pack": "bun run build && bun pm pack",
26
+ "pack": "rm *.tgz && bun run build && bun pm pack",
27
27
  "publish": "bun publish --provenance --access public",
28
28
  "clean": "tsc -b --clean",
29
29
  "watch": "tsc -b -w"
package/src/html.ts CHANGED
@@ -1,37 +1,37 @@
1
- import { Props, Vode } from "./vode.js";
2
-
3
- export function htmlToVode<S extends object | unknown>(html: string): (Vode<S> | string)[] {
4
- const div = document.createElement('div');
5
- div.innerHTML = html.trim();
6
-
7
- const vodes: (Vode<S> | string)[] = [];
8
- for (const child of div.childNodes) {
9
- const v = elementToVode<S>(<Element>child);
10
- if (v != null) vodes.push(v);
11
- }
12
- return vodes;
13
- }
14
-
15
- function elementToVode<S>(element: Element): Vode<S> | string | undefined | null {
16
- if (element.nodeType === Node.TEXT_NODE) {
17
- return element.textContent;
18
- }
19
- if (element.nodeType !== Node.ELEMENT_NODE) {
20
- return undefined;
21
- }
22
- const vode = <Vode<S>>[element.tagName.toLowerCase()];
23
-
24
- if (element.hasAttributes()) {
25
- const props = <Props<S>>{};
26
- for (const att of element.attributes) {
27
- props[att.name] = att.value;
28
- }
29
- (<any[]>vode).push(props);
30
- }
31
-
32
- for (const child of element.childNodes) {
33
- const v = elementToVode(<Element>child);
34
- if (v && (typeof v !== "string" || v.length > 0)) (<any[]>vode).push(v);
35
- }
36
- return vode;
37
- }
1
+ import { Props, Vode } from "./vode.js";
2
+
3
+ export function htmlToVode<S extends object | unknown>(html: string): (Vode<S> | string)[] {
4
+ const div = document.createElement('div');
5
+ div.innerHTML = html.trim();
6
+
7
+ const vodes: (Vode<S> | string)[] = [];
8
+ for (const child of div.childNodes) {
9
+ const v = elementToVode<S>(<Element>child);
10
+ if (v != null) vodes.push(v);
11
+ }
12
+ return vodes;
13
+ }
14
+
15
+ function elementToVode<S>(element: Element): Vode<S> | string | undefined | null {
16
+ if (element.nodeType === Node.TEXT_NODE) {
17
+ return element.textContent;
18
+ }
19
+ if (element.nodeType !== Node.ELEMENT_NODE) {
20
+ return undefined;
21
+ }
22
+ const vode = <Vode<S>>[element.tagName.toLowerCase()];
23
+
24
+ if (element.hasAttributes()) {
25
+ const props = <Props<S>>{};
26
+ for (const att of element.attributes) {
27
+ props[att.name] = att.value;
28
+ }
29
+ (<any[]>vode).push(props);
30
+ }
31
+
32
+ for (const child of element.childNodes) {
33
+ const v = elementToVode(<Element>child);
34
+ if (v && (typeof v !== "string" || v.length > 0)) (<any[]>vode).push(v);
35
+ }
36
+ return vode;
37
+ }