sprae 3.0.1 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sprae",
3
3
  "description": "DOM microhydration.",
4
- "version": "3.0.1",
4
+ "version": "4.0.0",
5
5
  "main": "src/index.js",
6
6
  "module": "src/index.js",
7
7
  "type": "module",
@@ -23,9 +23,11 @@
23
23
  },
24
24
  "scripts": {
25
25
  "test": "node -r ./test/register.cjs test/test.js",
26
- "build": "esbuild --bundle ./src/index.js --outfile=sprae.js --format=esm && npm run min",
26
+ "build": "npm run build-esm && npm run build-iife && npm run min",
27
+ "build-esm": "esbuild --bundle ./src/index.js --outfile=sprae.js --format=esm",
28
+ "build-iife": "esbuild --bundle ./src/index.js --outfile=sprae.auto.js --format=iife",
27
29
  "watch": "esbuild --bundle ./src/index.js --outfile=sprae.js --format=esm --sourcemap --watch",
28
- "min": "terser sprae.js -o sprae.min.js --module -c passes=3 -m"
30
+ "min": "terser sprae.js -o sprae.min.js --module -c passes=3 -m && terser sprae.auto.js -o sprae.auto.min.js --module -c passes=3 -m"
29
31
  },
30
32
  "repository": {
31
33
  "type": "git",
package/r&d.md CHANGED
@@ -474,6 +474,7 @@
474
474
  * [ ] x.raf="abc" - run regularly?
475
475
  * [ ] x.watch-a-b-c - update by change of any of the deps
476
476
  * [ ] :x.always - update by _any_ dep change
477
+ * [ ] :class.active="active"
477
478
 
478
479
  ## [x] Writing props on elements (like ones in :each) -> nah, just use `:x="this.x=abc"`
479
480
 
@@ -526,3 +527,8 @@
526
527
 
527
528
  1. :use="ref-id"
528
529
  2. :
530
+
531
+ ## [x] Remove non-essential directives -> yep, less API friction
532
+ * :aria - can be defined via plain attributes
533
+ * :data - confusable with :scope, doesn't provide much value, can be used as `:data-x=""` etc
534
+ * :={} - what's the meaning? Can be replaced with multiple attributes, no? No: no easy way to spread attributes.
package/readme.md CHANGED
@@ -1,11 +1,35 @@
1
1
  # ∴ spræ [![tests](https://github.com/dy/sprae/actions/workflows/node.js.yml/badge.svg)](https://github.com/dy/sprae/actions/workflows/node.js.yml) [![size](https://img.shields.io/bundlephobia/minzip/sprae?label=size)](https://bundlephobia.com/result?p=sprae) [![npm](https://img.shields.io/npm/v/sprae?color=orange)](https://npmjs.org/sprae)
2
2
 
3
- > DOM microhydration with `:` attributes
3
+ > DOM microhydration with `:` attributes.
4
4
 
5
+ _Sprae_ is tiny progressive enhancement lib, a minimal essential alternative to [alpine](https://github.com/alpinejs/alpine), [petite-vue](https://github.com/vuejs/petite-vue) or [template-parts](https://github.com/github/template-parts) with improved ergonomics. It enables simple markup logic without external scripts. Perfect for small websites or prototypes.
5
6
 
6
- ## Usage
7
+ ## Install
7
8
 
8
- Sprae defines attributes starting with `:` as directives:
9
+ To autoinit on document, include [`sprae.auto.js`](./sprae.auto.js):
10
+
11
+ ```html
12
+ <!-- <script src="https://cdn.jsdelivr.net/npm/sprae/sprae.auto.js" defer></script> -->
13
+ <script src="./path/to/sprae.auto.js" defer></script>
14
+
15
+ <div :scope="{foo:'bar'}">
16
+ <span :text="foo"></span>
17
+ </div>
18
+ ```
19
+
20
+ To use as module, import [`sprae.js`](./sprae.js):
21
+
22
+ ```html
23
+ <script type="module">
24
+ // import sprae from 'https://cdn.jsdelivr.net/npm/sprae/sprae.js';
25
+ import sprae from './path/to/sprae.js';
26
+ sprae(el, {foo: 'bar'});
27
+ </script>
28
+ ```
29
+
30
+ ## Use
31
+
32
+ Sprae evaluates attributes starting with `:`:
9
33
 
10
34
  ```html
11
35
  <div id="container" :if="user">
@@ -20,30 +44,28 @@ Sprae defines attributes starting with `:` as directives:
20
44
  </script>
21
45
  ```
22
46
 
23
- * `sprae` initializes subtree with data and immediately evaporates `:` attrs.
24
- * `state` is object reflecting current values, changing any of its props rerenders subtree.
25
- * To batch-update multiple properties `sprae` can be run repeatedly as: `sprae(container, newValues)`
47
+ * `sprae` initializes container's subtree with data and immediately evaporates `:` attrs.
48
+ * `state` object reflects current values, changing any props rerenders subtree next tick.
26
49
 
27
- <!--
28
- <details>
29
- <summary><strong>Autoinit</strong></summary>
30
50
 
31
- sprae can be used without build step or JS, autoinitializing document:
51
+ ## Attributes
32
52
 
33
- ```html
34
- <script src="./sprae.js" defer init="{ count: 0 }"></script>
53
+ #### `:scope="data"`
35
54
 
36
- <span :text="count">
37
- <button :on="{ click: e => count++ }">inc</button>
38
- ```
55
+ Define or extend data scope for a subtree.
39
56
 
40
- * `:with` defines data for regions of the tree to autoinit sprae on.
41
- * `init` attribute tells sprae to automatically initialize document.
57
+ ```html
58
+ <!-- Inline data -->
59
+ <x :scope="{ foo: 'bar' }" :text="foo"></x>
42
60
 
43
- </details>
44
- -->
61
+ <!-- External data -->
62
+ <y :scope="data"></y>
45
63
 
46
- ## Attributes
64
+ <!-- Extend scope -->
65
+ <x :scope="{ foo: 'bar' }">
66
+ <y :scope="{ baz: 'qux' }" :text="foo + baz"></y>
67
+ </x>
68
+ ```
47
69
 
48
70
  #### `:if="condition"`, `:else`
49
71
 
@@ -90,17 +112,17 @@ Welcome, <span :text="user.name">Guest</span>.
90
112
 
91
113
  #### `:class="value"`
92
114
 
93
- Set class value from either string, array or object. Appends existing `class` attribute, if any.
115
+ Set class value from either string, array or object. Extends existing `class` attribute, if any.
94
116
 
95
117
  ```html
96
118
  <div :class="`foo ${bar}`"></div>
97
- <div :class="['foo', 'bar']"></div>
98
- <div :class="{foo: true, bar: false}"></div>
99
119
 
100
- <div class="a" :class="['b', 'c']"></div>
101
- <!--
102
- <div class="a b c"></div>
103
- -->
120
+ <!-- extend existing class -->
121
+ <div class="foo" :class="`bar`"></div>
122
+ <!-- <div class="foo bar"></div> -->
123
+
124
+ <!-- object with values -->
125
+ <div :class="{foo:true, bar: false}"></div>
104
126
  ```
105
127
 
106
128
  #### `:style="value"`
@@ -183,54 +205,10 @@ Add event listeners.
183
205
  * `.ctrl-<key>, .alt-<key>, .meta-<key>, .shift-<key>` – key combinations, eg. `.ctrl-alt-delete` or `.meta-x`.
184
206
  * `.*` – any other modifier has no effect, but allows binding multiple handlers to same event (like jQuery event classes).
185
207
 
186
- #### `:data="values"`
187
-
188
- Set [data-*](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/data-*) attributes. CamelCase is converted to dash-case.
189
-
190
- ```html
191
- <input :data="{foo: 1, barBaz: true}" />
192
- <!--
193
- <input data-foo="1" data-bar-baz="true" />
194
- -->
195
- ```
196
-
197
- #### `:aria="values"`
198
-
199
- Set [aria-role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) attributes. Boolean values are stringified.
200
-
201
- ```html
202
- <input role="combobox" :aria="{
203
- controls: 'joketypes',
204
- autocomplete: 'list',
205
- expanded: false,
206
- activeOption: 'item1',
207
- activedescendant: ''
208
- }" />
209
- <!--
210
- <input role="combobox" aria-controls="joketypes" aria-autocomplete="list" aria-expanded="false" aria-active-option="item1" aria-activedescendant="">
211
- -->
212
- ```
213
-
214
- #### `:with="data"`
215
-
216
- Define variables for a subtree fragment scope.
217
-
218
- ```html
219
- <!-- Inline data -->
220
- <x :with="{ foo: 'bar' }" :text="foo"></x>
221
-
222
- <!-- External data -->
223
- <y :with="data"></y>
224
-
225
- <!-- Transparency -->
226
- <x :with="{ foo: 'bar' }">
227
- <y :with="{ baz: 'qux' }" :text="foo + baz"></y>
228
- </x>
229
- ```
230
208
 
231
209
  #### `:ref="id"`
232
210
 
233
- Expose element to data scope with the `id`:
211
+ Expose element to current data scope with the `id`:
234
212
 
235
213
  ```html
236
214
  <!-- single item -->
@@ -254,28 +232,24 @@ Expose element to data scope with the `id`:
254
232
 
255
233
  ## Sandbox
256
234
 
257
- Expressions are sandboxed, ie. have no access to global or window.
258
-
235
+ Expressions are sandboxed, ie. have no access to global or window (since sprae can be run in server environment).
259
236
  Default sandbox provides: _Array_, _Object_, _Number_, _String_, _Boolean_, _Date_, _console_.
260
-
261
- Sandbox can be extended via `Object.assign(sprae.globals, { BigInt, window, document })` etc.
237
+ Sandbox can be extended as `Object.assign(sprae.globals, { BigInt, window, document })` etc.
262
238
 
263
239
  ## Examples
264
240
 
265
241
  * TODO MVC: [demo](https://dy.github.io/sprae/examples/todomvc), [code](https://github.com/dy/sprae/blob/main/examples/todomvc.html)
266
- * Waveplay: [demo](https://dy.github.io/waveplay), [code](https://github.com/dy/waveedit)
242
+ * Wavearea: [demo](https://dy.github.io/wavearea?src=//cdn.freesound.org/previews/586/586281_2332564-lq.mp3), [code](https://github.com/dy/wavearea)
267
243
 
268
244
  ## Justification
269
245
 
270
- _Sprae_ is lightweight essential alternative to [alpine](https://github.com/alpinejs/alpine), [petite-vue](https://github.com/vuejs/petite-vue), [templize](https://github.com/dy/templize) or JSX with better ergonomics.
271
-
272
246
  * [Template-parts](https://github.com/dy/template-parts) / [templize](https://github.com/dy/templize) is progressive, but is stuck with native HTML quirks ([parsing table](https://github.com/github/template-parts/issues/24), [svg attributes](https://github.com/github/template-parts/issues/25), [liquid syntax](https://shopify.github.io/liquid/tags/template/#raw) conflict etc). Also ergonomics of `attr="{{}}"` is inferior to `:attr=""` since it creates flash of uninitialized values.
273
247
  * [Alpine](https://github.com/alpinejs/alpine) / [vue](https://github.com/vuejs/petite-vue) / [lit](https://github.com/lit/lit/tree/main/packages/lit-html) escapes native HTML quirks, but the syntax is a bit scattered: `:attr`, `v-*`,`x-*`, `@evt`, `{{}}` can be expressed with single convention. Besides, functionality is too broad and can be reduced to essence: perfection is when there's nothing to take away, not add. Also they tend to [self-encapsulate](https://github.com/alpinejs/alpine/discussions/3223), making interop hard.
274
248
  * React/[preact](https://ghub.io/preact) does the job wiring up JS to HTML, but with an extreme of migrating HTML to JSX and enforcing SPA, which is not organic for HTML. Also it doesn't support reactive fields (needs render call).
275
249
 
276
- _Sprae_ takes convention of _templize directives_ (_alpine_/_vue_ attrs) and builds upon [_@preact/signals_](https://ghub.io/@preact/signals).
250
+ _Sprae_ takes convention of _templize directives_ (_alpine_/_vue_ attrs) and builds upon <del>[_@preact/signals_](https://ghub.io/@preact/signals)</del> simple reacti.
277
251
 
278
- * It doesn't break static html markup.
252
+ * It doesn't break or modify initial static html markup.
279
253
  * It falls back to element content if uninitialized.
280
254
  * It doesn't enforce SPA nor JSX.
281
255
  * It enables island hydration.
@@ -284,7 +258,6 @@ _Sprae_ takes convention of _templize directives_ (_alpine_/_vue_ attrs) and bui
284
258
  * Input data may contain [signals](https://ghub.io/@preact/signals) or [reactive values](https://ghub.io/sube).
285
259
  * Elements / data API is open and enable easy interop.
286
260
 
287
-
288
261
  It is reminiscent of [XSLT](https://www.w3schools.com/xml/xsl_intro.asp), considered a [buried treasure](https://github.com/bahrus/be-restated) by web-connoisseurs.
289
262
 
290
263