sprae 6.1.1 → 7.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,11 +1,19 @@
1
1
  {
2
2
  "name": "sprae",
3
3
  "description": "DOM microhydration.",
4
- "version": "6.1.1",
4
+ "version": "7.0.0",
5
5
  "main": "src/index.js",
6
6
  "module": "src/index.js",
7
7
  "type": "module",
8
+ "files": [
9
+ "sprae.auto.js",
10
+ "sprae.auto.min.js",
11
+ "sprae.js",
12
+ "sprae.min.js",
13
+ "src"
14
+ ],
8
15
  "dependencies": {
16
+ "@preact/signals-core": "^1.5.0",
9
17
  "swapdom": "^1.1.1"
10
18
  },
11
19
  "devDependencies": {
package/readme.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > DOM tree hydration with reactivity.
4
4
 
5
- _Sprae_ is progressive enhancement framework, a tiny 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[*](#justification--alternatives). It enables simple markup logic without external scripts. Perfect for small websites, prototypes or UI logic.
5
+ _Sprae_ is progressive enhancement framework, a tiny 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 enhanced ergonomics[*](#justification--alternatives). It enables simple markup logic without external scripts. Perfect for small websites, prototypes or UI logic.
6
6
 
7
7
  ## Use
8
8
 
@@ -12,9 +12,13 @@ To autoinit document, include [`sprae.auto.js`](./sprae.auto.js):
12
12
 
13
13
  ```html
14
14
  <!-- <script src="https://cdn.jsdelivr.net/npm/sprae/sprae.auto.js" defer></script> -->
15
- <script src="./path/to/sprae.auto.js" defer></script>
15
+ <script defer src="./path/to/sprae.auto.js"></script>
16
16
 
17
- <a :each="id in ['a','b','c']" :href="`#${id}`" :text="id"></a>
17
+ <ul>
18
+ <li :each="item in ['apple', 'bananas', 'citrus']"">
19
+ <a :href="`#${item}`" :text="item" />
20
+ </li>
21
+ </ul>
18
22
  ```
19
23
 
20
24
  ### Manual init
@@ -23,19 +27,21 @@ To init manually as module, import [`sprae.js`](./sprae.js):
23
27
 
24
28
  ```html
25
29
  <div id="container" :if="user">
26
- Logged in as <span :text="user.displayName">Guest.</span>
30
+ Logged in as <span :text="user.name">Guest.</span>
27
31
  </div>
28
32
 
29
33
  <script type="module">
30
34
  // import sprae from 'https://cdn.jsdelivr.net/npm/sprae/sprae.js';
31
35
  import sprae from './path/to/sprae.js';
32
36
 
33
- const state = sprae(container, { user: { displayName: 'Dmitry Ivanov' } });
34
- state.user.displayName = 'dy'; // updates DOM
37
+ const state = sprae(container, { user: { name: 'Dmitry Ivanov' } });
38
+ state.user.name = 'dy'; // updates DOM
35
39
  </script>
36
40
  ```
37
41
 
38
- Sprae evaluates `:`-attributes and evaporates them. Reactive `state` reflects current values, can be updated directly (batches multiple updates internally for efficiency).
42
+ Sprae evaluates `:`-attributes and evaporates them.<br/>
43
+ Sprae creates reactive state representing current values in rendered DOM.<br/>
44
+ It is based on [preact signals](https://github.com/preactjs/signals) and can take them as inputs.
39
45
 
40
46
  ## Attributes
41
47
 
@@ -79,14 +85,14 @@ Welcome, <span :text="user.name">Guest</span>.
79
85
 
80
86
  #### `:class="value"`
81
87
 
82
- Set class value from either string, array or object. Extends existing `class` attribute, if any.
88
+ Set class value from either a string, array or object.
83
89
 
84
90
  ```html
91
+ <!-- set from string -->
85
92
  <div :class="`foo ${bar}`"></div>
86
93
 
87
- <!-- extend existing class -->
94
+ <!-- extends existing class as "foo bar" -->
88
95
  <div class="foo" :class="`bar`"></div>
89
- <!-- <div class="foo bar"></div> -->
90
96
 
91
97
  <!-- object with values -->
92
98
  <div :class="{foo:true, bar: false}"></div>
@@ -94,11 +100,16 @@ Set class value from either string, array or object. Extends existing `class` at
94
100
 
95
101
  #### `:style="value"`
96
102
 
97
- Set style value from object or a string. Extends existing `style` attribute, if any.
103
+ Set style value from an object or a string. Extends existing `style` attribute, if any.
98
104
 
99
105
  ```html
100
- <div :style="foo: bar"></div>
106
+ <!-- from string -->
107
+ <div :style="`foo: ${bar}`"></div>
108
+
109
+ <!-- from object -->
101
110
  <div :style="{foo: 'bar'}"></div>
111
+
112
+ <!-- set CSS variable -->
102
113
  <div :style="{'--baz': qux}"></div>
103
114
  ```
104
115
 
@@ -107,9 +118,11 @@ Set style value from object or a string. Extends existing `style` attribute, if
107
118
  Set value of an input, textarea or select. Takes handle of `checked` and `selected` attributes.
108
119
 
109
120
  ```html
110
- <input :value="text" />
111
- <textarea :value="text" />
121
+ <!-- set from value -->
122
+ <input :value="value" />
123
+ <textarea :value="value" />
112
124
 
125
+ <!-- selects right option -->
113
126
  <select :value="selected">
114
127
  <option :each="i in 5" :value="i" :text="i"></option>
115
128
  </select>
@@ -132,15 +145,30 @@ Define or extend data scope for a subtree.
132
145
  </x>
133
146
  ```
134
147
 
135
- #### `:render="ref"`
148
+ #### `:<prop>="value?"`
136
149
 
137
- Include template as element content.
150
+ Set any attribute value or run an effect.
138
151
 
139
152
  ```html
140
- <template :ref="foo"><span :text="foo"></span></template>
153
+ <!-- Single property -->
154
+ <label :for="name" :text="name" />
141
155
 
142
- <div :render="foo" :with="{foo:'bar'}">...inserted here...</div>
143
- <div :render="foo" :with="{foo:'baz'}">...inserted here...</div>
156
+ <!-- Multiple properties -->
157
+ <input :id:name="name" />
158
+
159
+ <!-- Effect - returns undefined, triggers any time bar changes -->
160
+ <div :fx="void bar()" ></div>
161
+
162
+ <!-- Raw event listener (see events) -->
163
+ <div :onclick="e=>e.preventDefault()"></div>
164
+ ```
165
+
166
+ #### `:="props?"`
167
+
168
+ Spread multiple attibures.
169
+
170
+ ```html
171
+ <input :="{ id: name, name, type:'text', value }" />
144
172
  ```
145
173
 
146
174
  #### `:ref="id"`
@@ -160,30 +188,17 @@ Expose element to current data scope with the `id`:
160
188
  </ul>
161
189
  ```
162
190
 
163
- #### `:="props?"`
164
-
165
- Spread multiple attibures.
166
-
167
- ```html
168
- <input :="{ id: name, name, type:'text', value }" />
169
- ```
170
-
171
- #### `:<prop>="value?"`
191
+ #### `:render="ref"`
172
192
 
173
- Set any attribute value or run an effect.
193
+ Include template as element content.
174
194
 
175
195
  ```html
176
- <!-- Single property -->
177
- <label :for="name" :text="name" />
178
-
179
- <!-- Multiple properties -->
180
- <input :id:name="name" />
181
-
182
- <!-- Effect - returns undefined, triggers any time bar changes -->
183
- <div :fx="void bar()" ></div>
196
+ <!-- assign template element to foo variable -->
197
+ <template :ref="foo"><span :text="foo"></span></template>
184
198
 
185
- <!-- Raw event listener (see events) -->
186
- <div :onclick="e=>e.preventDefault()"></div>
199
+ <!-- rended template as content -->
200
+ <div :render="foo" :with="{foo:'bar'}">...inserted here...</div>
201
+ <div :render="foo" :with="{foo:'baz'}">...inserted here...</div>
187
202
  ```
188
203
 
189
204
 
@@ -191,7 +206,7 @@ Set any attribute value or run an effect.
191
206
 
192
207
  #### `@<event>="handle"`, `@<foo>@<bar>.<baz>="handle"`
193
208
 
194
- Attach event(s) listener with possible modifiers. `event` variable holds current event.
209
+ Attach event(s) listener with possible modifiers. `event` variable holds current event. Allows async handlers.
195
210
 
196
211
  ```html
197
212
  <!-- Single event -->
@@ -224,7 +239,7 @@ Expressions are sandboxed, ie. don't access global/window scope by default (sinc
224
239
  <!-- scrollY is undefined -->
225
240
  ```
226
241
 
227
- Default sandbox provides: _window_, _document_, _console_, _history_, _location_, _Array_, _Object_, _Number_, _String_, _Boolean_, _Date_, _Set_, _Map_.
242
+ Default sandbox provides: _window_, _document_, _console_, _history_, _location_, _Date_, _Set_, _Map_.
228
243
 
229
244
  Sandbox can be extended as `Object.assign(sprae.globals, { BigInt })`.
230
245
 
@@ -237,13 +252,45 @@ To avoid _flash of unstyled content_, you can hide sprae attribute or add a cust
237
252
  <style>[:each],[:hidden] {visibility: hidden}</style>
238
253
  ```
239
254
 
255
+ ## Benchmark
256
+
257
+ Done via [js-framework-benchmark](https://github.com/krausest/js-framework-benchmark).
258
+
259
+ ```sh
260
+ # prerequisite
261
+ npm ci
262
+ npm run install-server
263
+ npm start
264
+
265
+ # build
266
+ cd frameworks/keyed/sprae
267
+ npm ci
268
+ npm run build-prod
269
+
270
+ # bench
271
+ cd ../../..
272
+ cd webdriver-ts
273
+ npm ci
274
+ npm run compile
275
+ npm run bench keyed/sprae
276
+
277
+ # show results
278
+ cd ..
279
+ cd webdriver-ts-results
280
+ npm ci
281
+ cd ..
282
+ cd webdriver-ts
283
+ npm run results
284
+ ```
285
+
240
286
  ## Examples
241
287
 
242
288
  * TODO MVC: [demo](https://dy.github.io/sprae/examples/todomvc), [code](https://github.com/dy/sprae/blob/main/examples/todomvc.html)
243
289
  * Wavearea: [demo](https://dy.github.io/wavearea?src=//cdn.freesound.org/previews/586/586281_2332564-lq.mp3), [code](https://github.com/dy/wavearea)
244
290
  * Prostogreen [demo](http://web-being.org/prostogreen/), [code](https://github.com/web-being/prostogreen/)
245
291
 
246
- ## Justification & alternatives
292
+
293
+ ## Justification
247
294
 
248
295
  * [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. Also it's just nice to keep `{{}}` generic, regardless of markup, and attributes as part of markup.
249
296
  * [Alpine](https://github.com/alpinejs/alpine) / [vue](https://github.com/vuejs/petite-vue) / [lit](https://github.com/lit/lit/tree/main/packages/lit-html) escape native HTML quirks, but the syntax space (`:attr`, `v-*`,`x-*`, `l-*` `@evt`, `{{}}`) is too broad, as well as functionality. Perfection is when there's nothing to take away, not add (c). Also they tend to [self-encapsulate](https://github.com/alpinejs/alpine/discussions/3223) making interop hard, invent own tooling or complex reactivity.
@@ -264,8 +311,8 @@ It is reminiscent of [XSLT](https://www.w3schools.com/xml/xsl_intro.asp), consid
264
311
  ## Alternatives
265
312
 
266
313
  * [Alpine](https://github.com/alpinejs/alpine)
267
- * [Lucia](https://github.com/aidenybai/lucia)
314
+ * ~~[Lucia](https://github.com/aidenybai/lucia)~~ deprecated
268
315
  * [Petite-vue](https://github.com/vuejs/petite-vue)
269
- * [Reken](https://github.com/hbroek/reken)
316
+ * [nuejs](https://github.com/nuejs/nuejs)
270
317
 
271
318
  <p align="center"><a href="https://github.com/krsnzd/license/">🕉</a></p>