sigmx 0.1.0 → 0.1.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 +52 -41
- package/dist/cli.js +3 -1
- package/dist/cli.js.map +2 -2
- package/dist/kernel/compile.js.map +2 -2
- package/dist/kernel/contracts.d.ts +1 -8
- package/dist/kernel/index.d.ts +10 -11
- package/dist/kernel/index.js +10 -7
- package/dist/kernel/index.js.map +3 -3
- package/dist/kernel/precompile.d.ts +0 -2
- package/dist/kernel/precompile.js +11 -4
- package/dist/kernel/precompile.js.map +2 -2
- package/dist/kernel/precompiled.js.map +2 -2
- package/dist/kernel/reactive.d.ts +6 -10
- package/dist/kernel/reactive.js +4 -8
- package/dist/kernel/reactive.js.map +2 -2
- package/dist/kernel/runtime.js +19 -7
- package/dist/kernel/runtime.js.map +2 -2
- package/dist/kernel/scan.d.ts +1 -10
- package/dist/kernel/scan.js +24 -7
- package/dist/kernel/scan.js.map +2 -2
- package/dist/kernel/state.d.ts +1 -5
- package/dist/kernel/state.js +49 -22
- package/dist/kernel/state.js.map +2 -2
- package/dist/kernel/strict-csp.js.map +1 -1
- package/dist/lib/casing.js.map +2 -2
- package/dist/lib/objects.d.ts +0 -1
- package/dist/lib/objects.js +4 -1
- package/dist/lib/objects.js.map +2 -2
- package/dist/lib/schedule.d.ts +0 -2
- package/dist/lib/schedule.js.map +2 -2
- package/dist/lib/sse.d.ts +0 -1
- package/dist/lib/sse.js +3 -2
- package/dist/lib/sse.js.map +2 -2
- package/dist/plugins/directives/attribute-sync.js.map +1 -1
- package/dist/plugins/directives/boost.js +2 -1
- package/dist/plugins/directives/boost.js.map +2 -2
- package/dist/plugins/directives/busy-flag.js.map +1 -1
- package/dist/plugins/directives/class-toggle.js.map +1 -1
- package/dist/plugins/directives/cloak.js.map +1 -1
- package/dist/plugins/directives/collapse.js.map +1 -1
- package/dist/plugins/directives/declare.js.map +1 -1
- package/dist/plugins/directives/derive.js +4 -1
- package/dist/plugins/directives/derive.js.map +2 -2
- package/dist/plugins/directives/element-ref.js.map +1 -1
- package/dist/plugins/directives/event-listener.js +4 -1
- package/dist/plugins/directives/event-listener.js.map +2 -2
- package/dist/plugins/directives/frame-loop.js.map +1 -1
- package/dist/plugins/directives/html.js.map +1 -1
- package/dist/plugins/directives/inline-style.js +1 -1
- package/dist/plugins/directives/inline-style.js.map +2 -2
- package/dist/plugins/directives/mask.js.map +1 -1
- package/dist/plugins/directives/media-query.js +2 -1
- package/dist/plugins/directives/media-query.js.map +2 -2
- package/dist/plugins/directives/on-mount.js +4 -1
- package/dist/plugins/directives/on-mount.js.map +2 -2
- package/dist/plugins/directives/patch-listener.js.map +1 -1
- package/dist/plugins/directives/remove-me.js.map +1 -1
- package/dist/plugins/directives/scroll-to.js.map +1 -1
- package/dist/plugins/directives/size-watch.js.map +1 -1
- package/dist/plugins/directives/state-dump.js.map +1 -1
- package/dist/plugins/directives/storage-sync.js.map +1 -1
- package/dist/plugins/directives/teleport.js.map +1 -1
- package/dist/plugins/directives/text-content.js.map +1 -1
- package/dist/plugins/directives/timer.js.map +1 -1
- package/dist/plugins/directives/transition-name.js.map +1 -1
- package/dist/plugins/directives/transition.js.map +1 -1
- package/dist/plugins/directives/trap.js +8 -2
- package/dist/plugins/directives/trap.js.map +2 -2
- package/dist/plugins/directives/tween.js.map +2 -2
- package/dist/plugins/directives/two-way-bind.js +37 -7
- package/dist/plugins/directives/two-way-bind.js.map +2 -2
- package/dist/plugins/directives/url-params.js +2 -1
- package/dist/plugins/directives/url-params.js.map +2 -2
- package/dist/plugins/directives/url-replace.js.map +1 -1
- package/dist/plugins/directives/validity.js.map +1 -1
- package/dist/plugins/directives/viewport.js +4 -1
- package/dist/plugins/directives/viewport.js.map +2 -2
- package/dist/plugins/directives/visibility.js.map +1 -1
- package/dist/plugins/directives/watch.d.ts +0 -1
- package/dist/plugins/directives/watch.js.map +2 -2
- package/dist/plugins/functions/bulk-set.js +5 -3
- package/dist/plugins/functions/bulk-set.js.map +2 -2
- package/dist/plugins/functions/bulk-toggle.js +5 -3
- package/dist/plugins/functions/bulk-toggle.js.map +2 -2
- package/dist/plugins/functions/confirm.js.map +1 -1
- package/dist/plugins/functions/copy-text.js.map +1 -1
- package/dist/plugins/functions/dispatch.js.map +2 -2
- package/dist/plugins/functions/locale-format.js.map +1 -1
- package/dist/plugins/functions/range-map.js.map +1 -1
- package/dist/plugins/functions/request.js +19 -5
- package/dist/plugins/functions/request.js.map +2 -2
- package/dist/plugins/functions/untracked-read.js.map +1 -1
- package/dist/plugins/functions/websocket.js +5 -1
- package/dist/plugins/functions/websocket.js.map +2 -2
- package/dist/plugins/index.d.ts +36 -36
- package/dist/plugins/index.js +33 -33
- package/dist/plugins/index.js.map +2 -2
- package/dist/plugins/server-events/apply-elements.js +4 -1
- package/dist/plugins/server-events/apply-elements.js.map +2 -2
- package/dist/plugins/server-events/apply-state.js.map +1 -1
- package/dist/plugins/server-events/morph.d.ts +0 -2
- package/dist/plugins/server-events/morph.js +31 -8
- package/dist/plugins/server-events/morph.js.map +2 -2
- package/dist/presets/all.d.ts +0 -1
- package/dist/presets/all.js +23 -23
- package/dist/presets/all.js.map +2 -2
- package/dist/presets/essentials.d.ts +0 -1
- package/dist/presets/essentials.js +27 -9
- package/dist/presets/essentials.js.map +2 -2
- package/dist/presets/minimal.d.ts +0 -1
- package/dist/presets/minimal.js +2 -2
- package/dist/presets/minimal.js.map +2 -2
- package/dist/server.d.ts +102 -0
- package/dist/server.js +190 -0
- package/dist/server.js.map +7 -0
- package/dist/sigmx.standalone.js +1 -1
- package/dist/standalone.js.map +2 -2
- package/dist/vite.d.ts +2 -2
- package/dist/vite.js +31 -8
- package/dist/vite.js.map +2 -2
- package/package.json +19 -2
- package/dist/auto.d.ts +0 -1
- package/dist/auto.js +0 -7
- package/dist/auto.js.map +0 -7
- package/dist/core/csp.d.ts +0 -7
- package/dist/core/csp.js +0 -20
- package/dist/core/csp.js.map +0 -7
- package/dist/core/engine.d.ts +0 -10
- package/dist/core/engine.js +0 -200
- package/dist/core/engine.js.map +0 -7
- package/dist/core/expr.d.ts +0 -12
- package/dist/core/expr.js +0 -94
- package/dist/core/expr.js.map +0 -7
- package/dist/core/index.d.ts +0 -16
- package/dist/core/index.js +0 -46
- package/dist/core/index.js.map +0 -7
- package/dist/core/signals.d.ts +0 -42
- package/dist/core/signals.js +0 -195
- package/dist/core/signals.js.map +0 -7
- package/dist/core/store.d.ts +0 -32
- package/dist/core/store.js +0 -185
- package/dist/core/store.js.map +0 -7
- package/dist/core/types.d.ts +0 -101
- package/dist/core/types.js +0 -1
- package/dist/core/types.js.map +0 -7
- package/dist/plugins/actions/clipboard.d.ts +0 -2
- package/dist/plugins/actions/clipboard.js +0 -11
- package/dist/plugins/actions/clipboard.js.map +0 -7
- package/dist/plugins/actions/fit.d.ts +0 -2
- package/dist/plugins/actions/fit.js +0 -14
- package/dist/plugins/actions/fit.js.map +0 -7
- package/dist/plugins/actions/intl.d.ts +0 -2
- package/dist/plugins/actions/intl.js +0 -21
- package/dist/plugins/actions/intl.js.map +0 -7
- package/dist/plugins/actions/peek.d.ts +0 -2
- package/dist/plugins/actions/peek.js +0 -6
- package/dist/plugins/actions/peek.js.map +0 -7
- package/dist/plugins/actions/setAll.d.ts +0 -2
- package/dist/plugins/actions/setAll.js +0 -11
- package/dist/plugins/actions/setAll.js.map +0 -7
- package/dist/plugins/actions/toggleAll.d.ts +0 -2
- package/dist/plugins/actions/toggleAll.js +0 -11
- package/dist/plugins/actions/toggleAll.js.map +0 -7
- package/dist/plugins/attributes/attr.d.ts +0 -2
- package/dist/plugins/attributes/attr.js +0 -20
- package/dist/plugins/attributes/attr.js.map +0 -7
- package/dist/plugins/attributes/bind.d.ts +0 -6
- package/dist/plugins/attributes/bind.js +0 -81
- package/dist/plugins/attributes/bind.js.map +0 -7
- package/dist/plugins/attributes/class.d.ts +0 -2
- package/dist/plugins/attributes/class.js +0 -22
- package/dist/plugins/attributes/class.js.map +0 -7
- package/dist/plugins/attributes/computed.d.ts +0 -2
- package/dist/plugins/attributes/computed.js +0 -20
- package/dist/plugins/attributes/computed.js.map +0 -7
- package/dist/plugins/attributes/customValidity.d.ts +0 -2
- package/dist/plugins/attributes/customValidity.js +0 -14
- package/dist/plugins/attributes/customValidity.js.map +0 -7
- package/dist/plugins/attributes/effect.d.ts +0 -2
- package/dist/plugins/attributes/effect.js +0 -12
- package/dist/plugins/attributes/effect.js.map +0 -7
- package/dist/plugins/attributes/indicator.d.ts +0 -2
- package/dist/plugins/attributes/indicator.js +0 -20
- package/dist/plugins/attributes/indicator.js.map +0 -7
- package/dist/plugins/attributes/init.d.ts +0 -2
- package/dist/plugins/attributes/init.js +0 -14
- package/dist/plugins/attributes/init.js.map +0 -7
- package/dist/plugins/attributes/jsonSignals.d.ts +0 -2
- package/dist/plugins/attributes/jsonSignals.js +0 -15
- package/dist/plugins/attributes/jsonSignals.js.map +0 -7
- package/dist/plugins/attributes/matchMedia.d.ts +0 -2
- package/dist/plugins/attributes/matchMedia.js +0 -19
- package/dist/plugins/attributes/matchMedia.js.map +0 -7
- package/dist/plugins/attributes/on.d.ts +0 -5
- package/dist/plugins/attributes/on.js +0 -28
- package/dist/plugins/attributes/on.js.map +0 -7
- package/dist/plugins/attributes/onIntersect.d.ts +0 -2
- package/dist/plugins/attributes/onIntersect.js +0 -28
- package/dist/plugins/attributes/onIntersect.js.map +0 -7
- package/dist/plugins/attributes/onInterval.d.ts +0 -2
- package/dist/plugins/attributes/onInterval.js +0 -18
- package/dist/plugins/attributes/onInterval.js.map +0 -7
- package/dist/plugins/attributes/onRaf.d.ts +0 -1
- package/dist/plugins/attributes/onRaf.js +0 -19
- package/dist/plugins/attributes/onRaf.js.map +0 -7
- package/dist/plugins/attributes/onResize.d.ts +0 -1
- package/dist/plugins/attributes/onResize.js +0 -17
- package/dist/plugins/attributes/onResize.js.map +0 -7
- package/dist/plugins/attributes/onSignalPatch.d.ts +0 -5
- package/dist/plugins/attributes/onSignalPatch.js +0 -35
- package/dist/plugins/attributes/onSignalPatch.js.map +0 -7
- package/dist/plugins/attributes/persist.d.ts +0 -6
- package/dist/plugins/attributes/persist.js +0 -16
- package/dist/plugins/attributes/persist.js.map +0 -7
- package/dist/plugins/attributes/queryString.d.ts +0 -5
- package/dist/plugins/attributes/queryString.js +0 -54
- package/dist/plugins/attributes/queryString.js.map +0 -7
- package/dist/plugins/attributes/ref.d.ts +0 -2
- package/dist/plugins/attributes/ref.js +0 -13
- package/dist/plugins/attributes/ref.js.map +0 -7
- package/dist/plugins/attributes/replaceUrl.d.ts +0 -1
- package/dist/plugins/attributes/replaceUrl.js +0 -11
- package/dist/plugins/attributes/replaceUrl.js.map +0 -7
- package/dist/plugins/attributes/scrollIntoView.d.ts +0 -2
- package/dist/plugins/attributes/scrollIntoView.js +0 -19
- package/dist/plugins/attributes/scrollIntoView.js.map +0 -7
- package/dist/plugins/attributes/show.d.ts +0 -2
- package/dist/plugins/attributes/show.js +0 -19
- package/dist/plugins/attributes/show.js.map +0 -7
- package/dist/plugins/attributes/signals.d.ts +0 -2
- package/dist/plugins/attributes/signals.js +0 -13
- package/dist/plugins/attributes/signals.js.map +0 -7
- package/dist/plugins/attributes/style.d.ts +0 -2
- package/dist/plugins/attributes/style.js +0 -25
- package/dist/plugins/attributes/style.js.map +0 -7
- package/dist/plugins/attributes/text.d.ts +0 -1
- package/dist/plugins/attributes/text.js +0 -13
- package/dist/plugins/attributes/text.js.map +0 -7
- package/dist/plugins/attributes/viewTransition.d.ts +0 -1
- package/dist/plugins/attributes/viewTransition.js +0 -11
- package/dist/plugins/attributes/viewTransition.js.map +0 -7
- package/dist/sigmx.auto.js +0 -5
- package/dist/utils/object.d.ts +0 -9
- package/dist/utils/object.js +0 -26
- package/dist/utils/object.js.map +0 -7
- package/dist/utils/text.d.ts +0 -7
- package/dist/utils/text.js +0 -15
- package/dist/utils/text.js.map +0 -7
- package/dist/utils/timing.d.ts +0 -14
- package/dist/utils/timing.js +0 -58
- package/dist/utils/timing.js.map +0 -7
package/README.md
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# sigmx
|
|
2
2
|
|
|
3
|
+
[](https://github.com/wrux/sigmx/actions/workflows/ci.yml)
|
|
4
|
+
|
|
3
5
|
**htmx on steroids, in a runtime smaller than htmx.**
|
|
4
6
|
|
|
5
7
|
> **Status: an experiment.** sigmx is a personal exploration of what a hypermedia library looks like when it starts from a tiny, plugin-based core. It is inspired by [htmx](https://htmx.org) (the server sends HTML, the browser swaps it in), [Alpine.js](https://alpinejs.dev) (declarative `data-*` attributes with a little reactivity) and [Datastar](https://data-star.dev) (which fused the two and whose attribute syntax sigmx keeps for compatibility). The code is original, the APIs may still change, and it has not been used in production. Try it, break it, and open an issue with what you find.
|
|
6
8
|
|
|
7
9
|
Your server renders HTML, as it always has. The browser asks for more of it with `@get` and `@post`, and sigmx merges the response into the page with a morph that keeps focus, typed input and scroll position. When you want live updates, the same request can return a stream of patches instead. Signals, two-way binding and reactive attributes cover the client-side state. You write `data-*` attributes and register only the plugins you use.
|
|
8
10
|
|
|
9
|
-
- **Tiny.** 4.
|
|
11
|
+
- **Tiny.** 4.1 KB core, 8.8 KB with the essentials, 12.1 KB with all 52 plugins (brotli). Zero runtime dependencies.
|
|
10
12
|
- **Server-driven.** Return plain HTML from any endpoint and it is morphed into the page by id, or targeted with a header. Return JSON to merge signals, or an event stream to push many patches over one request, with `Last-Event-ID` reconnects.
|
|
11
13
|
- **Reactive where it matters.** Signals declared in markup; `bind`, `show`, `class`, computed values and effects keep the page in step. No component model, no virtual DOM.
|
|
12
14
|
- **Pay for what you use.** Every directive and function is an opt-in plugin, and auto mode scans your source to bundle exactly the set it finds.
|
|
@@ -15,7 +17,7 @@ Your server renders HTML, as it always has. The browser asks for more of it with
|
|
|
15
17
|
|
|
16
18
|
```html
|
|
17
19
|
<div data-signals="{ count: 0, name: '' }">
|
|
18
|
-
<input data-bind:name placeholder="Your name"
|
|
20
|
+
<input data-bind:name placeholder="Your name" />
|
|
19
21
|
<p data-show="$name">Hello, <span data-text="$name"></span>!</p>
|
|
20
22
|
<button data-on:click="$count++">Clicked <b data-text="$count"></b> times</button>
|
|
21
23
|
<button data-on:click="@post('/save')" data-indicator:saving data-attr:disabled="$saving">Save</button>
|
|
@@ -29,10 +31,10 @@ npm install sigmx
|
|
|
29
31
|
```
|
|
30
32
|
|
|
31
33
|
```ts
|
|
32
|
-
import { createSigmx } from 'sigmx'
|
|
33
|
-
import { essentials } from 'sigmx/presets/essentials'
|
|
34
|
+
import { createSigmx } from 'sigmx';
|
|
35
|
+
import { essentials } from 'sigmx/presets/essentials';
|
|
34
36
|
|
|
35
|
-
createSigmx({ plugins: essentials })
|
|
37
|
+
createSigmx({ plugins: essentials });
|
|
36
38
|
```
|
|
37
39
|
|
|
38
40
|
Or pick plugins by hand (`sigmx/plugins` is tree-shakeable), use `sigmx/presets/minimal` or `sigmx/presets/all`, let [auto mode](#auto-mode) choose, or drop in the script-tag build:
|
|
@@ -41,7 +43,7 @@ Or pick plugins by hand (`sigmx/plugins` is tree-shakeable), use `sigmx/presets/
|
|
|
41
43
|
<script type="module" src="/sigmx.standalone.js"></script>
|
|
42
44
|
```
|
|
43
45
|
|
|
44
|
-
Astro users: `npm install sigmx sigmx
|
|
46
|
+
Astro users: `npm install sigmx @sigmx/astro` and add `sigmx()` to the integrations; see [sdks/astro](sdks/astro). Hono users: `npm install sigmx @sigmx/hono`, then `app.use(sigmx())` gives every handler `c.var.sigmx`; see [sdks/hono](sdks/hono). Everyone else: `sigmx/server` has the same event builders, responses, streams and signal reading as plain Fetch-API code.
|
|
45
47
|
|
|
46
48
|
## How it works
|
|
47
49
|
|
|
@@ -50,17 +52,17 @@ Attributes are `data-<plugin>[:key][__modifier.arg]="expression"`. Expressions a
|
|
|
50
52
|
```html
|
|
51
53
|
<button data-on:click__debounce.300ms="@get('/search')">Search</button>
|
|
52
54
|
<li data-class:active="$page === 3"></li>
|
|
53
|
-
<input data-bind:user.email
|
|
55
|
+
<input data-bind:user.email />
|
|
54
56
|
<p data-text="`${$items.length} items, ${@intl('number', $total, { style: 'currency', currency: 'EUR' })}`"></p>
|
|
55
57
|
```
|
|
56
58
|
|
|
57
59
|
State is one JSON-like store addressed by dotted paths and patched with merge-patch semantics: objects merge, `null` removes, arrays notify on `push`. Requests send the store (minus `_`-prefixed paths) and apply whatever comes back, decided by the response's content type:
|
|
58
60
|
|
|
59
|
-
| the server returns
|
|
60
|
-
|
|
61
|
-
| `text/html`
|
|
62
|
-
| `application/json`
|
|
63
|
-
| `text/event-stream` | applies each event as it arrives: `patch-elements`, `patch-signals`, or your own handlers
|
|
61
|
+
| the server returns | sigmx does |
|
|
62
|
+
| ------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
63
|
+
| `text/html` | morphs it into the page: top-level elements by `id`, or a target from the `sigmx-selector` and `sigmx-mode` headers |
|
|
64
|
+
| `application/json` | merges it into the signals |
|
|
65
|
+
| `text/event-stream` | applies each event as it arrives: `patch-elements`, `patch-signals`, or your own handlers |
|
|
64
66
|
|
|
65
67
|
The everyday case is the first row: render a partial with whatever templating you already use and return it. The morph keeps every element whose id appears on both sides, so a re-rendered form keeps what the user typed. Streams are there for progress, chat and dashboards, where one request should keep delivering:
|
|
66
68
|
|
|
@@ -76,14 +78,14 @@ data: elements <li>Validating…</li>
|
|
|
76
78
|
|
|
77
79
|
## Plugins
|
|
78
80
|
|
|
79
|
-
| kind
|
|
80
|
-
|
|
81
|
-
| state
|
|
82
|
-
| rendering | `text` `html` `show` `class` `style` `attr` `animate` `transition` `collapse` `view-transition` `cloak`
|
|
83
|
-
| forms
|
|
84
|
-
| events
|
|
85
|
-
| layout
|
|
86
|
-
| server
|
|
81
|
+
| kind | plugins |
|
|
82
|
+
| --------- | -------------------------------------------------------------------------------------------------------------- |
|
|
83
|
+
| state | `signals` `computed` `effect` `ref` `persist` `query-string` |
|
|
84
|
+
| rendering | `text` `html` `show` `class` `style` `attr` `animate` `transition` `collapse` `view-transition` `cloak` |
|
|
85
|
+
| forms | `bind` `custom-validity` `mask` |
|
|
86
|
+
| events | `on` `init` `on-interval` `on-intersect` `on-resize` `on-raf` `on-signal-patch` `match-media` |
|
|
87
|
+
| layout | `teleport` `trap` `scroll-into-view` `remove-me` |
|
|
88
|
+
| server | `@get` `@post` `@put` `@patch` `@delete` `@ws` `boost` `indicator` `patch-elements` `patch-signals` |
|
|
87
89
|
| utilities | `@peek` `@setAll` `@toggleAll` `@fit` `@clipboard` `@intl` `@dispatch` `@confirm` `json-signals` `replace-url` |
|
|
88
90
|
|
|
89
91
|
Every plugin has a page in the docs with a live example and its measured size.
|
|
@@ -92,16 +94,16 @@ Every plugin has a page in the docs with a live example and its measured size.
|
|
|
92
94
|
|
|
93
95
|
Brotli, measured from the real source by `npm run size` and `npm run compare` (nothing is quoted from memory):
|
|
94
96
|
|
|
95
|
-
|
|
|
96
|
-
|
|
97
|
-
| sigmx core
|
|
98
|
-
| sigmx essentials (state, rendering, forms, requests, morph) |
|
|
99
|
-
| sigmx everything, 52 plugins
|
|
100
|
-
| htmx 2.0.10
|
|
101
|
-
| Datastar 1.0.3, free bundle (23 plugins)
|
|
102
|
-
| Alpine.js 3.17.1
|
|
97
|
+
| | brotli |
|
|
98
|
+
| ----------------------------------------------------------- | ------: |
|
|
99
|
+
| sigmx core | 4.1 KB |
|
|
100
|
+
| sigmx essentials (state, rendering, forms, requests, morph) | 8.8 KB |
|
|
101
|
+
| sigmx everything, 52 plugins | 12.1 KB |
|
|
102
|
+
| htmx 2.0.10 | 14.6 KB |
|
|
103
|
+
| Datastar 1.0.3, free bundle (23 plugins) | 11.8 KB |
|
|
104
|
+
| Alpine.js 3.17.1 | 17.6 KB |
|
|
103
105
|
|
|
104
|
-
Precompiling expressions at build time removes the runtime compiler and any use of `new Function`, taking the core to 3.
|
|
106
|
+
Precompiling expressions at build time removes the runtime compiler and any use of `new Function`, taking the core to 3.7 KB and making strict CSP trivial.
|
|
105
107
|
|
|
106
108
|
## Auto mode
|
|
107
109
|
|
|
@@ -109,14 +111,14 @@ Like a CSS framework scanning for class names, sigmx can scan your source for th
|
|
|
109
111
|
|
|
110
112
|
```js
|
|
111
113
|
// vite.config.js
|
|
112
|
-
import { sigmxAuto } from 'sigmx/vite'
|
|
113
|
-
export default { plugins: [sigmxAuto({ always: ['signals'], custom: { upper: 'src/plugins/upper.ts' } })] }
|
|
114
|
+
import { sigmxAuto } from 'sigmx/vite';
|
|
115
|
+
export default { plugins: [sigmxAuto({ always: ['signals'], custom: { upper: 'src/plugins/upper.ts' } })] };
|
|
114
116
|
```
|
|
115
117
|
|
|
116
118
|
```ts
|
|
117
|
-
import { createSigmx } from 'sigmx'
|
|
118
|
-
import { plugins } from 'virtual:sigmx-plugins'
|
|
119
|
-
createSigmx({ plugins })
|
|
119
|
+
import { createSigmx } from 'sigmx';
|
|
120
|
+
import { plugins } from 'virtual:sigmx-plugins';
|
|
121
|
+
createSigmx({ plugins });
|
|
120
122
|
```
|
|
121
123
|
|
|
122
124
|
Without Vite: `npx sigmx scan src --out src/sigmx-plugins.js`. In Astro: `sigmx({ plugins: 'auto' })`.
|
|
@@ -124,15 +126,17 @@ Without Vite: `npx sigmx scan src --out src/sigmx-plugins.js`. In Astro: `sigmx(
|
|
|
124
126
|
## Writing a plugin
|
|
125
127
|
|
|
126
128
|
```ts
|
|
127
|
-
import { attribute } from 'sigmx'
|
|
129
|
+
import { attribute } from 'sigmx';
|
|
128
130
|
|
|
129
131
|
export const upper = attribute({
|
|
130
132
|
name: 'upper',
|
|
131
133
|
value: 'required',
|
|
132
134
|
mount({ el, evaluate, effect }) {
|
|
133
|
-
effect(() => {
|
|
135
|
+
effect(() => {
|
|
136
|
+
el.textContent = String(evaluate()).toUpperCase();
|
|
137
|
+
});
|
|
134
138
|
},
|
|
135
|
-
})
|
|
139
|
+
});
|
|
136
140
|
```
|
|
137
141
|
|
|
138
142
|
Plugins are plain objects; nothing registers on import. The mount context gives you `evaluate`, `effect`, `listen`, `cleanup`, the store and the runtime, and everything registered through it is torn down when the attribute or element goes away. Functions (`@name()`) and server-event handlers work the same way with `action()` and `handler()`.
|
|
@@ -149,24 +153,31 @@ cd website && npm install && npm run dev
|
|
|
149
153
|
|
|
150
154
|
```
|
|
151
155
|
src/kernel/ reactive graph, store, expression compiler, runtime (DOM-free core)
|
|
156
|
+
src/server.ts sigmx/server: event builders, sse/sseStream/html/json responses, readSignals
|
|
152
157
|
src/plugins/ directives, functions, server-event handlers, the morph
|
|
153
158
|
src/presets/ minimal, essentials, all
|
|
154
|
-
sdks/astro/ sigmx
|
|
159
|
+
sdks/astro/ @sigmx/astro: integration, server helpers, auto mode, precompilation
|
|
160
|
+
sdks/hono/ @sigmx/hono: middleware with signals(), html(), events(), stream(); serveClient()
|
|
161
|
+
examples/ standalone Vite, Express, Hono and Astro projects using the published packages
|
|
155
162
|
website/ documentation site
|
|
156
163
|
scripts/ build, size and comparison measurements, dev server
|
|
157
|
-
tests/ node:test
|
|
164
|
+
tests/ unit (node:test), dom (happy-dom) and browser (Playwright) suites
|
|
158
165
|
```
|
|
159
166
|
|
|
160
167
|
```bash
|
|
161
168
|
npm install
|
|
162
169
|
npm run check # type-check
|
|
163
|
-
npm
|
|
170
|
+
npm run lint # biome: formatting and lint rules
|
|
171
|
+
npm run format # biome: rewrite files in the house style
|
|
172
|
+
npm test # build, then unit tests and happy-dom tests for every plugin
|
|
173
|
+
npm run test:browser # Playwright: transitions, observers, WebSocket, the standalone build
|
|
174
|
+
npm run test:all # everything above plus the SDK suites
|
|
164
175
|
npm run dev # dev server with SSE and WebSocket endpoints; open /tests/browser/index.html
|
|
165
176
|
npm run size # bundle sizes for representative plugin sets
|
|
166
177
|
npm run compare # sizes of htmx, Datastar and Alpine at pinned versions
|
|
167
178
|
```
|
|
168
179
|
|
|
169
|
-
Contributions are welcome. Open an issue first for anything larger than a fix, keep plugins as small as their reference-page size table suggests, and run both test suites before a pull request.
|
|
180
|
+
Contributions are welcome. Open an issue first for anything larger than a fix, keep plugins as small as their reference-page size table suggests, and run `npm run lint` and both test suites before a pull request.
|
|
170
181
|
|
|
171
182
|
## Licence
|
|
172
183
|
|
package/dist/cli.js
CHANGED
|
@@ -9,7 +9,9 @@ const opt = (name) => {
|
|
|
9
9
|
return i < 0 ? void 0 : args.splice(i, 2)[1];
|
|
10
10
|
};
|
|
11
11
|
if (cmd !== "scan") {
|
|
12
|
-
console.log(
|
|
12
|
+
console.log(
|
|
13
|
+
"usage: sigmx scan [dirs...] [--out src/sigmx-plugins.js] [--always signals,httpGet] [--custom upper=src/plugins/upper.ts] [--prefix data-,hx-]"
|
|
14
|
+
);
|
|
13
15
|
process.exit(cmd ? 1 : 0);
|
|
14
16
|
}
|
|
15
17
|
const out = opt("out");
|
package/dist/cli.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/cli.ts"],
|
|
4
|
-
"sourcesContent": ["#!/usr/bin/env node\n// `sigmx scan [dirs...] [--out file] [--always a,b] [--custom name=path,...] [--prefix data-,hx-]`\nimport { writeFileSync } from 'node:fs'
|
|
5
|
-
"mappings": ";AAEA,SAAS,qBAAqB;AAC9B,SAAS,6BAA6B;AACtC,SAAS,mBAAmB;AAE5B,MAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,MAAM,MAAM,KAAK,MAAM;AACvB,MAAM,MAAM,CAAC,SAAiB;AAC5B,QAAM,IAAI,KAAK,QAAQ,KAAK,IAAI,EAAE;AAClC,SAAO,IAAI,IAAI,SAAY,KAAK,OAAO,GAAG,CAAC,EAAE,CAAC;AAChD;AACA,IAAI,QAAQ,QAAQ;AAClB,UAAQ,
|
|
4
|
+
"sourcesContent": ["#!/usr/bin/env node\n// `sigmx scan [dirs...] [--out file] [--always a,b] [--custom name=path,...] [--prefix data-,hx-]`\nimport { writeFileSync } from 'node:fs';\nimport { generatePluginsModule } from './kernel/scan.js';\nimport { scanProject } from './vite.js';\n\nconst args = process.argv.slice(2);\nconst cmd = args.shift();\nconst opt = (name: string) => {\n const i = args.indexOf(`--${name}`);\n return i < 0 ? undefined : args.splice(i, 2)[1];\n};\nif (cmd !== 'scan') {\n console.log(\n 'usage: sigmx scan [dirs...] [--out src/sigmx-plugins.js] [--always signals,httpGet] [--custom upper=src/plugins/upper.ts] [--prefix data-,hx-]',\n );\n process.exit(cmd ? 1 : 0);\n}\nconst out = opt('out');\nconst always = opt('always')?.split(',').filter(Boolean);\nconst prefixes = opt('prefix')?.split(',').filter(Boolean);\nconst custom = Object.fromEntries((opt('custom')?.split(',') ?? []).map((pair) => pair.split('=') as [string, string]));\nconst sel = scanProject({ include: args.length ? args : undefined, always, prefixes, custom });\nconst code = generatePluginsModule(sel);\nif (out) {\n writeFileSync(out, code);\n console.log(`wrote ${out}: ${sel.plugins.length} plugins, ${sel.unused.length} unused`);\n} else process.stdout.write(code);\nfor (const [exp, why] of Object.entries(sel.reasons)) console.error(` ${exp.padEnd(16)} ${why}`);\n"],
|
|
5
|
+
"mappings": ";AAEA,SAAS,qBAAqB;AAC9B,SAAS,6BAA6B;AACtC,SAAS,mBAAmB;AAE5B,MAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,MAAM,MAAM,KAAK,MAAM;AACvB,MAAM,MAAM,CAAC,SAAiB;AAC5B,QAAM,IAAI,KAAK,QAAQ,KAAK,IAAI,EAAE;AAClC,SAAO,IAAI,IAAI,SAAY,KAAK,OAAO,GAAG,CAAC,EAAE,CAAC;AAChD;AACA,IAAI,QAAQ,QAAQ;AAClB,UAAQ;AAAA,IACN;AAAA,EACF;AACA,UAAQ,KAAK,MAAM,IAAI,CAAC;AAC1B;AACA,MAAM,MAAM,IAAI,KAAK;AACrB,MAAM,SAAS,IAAI,QAAQ,GAAG,MAAM,GAAG,EAAE,OAAO,OAAO;AACvD,MAAM,WAAW,IAAI,QAAQ,GAAG,MAAM,GAAG,EAAE,OAAO,OAAO;AACzD,MAAM,SAAS,OAAO,aAAa,IAAI,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,KAAK,MAAM,GAAG,CAAqB,CAAC;AACtH,MAAM,MAAM,YAAY,EAAE,SAAS,KAAK,SAAS,OAAO,QAAW,QAAQ,UAAU,OAAO,CAAC;AAC7F,MAAM,OAAO,sBAAsB,GAAG;AACtC,IAAI,KAAK;AACP,gBAAc,KAAK,IAAI;AACvB,UAAQ,IAAI,SAAS,GAAG,KAAK,IAAI,QAAQ,MAAM,aAAa,IAAI,OAAO,MAAM,SAAS;AACxF,MAAO,SAAQ,OAAO,MAAM,IAAI;AAChC,WAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,IAAI,OAAO,EAAG,SAAQ,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC,IAAI,GAAG,EAAE;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/kernel/compile.ts"],
|
|
4
|
-
"sourcesContent": ["// Expression compiler. Signals need no rewriting: the body runs inside `with (scope)`, where\n// `$count`, `$user.name` and `$` resolve through the store's scope proxy. Only `@action(` is\n// rewritten, into a call on the per-evaluation actions object.\n\nimport type { ExpressionCompiler } from './contracts.js'
|
|
5
|
-
"mappings": "AASO,MAAM,mBAA6B,CAAC,QAAQ,SAAS,SAAS,GAAG,QAAQ,IAAI;AAEpF,MAAM,QAAQ,oBAAI,IAAqC;AAEvD,MAAM,UAAU,CAAC,MAAuB,gBAAgB,KAAK,CAAC;
|
|
4
|
+
"sourcesContent": ["// Expression compiler. Signals need no rewriting: the body runs inside `with (scope)`, where\n// `$count`, `$user.name` and `$` resolve through the store's scope proxy. Only `@action(` is\n// rewritten, into a call on the per-evaluation actions object.\n\nimport type { ExpressionCompiler } from './contracts.js';\n\nexport type Compiler = (params: string[], body: string) => (...args: any[]) => any;\n\n/** Default compiler: `new Function`. Not usable under a strict CSP; see `cspCompiler`. */\nexport const functionCompiler: Compiler = (params, body) => Function(...params, body) as (...args: any[]) => any;\n\nconst cache = new Map<string, (...args: any[]) => any>();\n\nconst isIdent = (c: string): boolean => /[A-Za-z0-9_$]/.test(c);\n\n/** Walk source text, skipping string, template and comment contents; `emit` receives code chars. */\n// biome-ignore lint/suspicious/noConfusingVoidType: callers may return nothing to keep scanning\nconst scan = (src: string, onCode: (c: string, i: number) => number | void): void => {\n let i = 0;\n const n = src.length;\n while (i < n) {\n const c = src[i];\n const next = src[i + 1];\n if (c === '\"' || c === \"'\" || c === '`') {\n let j = i + 1;\n while (j < n && src[j] !== c) j += src[j] === '\\\\' ? 2 : 1;\n onCode(src.slice(i, j + 1), i);\n i = j + 1;\n } else if (c === '/' && next === '/') {\n const j = src.indexOf('\\n', i);\n i = j < 0 ? n : j;\n } else if (c === '/' && next === '*') {\n const j = src.indexOf('*/', i + 2);\n i = j < 0 ? n : j + 2;\n } else {\n const skip = onCode(c, i);\n i += skip || 1;\n }\n }\n};\n\n/** Replace `@name(` with `__a.name(` outside strings and comments. */\nexport const rewriteActions = (src: string): string => {\n let out = '';\n scan(src, (c, i) => {\n if (c === '@') {\n let j = i + 1;\n while (j < src.length && isIdent(src[j])) j++;\n let k = j;\n while (k < src.length && /\\s/.test(src[k])) k++;\n if (j > i + 1 && src[k] === '(') {\n out += `__a.${src.slice(i + 1, j)}(`;\n return k + 1 - i;\n }\n }\n out += c;\n });\n return out;\n};\n\n/** Split on top-level semicolons. */\nexport const splitStatements = (src: string): string[] => {\n const parts: string[] = [];\n let depth = 0;\n let start = 0;\n scan(src, (c, i) => {\n if (c.length > 1) return;\n if ('([{'.includes(c)) depth++;\n else if (')]}'.includes(c)) depth--;\n else if (c === ';' && !depth) {\n parts.push(src.slice(start, i));\n start = i + 1;\n }\n });\n parts.push(src.slice(start));\n return parts.filter((p) => p.trim());\n};\n\n/**\n * Compile an expression to `(store, actions, ...params) => any`: the body runs inside\n * `with (store.scope)`, so `$name` resolves through the store. With `returns`, the value of the\n * last statement is returned, so `$a = 1; $a * 2` works. Compiled functions are cached by source.\n */\nexport const compile = (\n compiler: Compiler,\n src: string,\n params: string[],\n returns: boolean,\n): ((...args: any[]) => any) => {\n const key = `${+returns}|${params.join()}|${src}`;\n const hit = cache.get(key);\n if (hit) return hit;\n const code = rewriteActions(src.trim());\n const make = (body: string) => compiler(['$', '__a', ...params], `with($.scope){${body}\\n}`);\n let fn: (...args: any[]) => any;\n if (!returns) {\n fn = make(code);\n } else {\n try {\n fn = make(`return(${code}\\n)`);\n } catch {\n const parts = splitStatements(code);\n const last = parts.pop() ?? '';\n try {\n fn = make(`${parts.join(';')};return(${last}\\n)`);\n } catch {\n fn = make(code);\n }\n }\n }\n cache.set(key, fn);\n return fn;\n};\n\n/** The default pipeline: compile at runtime inside `with (scope)` using `compiler` (`new Function` or CSP). */\nexport const runtimeExpressions =\n (compiler: Compiler): ExpressionCompiler =>\n (src, params, returns) =>\n compile(compiler, src, params, returns);\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import type { CaseStyle } from '../lib/casing.js';
|
|
1
2
|
import type { Compiler } from './compile.js';
|
|
2
3
|
import type { Store } from './state.js';
|
|
3
|
-
import type { CaseStyle } from '../lib/casing.js';
|
|
4
4
|
export type El = HTMLElement | SVGElement | MathMLElement;
|
|
5
5
|
export type Mods = Map<string, string[]>;
|
|
6
6
|
/** A compiled attribute expression. `store` is the instance store; `actions` resolves `@name(...)`. */
|
|
@@ -17,7 +17,6 @@ export interface Runtime {
|
|
|
17
17
|
readonly compiler: Compiler;
|
|
18
18
|
/** Dispatch a `sigmx-<type>` CustomEvent on `document`. */
|
|
19
19
|
emit(type: string, detail?: unknown): void;
|
|
20
|
-
/** Call a registered action by name. */
|
|
21
20
|
call(name: string, ctx: ActionCtx, args: any[]): any;
|
|
22
21
|
/** Event-name prefixes accepted from servers; the first is what sigmx itself uses. */
|
|
23
22
|
readonly eventPrefixes: readonly string[];
|
|
@@ -29,13 +28,10 @@ export interface Runtime {
|
|
|
29
28
|
}
|
|
30
29
|
export interface Ctx {
|
|
31
30
|
el: El;
|
|
32
|
-
/** Plugin name, e.g. 'on'. */
|
|
33
31
|
plugin: string;
|
|
34
32
|
/** Full attribute name as written, e.g. 'data-on:click__debounce.300ms'. */
|
|
35
33
|
attr: string;
|
|
36
|
-
/** The `:key` part, if any. */
|
|
37
34
|
key: string | undefined;
|
|
38
|
-
/** Attribute value (the expression source). */
|
|
39
35
|
value: string;
|
|
40
36
|
mods: Mods;
|
|
41
37
|
/** The key recased per `__case.<style>`, defaulting to `style`. */
|
|
@@ -76,7 +72,6 @@ export interface ActionPlugin {
|
|
|
76
72
|
name: string;
|
|
77
73
|
call(ctx: ActionCtx, ...args: any[]): any;
|
|
78
74
|
}
|
|
79
|
-
/** Handles a named server event (for example a streamed patch). */
|
|
80
75
|
export interface HandlerPlugin {
|
|
81
76
|
type: 'handler';
|
|
82
77
|
name: string;
|
|
@@ -93,7 +88,6 @@ export interface RuntimeOptions {
|
|
|
93
88
|
prefix?: string | string[];
|
|
94
89
|
/** Server event-name prefixes to accept, add a second prefix while migrating from another library. Default 'sigmx-'. */
|
|
95
90
|
eventPrefix?: string | string[];
|
|
96
|
-
/** Share a store between instances. */
|
|
97
91
|
store?: Store;
|
|
98
92
|
/** Called for any plugin or expression error. Default: console.error. */
|
|
99
93
|
onError?: (error: unknown, info: {
|
|
@@ -113,7 +107,6 @@ export interface Sigmx {
|
|
|
113
107
|
store: Store;
|
|
114
108
|
/** Root namespace proxy for use from JavaScript: `sigmx.$.count++`. */
|
|
115
109
|
$: any;
|
|
116
|
-
/** Mount plugins under `root` and observe it for changes. */
|
|
117
110
|
apply(root?: El | ShadowRoot, observe?: boolean): void;
|
|
118
111
|
/** Register more plugins; attribute plugins are applied to observed roots immediately. */
|
|
119
112
|
use(...plugins: Plugin[]): void;
|
package/dist/kernel/index.d.ts
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { camel, kebab, pascal, recase, snake } from '../lib/casing.js';
|
|
2
|
+
export type { Filter } from '../lib/objects.js';
|
|
3
|
+
export { expand, isPlain, toPredicate } from '../lib/objects.js';
|
|
4
|
+
export { debounce, delay, throttle, toMs, withTiming, withViewTransition } from '../lib/schedule.js';
|
|
5
|
+
export type { Compiler } from './compile.js';
|
|
2
6
|
export { compile, functionCompiler, rewriteActions, runtimeExpressions, splitStatements } from './compile.js';
|
|
3
|
-
export
|
|
7
|
+
export type * from './contracts.js';
|
|
4
8
|
export type { ExpressionTable } from './precompiled.js';
|
|
5
|
-
export
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
9
|
+
export { expressionKey, precompiled } from './precompiled.js';
|
|
10
|
+
export { batch, Computed, computed, effect, flush, onSettled, Signal, signal, untracked } from './reactive.js';
|
|
11
|
+
export { createRuntime, parseAttr } from './runtime.js';
|
|
8
12
|
export type { Patch, Store } from './state.js';
|
|
9
|
-
export
|
|
10
|
-
export { expand, isPlain, toPredicate } from '../lib/objects.js';
|
|
11
|
-
export type { Filter } from '../lib/objects.js';
|
|
12
|
-
export { camel, kebab, pascal, recase, snake } from '../lib/casing.js';
|
|
13
|
-
export { debounce, delay, throttle, toMs, withTiming, withViewTransition } from '../lib/schedule.js';
|
|
13
|
+
export { createStore } from './state.js';
|
|
14
14
|
import type { ActionPlugin, AttributePlugin, HandlerPlugin, Sigmx, SigmxOptions } from './contracts.js';
|
|
15
15
|
/** Create an instance. Expressions compile at runtime unless you pass `expressions` (see `precompiled`). */
|
|
16
16
|
export declare const createSigmx: (options?: SigmxOptions) => Sigmx;
|
|
17
|
-
/** Type a plugin definition. Pure: registration is `createSigmx({ plugins })` or `sigmx.use()`. */
|
|
18
17
|
export declare const attribute: (p: Omit<AttributePlugin, "type">) => AttributePlugin;
|
|
19
18
|
export declare const action: (p: Omit<ActionPlugin, "type">) => ActionPlugin;
|
|
20
19
|
export declare const handler: (p: Omit<HandlerPlugin, "type">) => HandlerPlugin;
|
package/dist/kernel/index.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { camel, kebab, pascal, recase, snake } from "../lib/casing.js";
|
|
2
|
+
import { expand, isPlain, toPredicate } from "../lib/objects.js";
|
|
3
|
+
import { debounce, delay, throttle, toMs, withTiming, withViewTransition } from "../lib/schedule.js";
|
|
2
4
|
import { compile, functionCompiler, rewriteActions, runtimeExpressions, splitStatements } from "./compile.js";
|
|
3
5
|
import { expressionKey, precompiled } from "./precompiled.js";
|
|
4
|
-
import {
|
|
6
|
+
import { batch, Computed, computed, effect, flush, onSettled, Signal, signal, untracked } from "./reactive.js";
|
|
7
|
+
import { createRuntime, parseAttr } from "./runtime.js";
|
|
5
8
|
import { createStore } from "./state.js";
|
|
6
|
-
import { expand, isPlain, toPredicate } from "../lib/objects.js";
|
|
7
|
-
import { camel, kebab, pascal, recase, snake } from "../lib/casing.js";
|
|
8
|
-
import { debounce, delay, throttle, toMs, withTiming, withViewTransition } from "../lib/schedule.js";
|
|
9
|
-
import { createRuntime as createRuntime2 } from "./runtime.js";
|
|
10
9
|
import { functionCompiler as functionCompiler2, runtimeExpressions as runtimeExpressions2 } from "./compile.js";
|
|
11
|
-
|
|
10
|
+
import { createRuntime as createRuntime2 } from "./runtime.js";
|
|
11
|
+
const createSigmx = (options = {}) => createRuntime2({
|
|
12
|
+
...options,
|
|
13
|
+
expressions: options.expressions ?? runtimeExpressions2(options.compile ?? functionCompiler2)
|
|
14
|
+
});
|
|
12
15
|
const attribute = (p) => ({ type: "attribute", ...p });
|
|
13
16
|
const action = (p) => ({ type: "action", ...p });
|
|
14
17
|
const handler = (p) => ({ type: "handler", ...p });
|
package/dist/kernel/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/kernel/index.ts"],
|
|
4
|
-
"sourcesContent": ["export {
|
|
5
|
-
"mappings": "AAAA,SAAS,
|
|
6
|
-
"names": ["
|
|
4
|
+
"sourcesContent": ["export { camel, kebab, pascal, recase, snake } from '../lib/casing.js';\nexport type { Filter } from '../lib/objects.js';\nexport { expand, isPlain, toPredicate } from '../lib/objects.js';\nexport { debounce, delay, throttle, toMs, withTiming, withViewTransition } from '../lib/schedule.js';\nexport type { Compiler } from './compile.js';\nexport { compile, functionCompiler, rewriteActions, runtimeExpressions, splitStatements } from './compile.js';\nexport type * from './contracts.js';\nexport type { ExpressionTable } from './precompiled.js';\nexport { expressionKey, precompiled } from './precompiled.js';\nexport { batch, Computed, computed, effect, flush, onSettled, Signal, signal, untracked } from './reactive.js';\nexport { createRuntime, parseAttr } from './runtime.js';\nexport type { Patch, Store } from './state.js';\nexport { createStore } from './state.js';\n\nimport { functionCompiler, runtimeExpressions } from './compile.js';\nimport type { ActionPlugin, AttributePlugin, HandlerPlugin, Sigmx, SigmxOptions } from './contracts.js';\nimport { createRuntime } from './runtime.js';\n\n/** Create an instance. Expressions compile at runtime unless you pass `expressions` (see `precompiled`). */\nexport const createSigmx = (options: SigmxOptions = {}): Sigmx =>\n createRuntime({\n ...options,\n expressions: options.expressions ?? runtimeExpressions(options.compile ?? functionCompiler),\n });\n\nexport const attribute = (p: Omit<AttributePlugin, 'type'>): AttributePlugin => ({ type: 'attribute', ...p });\nexport const action = (p: Omit<ActionPlugin, 'type'>): ActionPlugin => ({ type: 'action', ...p });\nexport const handler = (p: Omit<HandlerPlugin, 'type'>): HandlerPlugin => ({ type: 'handler', ...p });\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,OAAO,OAAO,QAAQ,QAAQ,aAAa;AAEpD,SAAS,QAAQ,SAAS,mBAAmB;AAC7C,SAAS,UAAU,OAAO,UAAU,MAAM,YAAY,0BAA0B;AAEhF,SAAS,SAAS,kBAAkB,gBAAgB,oBAAoB,uBAAuB;AAG/F,SAAS,eAAe,mBAAmB;AAC3C,SAAS,OAAO,UAAU,UAAU,QAAQ,OAAO,WAAW,QAAQ,QAAQ,iBAAiB;AAC/F,SAAS,eAAe,iBAAiB;AAEzC,SAAS,mBAAmB;AAE5B,SAAS,oBAAAA,mBAAkB,sBAAAC,2BAA0B;AAErD,SAAS,iBAAAC,sBAAqB;AAGvB,MAAM,cAAc,CAAC,UAAwB,CAAC,MACnDA,eAAc;AAAA,EACZ,GAAG;AAAA,EACH,aAAa,QAAQ,eAAeD,oBAAmB,QAAQ,WAAWD,iBAAgB;AAC5F,CAAC;AAEI,MAAM,YAAY,CAAC,OAAuD,EAAE,MAAM,aAAa,GAAG,EAAE;AACpG,MAAM,SAAS,CAAC,OAAiD,EAAE,MAAM,UAAU,GAAG,EAAE;AACxF,MAAM,UAAU,CAAC,OAAmD,EAAE,MAAM,WAAW,GAAG,EAAE;",
|
|
6
|
+
"names": ["functionCompiler", "runtimeExpressions", "createRuntime"]
|
|
7
7
|
}
|
|
@@ -4,14 +4,12 @@
|
|
|
4
4
|
* `$` alone, `$[...]` alone, and `obj.$prop` alone.
|
|
5
5
|
*/
|
|
6
6
|
export declare const rewriteSignals: (src: string) => string;
|
|
7
|
-
/** The strict-mode function body for one expression: same semantics as the runtime compiler. */
|
|
8
7
|
export declare const compileBody: (src: string, returns: boolean) => string;
|
|
9
8
|
export type Extracted = {
|
|
10
9
|
src: string;
|
|
11
10
|
params: string[];
|
|
12
11
|
returns: boolean;
|
|
13
12
|
};
|
|
14
|
-
/** JavaScript source for a module exporting `table`, from a list of extracted expressions. */
|
|
15
13
|
export declare const generateTable: (items: Extracted[]) => string;
|
|
16
14
|
export type PluginMeta = {
|
|
17
15
|
name: string;
|
|
@@ -32,7 +32,7 @@ const rewriteSignals = (src) => {
|
|
|
32
32
|
else if (src[j] === "}") depth--;
|
|
33
33
|
if (depth) j++;
|
|
34
34
|
}
|
|
35
|
-
out +=
|
|
35
|
+
out += `\${${rewriteSignals(src.slice(i + 2, j))}}`;
|
|
36
36
|
i = j + 1;
|
|
37
37
|
} else out += src[i++];
|
|
38
38
|
}
|
|
@@ -47,7 +47,7 @@ const rewriteSignals = (src) => {
|
|
|
47
47
|
} else if (c === "$" && next !== void 0 && ident.test(next) && next !== "$" && prevCode() !== "." && !ident.test(out[out.length - 1] ?? "")) {
|
|
48
48
|
let j = i + 1;
|
|
49
49
|
while (j < n && ident.test(src[j])) j++;
|
|
50
|
-
out +=
|
|
50
|
+
out += `$.${src.slice(i + 1, j)}`;
|
|
51
51
|
i = j;
|
|
52
52
|
} else {
|
|
53
53
|
out += c;
|
|
@@ -61,7 +61,7 @@ const compileBody = (src, returns) => {
|
|
|
61
61
|
if (!returns) return code;
|
|
62
62
|
const parts = splitStatements(code);
|
|
63
63
|
const last = parts.pop() ?? "";
|
|
64
|
-
return `${parts.length ? parts.join(";")
|
|
64
|
+
return `${parts.length ? `${parts.join(";")};` : ""}return (${last}
|
|
65
65
|
)`;
|
|
66
66
|
};
|
|
67
67
|
const generateTable = (items) => {
|
|
@@ -85,7 +85,14 @@ ${lines.join("\n")}
|
|
|
85
85
|
}
|
|
86
86
|
`;
|
|
87
87
|
};
|
|
88
|
-
const entities = {
|
|
88
|
+
const entities = {
|
|
89
|
+
""": '"',
|
|
90
|
+
"'": "'",
|
|
91
|
+
"'": "'",
|
|
92
|
+
"<": "<",
|
|
93
|
+
">": ">",
|
|
94
|
+
"&": "&"
|
|
95
|
+
};
|
|
89
96
|
const decode = (s) => s.replace(/&(quot|#39|apos|lt|gt|amp);/g, (m) => entities[m]);
|
|
90
97
|
const extractExpressions = (source, plugins, prefixes = ["data-"]) => {
|
|
91
98
|
const byName = new Map(plugins.map((p) => [p.name, p]));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/kernel/precompile.ts"],
|
|
4
|
-
"sourcesContent": ["// Build-time expression compiler. Not for the browser: import it from a Vite/Astro plugin.\nimport { rewriteActions, splitStatements } from './compile.js'
|
|
5
|
-
"mappings": "AACA,SAAS,gBAAgB,uBAAuB;AAChD,SAAS,qBAAqB;AAE9B,MAAM,QAAQ;AAOP,MAAM,iBAAiB,CAAC,QAAwB;AACrD,MAAI,MAAM;AACV,MAAI,IAAI;AACR,QAAM,IAAI,IAAI;AACd,QAAM,WAAW,MAAM;AACrB,aAAS,IAAI,IAAI,SAAS,GAAG,KAAK,GAAG,IAAK,KAAI,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,EAAG,QAAO,IAAI,CAAC;AAC9E,WAAO;AAAA,EACT;AACA,SAAO,IAAI,GAAG;AACZ,UAAM,IAAI,IAAI,CAAC;AACf,UAAM,OAAO,IAAI,IAAI,CAAC;AACtB,QAAI,MAAM,OAAO,MAAM,KAAK;AAC1B,UAAI,IAAI,IAAI;AACZ,aAAO,IAAI,KAAK,IAAI,CAAC,MAAM,EAAG,MAAK,IAAI,CAAC,MAAM,OAAO,IAAI;AACzD,aAAO,IAAI,MAAM,GAAG,IAAI,CAAC;AACzB,UAAI,IAAI;AAAA,IACV,WAAW,MAAM,KAAK;AACpB,aAAO;AACP;AACA,aAAO,IAAI,KAAK,IAAI,CAAC,MAAM,KAAK;AAC9B,YAAI,IAAI,CAAC,MAAM,MAAM;AACnB,iBAAO,IAAI,MAAM,GAAG,IAAI,CAAC;AACzB,eAAK;AAAA,QACP,WAAW,IAAI,CAAC,MAAM,OAAO,IAAI,IAAI,CAAC,MAAM,KAAK;AAC/C,cAAI,QAAQ;AACZ,cAAI,IAAI,IAAI;AACZ,iBAAO,IAAI,KAAK,OAAO;AACrB,gBAAI,IAAI,CAAC,MAAM,IAAK;AAAA,qBACX,IAAI,CAAC,MAAM,IAAK;AACzB,gBAAI,MAAO;AAAA,UACb;AACA,iBAAO,
|
|
4
|
+
"sourcesContent": ["// Build-time expression compiler. Not for the browser: import it from a Vite/Astro plugin.\nimport { rewriteActions, splitStatements } from './compile.js';\nimport { expressionKey } from './precompiled.js';\n\nconst ident = /[A-Za-z0-9_$]/;\n\n/**\n * Rewrite `$name` and `$a.b` into `$.name` / `$.a.b` so the expression runs in strict mode without\n * `with`. Skips strings and comments, recurses into template-literal interpolations, and leaves\n * `$` alone, `$[...]` alone, and `obj.$prop` alone.\n */\nexport const rewriteSignals = (src: string): string => {\n let out = '';\n let i = 0;\n const n = src.length;\n const prevCode = () => {\n for (let j = out.length - 1; j >= 0; j--) if (!/\\s/.test(out[j])) return out[j];\n return '';\n };\n while (i < n) {\n const c = src[i];\n const next = src[i + 1];\n if (c === '\"' || c === \"'\") {\n let j = i + 1;\n while (j < n && src[j] !== c) j += src[j] === '\\\\' ? 2 : 1;\n out += src.slice(i, j + 1);\n i = j + 1;\n } else if (c === '`') {\n out += c;\n i++;\n while (i < n && src[i] !== '`') {\n if (src[i] === '\\\\') {\n out += src.slice(i, i + 2);\n i += 2;\n } else if (src[i] === '$' && src[i + 1] === '{') {\n let depth = 1;\n let j = i + 2;\n while (j < n && depth) {\n if (src[j] === '{') depth++;\n else if (src[j] === '}') depth--;\n if (depth) j++;\n }\n out += `\\${${rewriteSignals(src.slice(i + 2, j))}}`;\n i = j + 1;\n } else out += src[i++];\n }\n out += '`';\n i++;\n } else if (c === '/' && next === '/') {\n const j = src.indexOf('\\n', i);\n i = j < 0 ? n : j;\n } else if (c === '/' && next === '*') {\n const j = src.indexOf('*/', i + 2);\n i = j < 0 ? n : j + 2;\n } else if (\n c === '$' &&\n next !== undefined &&\n ident.test(next) &&\n next !== '$' &&\n prevCode() !== '.' &&\n !ident.test(out[out.length - 1] ?? '')\n ) {\n let j = i + 1;\n while (j < n && ident.test(src[j])) j++;\n out += `$.${src.slice(i + 1, j)}`;\n i = j;\n } else {\n out += c;\n i++;\n }\n }\n return out;\n};\n\nexport const compileBody = (src: string, returns: boolean): string => {\n const code = rewriteSignals(rewriteActions(src.trim()));\n if (!returns) return code;\n const parts = splitStatements(code);\n const last = parts.pop() ?? '';\n return `${parts.length ? `${parts.join(';')};` : ''}return (${last}\\n)`;\n};\n\nexport type Extracted = { src: string; params: string[]; returns: boolean };\n\nexport const generateTable = (items: Extracted[]): string => {\n const seen = new Set<string>();\n const lines: string[] = [];\n for (const { src, params, returns } of items) {\n const key = expressionKey(src, params, returns);\n if (seen.has(key)) continue;\n seen.add(key);\n let body: string;\n try {\n body = compileBody(src, returns);\n Function('$', '__a', ...params, body); // syntax check at build time\n } catch {\n continue; // leave it to the runtime fallback (or fail there)\n }\n lines.push(` ${JSON.stringify(key)}: function($, __a, ${params.join(', ')}) { ${body} },`);\n }\n return `export const table = {\\n${lines.join('\\n')}\\n}\\n`;\n};\n\nconst entities: Record<string, string> = {\n '"': '\"',\n ''': \"'\",\n ''': \"'\",\n '<': '<',\n '>': '>',\n '&': '&',\n};\nconst decode = (s: string) => s.replace(/&(quot|#39|apos|lt|gt|amp);/g, (m) => entities[m]);\n\nexport type PluginMeta = { name: string; returns?: boolean; args?: string[] };\n\n/**\n * Find directive attributes with literal values in template source. Values must be plain quoted\n * strings; anything interpolated at render time is left to the runtime fallback.\n */\nexport const extractExpressions = (\n source: string,\n plugins: PluginMeta[],\n prefixes: string[] = ['data-'],\n): Extracted[] => {\n const byName = new Map(plugins.map((p) => [p.name, p]));\n const out: Extracted[] = [];\n const re = /([a-z][\\w-]*(?::[^\\s=\"'<>]+)?(?:__[^\\s=\"'<>]+)*)=(?:\"([^\"]*)\"|'([^']*)')/g;\n for (const m of source.matchAll(re)) {\n const attr = m[1];\n const value = decode(m[2] ?? m[3] ?? '');\n const prefix = prefixes.find((p) => attr.startsWith(p));\n if (!prefix || !value.trim()) continue;\n const plugin = byName.get(attr.slice(prefix.length).split('__')[0].split(':')[0]);\n if (!plugin) continue;\n out.push({ src: value, params: ['el', 'evt', ...(plugin.args ?? [])], returns: plugin.returns ?? true });\n }\n return out;\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/kernel/precompiled.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Evaluator, ExpressionCompiler } from './contracts.js'
|
|
5
|
-
"mappings": "AAKO,MAAM,gBAAgB,CAAC,KAAa,QAAkB,
|
|
4
|
+
"sourcesContent": ["import type { Evaluator, ExpressionCompiler } from './contracts.js';\n\nexport type ExpressionTable = Record<string, (root: any, actions: any, el: any, evt: any, ...args: any[]) => any>;\n\n/** Key used by the build plugin and the lookup: returns flag, parameter names, trimmed source. */\nexport const expressionKey = (src: string, params: string[], returns: boolean): string =>\n `${+returns}|${params.join()}|${src.trim()}`;\n\n/**\n * Look expressions up in a table generated at build time (see `sigmx/precompile`). Precompiled functions\n * receive the root store proxy as `$` instead of a `with` scope. Pass a `fallback` (for example\n * `runtimeExpressions(functionCompiler)`) for markup assembled at runtime; omit it and the runtime\n * compiler is not bundled at all.\n */\nexport const precompiled =\n (table: ExpressionTable, fallback?: ExpressionCompiler, onMiss?: (src: string) => void): ExpressionCompiler =>\n (src, params, returns) => {\n const fn = table[expressionKey(src, params, returns)];\n if (fn) return ((store, actions, el, evt, ...args) => fn(store.$, actions, el, evt, ...args)) as Evaluator;\n onMiss?.(src);\n if (!fallback) throw new Error(`expression not precompiled: ${src}`);\n return fallback(src, params, returns);\n };\n"],
|
|
5
|
+
"mappings": "AAKO,MAAM,gBAAgB,CAAC,KAAa,QAAkB,YAC3D,GAAG,CAAC,OAAO,IAAI,OAAO,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC;AAQrC,MAAM,cACX,CAAC,OAAwB,UAA+B,WACxD,CAAC,KAAK,QAAQ,YAAY;AACxB,QAAM,KAAK,MAAM,cAAc,KAAK,QAAQ,OAAO,CAAC;AACpD,MAAI,GAAI,SAAQ,CAAC,OAAO,SAAS,IAAI,QAAQ,SAAS,GAAG,MAAM,GAAG,SAAS,IAAI,KAAK,GAAG,IAAI;AAC3F,WAAS,GAAG;AACZ,MAAI,CAAC,SAAU,OAAM,IAAI,MAAM,+BAA+B,GAAG,EAAE;AACnE,SAAO,SAAS,KAAK,QAAQ,OAAO;AACtC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -3,23 +3,22 @@ interface Tracker {
|
|
|
3
3
|
_invalidate(): void;
|
|
4
4
|
}
|
|
5
5
|
export declare class Signal<T> {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
_v: T;
|
|
7
|
+
_ver: number;
|
|
8
|
+
_subs: Set<Tracker>;
|
|
9
9
|
constructor(v: T);
|
|
10
10
|
get value(): T;
|
|
11
11
|
set value(x: T);
|
|
12
|
-
/** Read without subscribing. */
|
|
13
12
|
peek(): T;
|
|
14
13
|
/** Notify subscribers without replacing the value (after mutating an array or object in place). */
|
|
15
14
|
bump(): void;
|
|
16
15
|
}
|
|
17
16
|
export declare class Computed<T> extends Signal<T> implements Tracker {
|
|
18
17
|
_deps: Map<Signal<any>, number>;
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
_dirty: boolean;
|
|
19
|
+
_fn: () => T;
|
|
21
20
|
constructor(fn: () => T);
|
|
22
|
-
|
|
21
|
+
_refresh(): void;
|
|
23
22
|
get value(): T;
|
|
24
23
|
set value(_: T);
|
|
25
24
|
peek(): T;
|
|
@@ -32,11 +31,8 @@ export declare const computed: <T>(fn: () => T) => Computed<T>;
|
|
|
32
31
|
* effect are disposed when the parent re-runs. Returns a disposer.
|
|
33
32
|
*/
|
|
34
33
|
export declare const effect: (fn: () => void, onError?: (e: unknown) => void) => (() => void);
|
|
35
|
-
/** Coalesce many writes into one round of effect runs. */
|
|
36
34
|
export declare const batch: <R>(fn: () => R) => R;
|
|
37
|
-
/** Read signals inside `fn` without subscribing the current effect to them. */
|
|
38
35
|
export declare const untracked: <R>(fn: () => R) => R;
|
|
39
|
-
/** Called after each flush once every queued effect has run. */
|
|
40
36
|
export declare const onSettled: (fn: () => void) => (() => void);
|
|
41
37
|
export declare const flush: () => void;
|
|
42
38
|
export {};
|