sprae 5.2.0 → 5.3.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 +1 -1
- package/r&d.md +13 -1
- package/readme.md +18 -25
- package/sprae.auto.js +7 -7
- package/sprae.auto.min.js +1 -1
- package/sprae.js +7 -7
- package/sprae.min.js +1 -1
- package/src/directives.js +10 -9
- package/test/dom.js +10 -4
- package/todo.md +2 -1
package/package.json
CHANGED
package/r&d.md
CHANGED
|
@@ -225,13 +225,14 @@
|
|
|
225
225
|
- slows down domdiff
|
|
226
226
|
- can be solved as `<x :if="xxx" :="xxx && (...)'">` automatically
|
|
227
227
|
|
|
228
|
-
## [
|
|
228
|
+
## [ ] :onmount/onunmount? ->
|
|
229
229
|
|
|
230
230
|
+ useful for :if, :each
|
|
231
231
|
+ useful to dispose listeners via :onunmount (opposed to hidden symbols)
|
|
232
232
|
- doesn't really solve disposal: if element is attached again, it would need to reattach removed listeners
|
|
233
233
|
-> can be dolved via teardowns returned from updators
|
|
234
234
|
-> nah, event listeners don't need collection, just make sure no refs to element remain
|
|
235
|
+
+ can be useful for lazy-loadings
|
|
235
236
|
|
|
236
237
|
## [x] :focus="direct code", :evt="direct code" -> nah, too messy.
|
|
237
238
|
|
|
@@ -374,7 +375,18 @@
|
|
|
374
375
|
- still need that syntax for filters, maps etc
|
|
375
376
|
+ can be made async by default
|
|
376
377
|
- illicit `event` object
|
|
378
|
+
+ we don't seem to ever need that event argument, many cases are covered by `.prevent` or `.stop`
|
|
379
|
+
~+ generally `e=>` seem to conflict logically with modifiers sense
|
|
380
|
+
+ `e=>` brings syntax burden - we may not ever need functions
|
|
381
|
+
+ less problem detecting `const/let` in code
|
|
377
382
|
- conflicts with regular attrs logic: the code is immediately invoked and can assign a function.
|
|
383
|
+
- `:oninput="e => (handleCaret(e), updateTimecodes())"`
|
|
384
|
+
- `:onbeforeinput="handleBeforeInput"`
|
|
385
|
+
- `:ondragenter..ondragleave:ondragenter..ondrop="e=>(this.classList.add('w-dragover'),e=>this.classList.remove('w-dragover'))"`
|
|
386
|
+
- `:ondrop="e=>console.log(e.dataTransfer.types)||e.preventDefault()"`
|
|
387
|
+
- `:onfocus="e => (e.relatedTarget ? e.relatedTarget.focus() : e.target.blur())"`
|
|
388
|
+
- `:onpopstate.window="e => goto(e.state)"`
|
|
389
|
+
- `:onclick.toggle="play"`
|
|
378
390
|
|
|
379
391
|
## [x] Should getters convert to computed? -> yes, that's relatively cheap and useful
|
|
380
392
|
|
package/readme.md
CHANGED
|
@@ -2,32 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
> DOM microhydration with `:` attributes.
|
|
4
4
|
|
|
5
|
-
_Sprae_ is tiny progressive enhancement
|
|
5
|
+
_Sprae_ is tiny progressive enhancement framework, a minimal essential alternative to [alpine](https://github.com/alpinejs/alpine)/[lucia](https://github.com/aidenybai/lucia), [petite-vue](https://github.com/vuejs/petite-vue) or [template-parts](https://github.com/github/template-parts) with improved ergonomics[*](#justification). It enables simple markup logic without external scripts. Perfect for small websites, prototypes or UI logic.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Use
|
|
8
|
+
|
|
9
|
+
### Autoinit
|
|
8
10
|
|
|
9
|
-
To autoinit
|
|
11
|
+
To autoinit document, include [`sprae.auto.js`](./sprae.auto.js):
|
|
10
12
|
|
|
11
13
|
```html
|
|
12
14
|
<!-- <script src="https://cdn.jsdelivr.net/npm/sprae/sprae.auto.js" defer></script> -->
|
|
13
15
|
<script src="./path/to/sprae.auto.js" defer></script>
|
|
14
16
|
|
|
15
|
-
<a :each="id in ['a','b','c']" :href="`#${id}`"></a>
|
|
17
|
+
<a :each="id in ['a','b','c']" :href="`#${id}`" :text="id"></a>
|
|
16
18
|
```
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
### Manual init
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
<script type="module">
|
|
22
|
-
// import sprae from 'https://cdn.jsdelivr.net/npm/sprae/sprae.js';
|
|
23
|
-
import sprae from './path/to/sprae.js';
|
|
24
|
-
sprae(el, {foo: 'bar'});
|
|
25
|
-
</script>
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Use
|
|
29
|
-
|
|
30
|
-
Sprae evaluates attributes starting with `:`:
|
|
22
|
+
To use as module, import [`sprae.js`](./sprae.js):
|
|
31
23
|
|
|
32
24
|
```html
|
|
33
25
|
<div id="container" :if="user">
|
|
@@ -35,15 +27,15 @@ Sprae evaluates attributes starting with `:`:
|
|
|
35
27
|
</div>
|
|
36
28
|
|
|
37
29
|
<script type="module">
|
|
38
|
-
import sprae from 'sprae';
|
|
30
|
+
// import sprae from 'https://cdn.jsdelivr.net/npm/sprae/sprae.js';
|
|
31
|
+
import sprae from './path/to/sprae.js';
|
|
39
32
|
|
|
40
33
|
const state = sprae(container, { user: { displayName: 'Dmitry Ivanov' } });
|
|
41
|
-
state.user.displayName = 'dy'; //
|
|
34
|
+
state.user.displayName = 'dy'; // updates DOM
|
|
42
35
|
</script>
|
|
43
36
|
```
|
|
44
37
|
|
|
45
|
-
|
|
46
|
-
* `state` object reflects current values, changing any props rerenders subtree next tick.
|
|
38
|
+
Sprae evaluates `:`-attributes and evaporates them. Reactive `state` reflects current values, can be updated directly.
|
|
47
39
|
|
|
48
40
|
|
|
49
41
|
## Attributes
|
|
@@ -68,7 +60,7 @@ Multiply element. `index` value starts from 1.
|
|
|
68
60
|
<!-- Cases -->
|
|
69
61
|
<li :each="item, idx in list" />
|
|
70
62
|
<li :each="val, key in obj" />
|
|
71
|
-
<li :each="
|
|
63
|
+
<li :each="idx0, idx in number" />
|
|
72
64
|
|
|
73
65
|
<!-- Loop by condition -->
|
|
74
66
|
<li :if="items" :each="item in items" :text="item" />
|
|
@@ -253,13 +245,13 @@ To avoid _flash of unstyled content_, you can hide sprae attribute or add a cust
|
|
|
253
245
|
* Wavearea: [demo](https://dy.github.io/wavearea?src=//cdn.freesound.org/previews/586/586281_2332564-lq.mp3), [code](https://github.com/dy/wavearea)
|
|
254
246
|
* Prostogreen [demo](http://web-being.org/prostogreen/), [code](https://github.com/web-being/prostogreen/)
|
|
255
247
|
|
|
256
|
-
## Justification
|
|
248
|
+
## Justification & alternatives
|
|
257
249
|
|
|
258
|
-
* [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), [
|
|
259
|
-
* [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.
|
|
250
|
+
* [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.
|
|
251
|
+
* [Alpine](https://github.com/alpinejs/alpine) / [vue](https://github.com/vuejs/petite-vue) / [lit](https://github.com/lit/lit/tree/main/packages/lit-html) / [lucia](https://github.com/aidenybai/lucia) escapes native HTML quirks, but the syntax is a bit scattered: `:attr`, `v-*`,`x-*`, `l-*` `@evt`, `{{}}` can be expressed with single convention. `{{}}` also conflicts with template-parts and liquid/django. 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.
|
|
260
252
|
* 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).
|
|
261
253
|
|
|
262
|
-
_Sprae_ takes
|
|
254
|
+
_Sprae_ takes idea of _templize directives_/_alpine_/_vue_ attrs and builds upon <del>[_@preact/signals_](https://ghub.io/@preact/signals)</del> simple reactive state.
|
|
263
255
|
|
|
264
256
|
* It doesn't break or modify static html markup.
|
|
265
257
|
* It falls back to element content if uninitialized.
|
|
@@ -268,6 +260,7 @@ _Sprae_ takes convention of _templize directives_ (_alpine_/_vue_ attrs) and bui
|
|
|
268
260
|
* It reserves minimal syntax space as `:` convention (keeping tree neatly decorated, not scattered).
|
|
269
261
|
* Expressions are naturally reactive and incur minimal updates.
|
|
270
262
|
* Elements / data API is open and enable easy interop.
|
|
263
|
+
* It's just nice separation: attributes belong to client and template fields to server.
|
|
271
264
|
|
|
272
265
|
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.
|
|
273
266
|
|
package/sprae.auto.js
CHANGED
|
@@ -223,12 +223,6 @@
|
|
|
223
223
|
}
|
|
224
224
|
};
|
|
225
225
|
};
|
|
226
|
-
primary["with"] = (el, expr, rootState) => {
|
|
227
|
-
let evaluate = parseExpr(el, expr, ":with");
|
|
228
|
-
const localState = evaluate(rootState);
|
|
229
|
-
let state2 = state(localState, rootState);
|
|
230
|
-
sprae(el, state2);
|
|
231
|
-
};
|
|
232
226
|
var _each = Symbol(":each");
|
|
233
227
|
primary["each"] = (tpl, expr) => {
|
|
234
228
|
let each = parseForExpression(expr);
|
|
@@ -249,7 +243,7 @@
|
|
|
249
243
|
if (!list)
|
|
250
244
|
list = [];
|
|
251
245
|
else if (typeof list === "number")
|
|
252
|
-
list = Array.from({ length: list }, (_, i) => [i
|
|
246
|
+
list = Array.from({ length: list }, (_, i) => [i + 1, i]);
|
|
253
247
|
else if (Array.isArray(list))
|
|
254
248
|
list = list.map((item, i) => [i + 1, item]);
|
|
255
249
|
else if (typeof list === "object")
|
|
@@ -279,6 +273,12 @@
|
|
|
279
273
|
}
|
|
280
274
|
};
|
|
281
275
|
};
|
|
276
|
+
primary["with"] = (el, expr, rootState) => {
|
|
277
|
+
let evaluate = parseExpr(el, expr, ":with");
|
|
278
|
+
const localState = evaluate(rootState);
|
|
279
|
+
let state2 = state(localState, rootState);
|
|
280
|
+
sprae(el, state2);
|
|
281
|
+
};
|
|
282
282
|
primary["ref"] = (el, expr, state2) => {
|
|
283
283
|
state2[expr] = el;
|
|
284
284
|
};
|
package/sprae.auto.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{var e,t,r=Promise.prototype.then.bind(Promise.resolve()),n=new WeakMap,l=class extends Map{#e=new FinalizationRegistry((e=>super.delete(e)));get size(){return[...this].length}constructor(e=[]){super();for(const[t,r]of e)this.set(t,r)}get(e){return super.get(e)?.deref()}set(e,t){let r=super.get(e);return r&&this.#e.unregister(r),r=(e=>n.get(e)||(e=>{const t=new WeakRef(e);return n.set(e,t),t})(e))(t),this.#e.register(t,e,r),super.set(e,r)}},s=new Set,i=new WeakMap,o=new WeakMap,a=new WeakMap,u=Symbol("parent"),c={Array:Array,Object:Object,Number:Number,String:String,Boolean:Boolean,Date:Date,console:console,window:window,document:document,history:history,location:location},f={has:()=>!0,get(t,r){if("symbol"==typeof r)return t[r];if(!(r in t))return t[u]?.[r];if(r in Object.prototype||Array.isArray(t)&&r in Array.prototype&&"length"!==r)return t[r];let n=t[r];if(e){let n=i.get(t);n||i.set(t,n={}),n[r]?n[r].includes(e)||n[r].push(e):n[r]=[e]}if(n&&n.constructor===Object||Array.isArray(n)){let e=o.get(n);return e||o.set(n,e=new Proxy(n,f)),e}return n},set(e,t,r){if(!(t in e)&&e[u]&&t in e[u])return e[u][t]=r;if(!Array.isArray(e)&&Object.is(e[t],r))return!0;e[t]=r;let n=i.get(e)?.[t];if(n)for(let e of n)s.add(e);return h(),!0},deleteProperty:(e,t)=>(e[t]=void 0,delete e[t],!0)},p=(e,t)=>{if(o.has(e))return o.get(e);if(a.has(e))return e;let r=new Proxy(e,f);o.set(e,r),a.set(r,e);let n=Object.getOwnPropertyDescriptors(e);for(let t in n){let l=n[t];l.get&&l.get&&(l.get=l.get.bind(r),Object.defineProperty(e,t,l))}return e[u]=t?p(t):c,r},y=t=>{const r=()=>{let n=e;e=r,t(),e=n};return r(),r},h=()=>{t||(t=!0,r((()=>{for(let e of s)e.call();s.clear(),t=!1})))},g={},d={};g.if=(e,t)=>{let r=document.createTextNode(""),n=[j(e,t,":if")],l=[e],s=e;for(;(s=e.nextElementSibling)&&s.hasAttribute(":else");)s.removeAttribute(":else"),(t=s.getAttribute(":if"))?(s.removeAttribute(":if"),s.remove(),l.push(s),n.push(j(e,t,":else :if"))):(s.remove(),l.push(s),n.push((()=>1)));return e.replaceWith(s=r),e=>{let t=n.findIndex((t=>t(e)));l[t]!=s&&((s[m]||s).replaceWith(s=l[t]||r),O(s,e))}}
|
|
1
|
+
(()=>{var e,t,r=Promise.prototype.then.bind(Promise.resolve()),n=new WeakMap,l=class extends Map{#e=new FinalizationRegistry((e=>super.delete(e)));get size(){return[...this].length}constructor(e=[]){super();for(const[t,r]of e)this.set(t,r)}get(e){return super.get(e)?.deref()}set(e,t){let r=super.get(e);return r&&this.#e.unregister(r),r=(e=>n.get(e)||(e=>{const t=new WeakRef(e);return n.set(e,t),t})(e))(t),this.#e.register(t,e,r),super.set(e,r)}},s=new Set,i=new WeakMap,o=new WeakMap,a=new WeakMap,u=Symbol("parent"),c={Array:Array,Object:Object,Number:Number,String:String,Boolean:Boolean,Date:Date,console:console,window:window,document:document,history:history,location:location},f={has:()=>!0,get(t,r){if("symbol"==typeof r)return t[r];if(!(r in t))return t[u]?.[r];if(r in Object.prototype||Array.isArray(t)&&r in Array.prototype&&"length"!==r)return t[r];let n=t[r];if(e){let n=i.get(t);n||i.set(t,n={}),n[r]?n[r].includes(e)||n[r].push(e):n[r]=[e]}if(n&&n.constructor===Object||Array.isArray(n)){let e=o.get(n);return e||o.set(n,e=new Proxy(n,f)),e}return n},set(e,t,r){if(!(t in e)&&e[u]&&t in e[u])return e[u][t]=r;if(!Array.isArray(e)&&Object.is(e[t],r))return!0;e[t]=r;let n=i.get(e)?.[t];if(n)for(let e of n)s.add(e);return h(),!0},deleteProperty:(e,t)=>(e[t]=void 0,delete e[t],!0)},p=(e,t)=>{if(o.has(e))return o.get(e);if(a.has(e))return e;let r=new Proxy(e,f);o.set(e,r),a.set(r,e);let n=Object.getOwnPropertyDescriptors(e);for(let t in n){let l=n[t];l.get&&l.get&&(l.get=l.get.bind(r),Object.defineProperty(e,t,l))}return e[u]=t?p(t):c,r},y=t=>{const r=()=>{let n=e;e=r,t(),e=n};return r(),r},h=()=>{t||(t=!0,r((()=>{for(let e of s)e.call();s.clear(),t=!1})))},g={},d={};g.if=(e,t)=>{let r=document.createTextNode(""),n=[j(e,t,":if")],l=[e],s=e;for(;(s=e.nextElementSibling)&&s.hasAttribute(":else");)s.removeAttribute(":else"),(t=s.getAttribute(":if"))?(s.removeAttribute(":if"),s.remove(),l.push(s),n.push(j(e,t,":else :if"))):(s.remove(),l.push(s),n.push((()=>1)));return e.replaceWith(s=r),e=>{let t=n.findIndex((t=>t(e)));l[t]!=s&&((s[m]||s).replaceWith(s=l[t]||r),O(s,e))}};var m=Symbol(":each");g.each=(e,t)=>{let r=function(e){let t=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,r=e.match(/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/);if(!r)return;let n=r[2].trim(),l=r[1].replace(/^\s*\(|\)\s*$/g,"").trim(),s=l.match(t);return s?[l.replace(t,"").trim(),s[1].trim(),n]:[l,"",n]}(t);if(!r)return E(new Error,e,t,":each");const n=e[m]=document.createTextNode("");e.replaceWith(n);const s=j(e,r[2],":each"),i=e.getAttribute(":key"),o=i?j(null,i,":each"):null;e.removeAttribute(":key");const a=e.getAttribute(":ref"),u=new l,c=new l;let f=[];return l=>{let i=s(l);i?"number"==typeof i?i=Array.from({length:i},((e,t)=>[t+1,t])):Array.isArray(i)?i=i.map(((e,t)=>[t+1,e])):"object"==typeof i?i=Object.entries(i):E(Error("Bad list value"),e,t,":each"):i=[];let y=[],h=[];for(let[t,n]of i){let s,i,f=o?.({[r[0]]:n,[r[1]]:t});null==f?s=e.cloneNode(!0):(s=c.get(f))||c.set(f,s=e.cloneNode(!0)),y.push(s),null!=f&&(i=u.get(f))?i[r[0]]=n:(i=p({[r[0]]:n,[a||""]:null,[r[1]]:t},l),null!=f&&u.set(f,i)),h.push(i)}!function(e,t,r,n){const l=new Map,s=new Map;let i,o;for(i=0;i<t.length;i++)l.set(t[i],i);for(i=0;i<r.length;i++)s.set(r[i],i);for(i=o=0;i!==t.length||o!==r.length;){var a=t[i],u=r[o];if(null===a)i++;else if(r.length<=o)e.removeChild(t[i]),i++;else if(t.length<=i)e.insertBefore(u,t[i]||n),o++;else if(a===u)i++,o++;else{var c=s.get(a),f=l.get(u);void 0===c?(e.removeChild(t[i]),i++):void 0===f?(e.insertBefore(u,t[i]||n),o++):(e.insertBefore(t[f],t[i]||n),t[f]=null,f>i+1&&i++,o++)}}}(n.parentNode,f,y,n),f=y;for(let e=0;e<y.length;e++)O(y[e],h[e])}},g.with=(e,t,r)=>{const n=j(e,t,":with")(r);O(e,p(n,r))},g.ref=(e,t,r)=>{r[t]=e},d.render=(e,t,r)=>{let n=j(e,t,":render")(r);n||E(new Error("Template not found"),e,t,":render");let l=n.content.cloneNode(!0);e.replaceChildren(l),O(e,r)},d.id=(e,t)=>{let r=j(e,t,":id");return t=>{return n=r(t),e.id=n||0===n?n:"";var n}},d.class=(e,t)=>{let r=j(e,t,":class"),n=e.getAttribute("class");return t=>{let l=r(t),s=[n];l&&("string"==typeof l?s.push(l):Array.isArray(l)?s.push(...l):s.push(...Object.entries(l).map((([e,t])=>t?e:"")))),(s=s.filter(Boolean).join(" "))?e.setAttribute("class",s):e.removeAttribute("class")}},d.style=(e,t)=>{let r=j(e,t,":style"),n=e.getAttribute("style")||"";return n.endsWith(";")||(n+="; "),t=>{let l=r(t);if("string"==typeof l)e.setAttribute("style",n+l);else{e.setAttribute("style",n);for(let t in l)e.style.setProperty(t,l[t])}}},d.text=(e,t)=>{let r=j(e,t,":text");return t=>{let n=r(t);e.textContent=null==n?"":n}},d[""]=(e,t)=>{let r=j(e,t,":");if(r)return t=>{let n=r(t);for(let t in n)x(e,t.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(e=>"-"+e.toLowerCase())),n[t])}},d.value=(e,t)=>{let r,n,l=j(e,t,":value"),s="text"===e.type||""===e.type?t=>e.setAttribute("value",e.value=null==t?"":t):"TEXTAREA"===e.tagName||"text"===e.type||""===e.type?t=>(r=e.selectionStart,n=e.selectionEnd,e.setAttribute("value",e.value=null==t?"":t),r&&e.setSelectionRange(r,n)):"checkbox"===e.type?t=>(e.value=t?"on":"",x(e,"checked",t)):"select-one"===e.type?t=>{for(let t in e.options)t.removeAttribute("selected");e.value=t,e.selectedOptions[0]?.setAttribute("selected","")}:t=>e.value=t;return e=>s(l(e))},d.on=(e,t)=>{let r=j(e,t,":on");return t=>{let n=r(t),l=[];for(let t in n)l.push(v(e,t,n[t]));return()=>{for(let e of l)e()}}};var b=(e,t,r,n)=>{let l=n.startsWith("on")&&n.slice(2),s=j(e,t,":"+n);if(s)return l?t=>{let r=s(t)||(()=>{});return v(e,l,r)}:t=>x(e,n,s(t))},v=(e,t,r)=>{if(!r)return;let n=t.split("..").map((t=>{let r={evt:"",target:e,test:()=>!0};return r.evt=(t.startsWith("on")?t.slice(2):t).replace(/\.(\w+)?-?([-\w]+)?/g,((e,t,n="")=>(r.test=A[t]?.(r,...n.split("-"))||r.test,""))),r}));if(1==n.length)return i(r,n[0]);const l=(t,r=0)=>{let s;return s=i((i=>{r&&s();let o=t.call(e,i);"function"!=typeof o&&(o=()=>{}),r+1<n.length&&l(o,r?r+1:1)}),n[r])};let s=l(r);return()=>s();function i(e,{evt:t,target:r,test:n,defer:l,stop:s,prevent:i,...o}){l&&(e=l(e));let a=t=>n(t)&&(s&&t.stopPropagation(),i&&t.preventDefault(),e.call(r,t));return r.addEventListener(t,a,o),()=>r.removeEventListener(t,a,o)}},A={prevent(e){e.prevent=!0},stop(e){e.stop=!0},once(e){e.once=!0},passive(e){e.passive=!0},capture(e){e.capture=!0},window(e){e.target=window},document(e){e.target=document},toggle(e){e.defer=(t,r)=>n=>r?(r.call?.(e.target,n),r=null):r=t()},throttle(e,t){e.defer=e=>k(e,t?Number(t)||0:108)},debounce(e,t){e.defer=e=>W(e,t?Number(t)||0:108)},outside:e=>t=>{let r=e.target;return!(r.contains(t.target)||!1===t.target.isConnected||r.offsetWidth<1&&r.offsetHeight<1)},self:e=>t=>t.target===e.target,ctrl:(e,...t)=>e=>w.ctrl(e)&&t.every((t=>w[t]?w[t](e):e.key===t)),shift:(e,...t)=>e=>w.shift(e)&&t.every((t=>w[t]?w[t](e):e.key===t)),alt:(e,...t)=>e=>w.alt(e)&&t.every((t=>w[t]?w[t](e):e.key===t)),meta:(e,...t)=>e=>w.meta(e)&&t.every((t=>w[t]?w[t](e):e.key===t)),arrow:e=>w.arrow,enter:e=>w.enter,escape:e=>w.escape,tab:e=>w.tab,space:e=>w.space,backspace:e=>w.backspace,delete:e=>w.delete,digit:e=>w.digit,letter:e=>w.letter,character:e=>w.character},w={ctrl:e=>e.ctrlKey||"Control"===e.key||"Ctrl"===e.key,shift:e=>e.shiftKey||"Shift"===e.key,alt:e=>e.altKey||"Alt"===e.key,meta:e=>e.metaKey||"Meta"===e.key||"Command"===e.key,arrow:e=>e.key.startsWith("Arrow"),enter:e=>"Enter"===e.key,escape:e=>e.key.startsWith("Esc"),tab:e=>"Tab"===e.key,space:e=>" "===e.key||"Space"===e.key||" "===e.key,backspace:e=>"Backspace"===e.key,delete:e=>"Delete"===e.key,digit:e=>/^\d$/.test(e.key),letter:e=>/^[a-zA-Z]$/.test(e.key),character:e=>/^\S$/.test(e.key)},k=(e,t)=>{let r,n,l=s=>{r=!0,setTimeout((()=>{if(r=!1,n)return n=!1,l(s),e(s)}),t)};return t=>r?n=!0:(l(t),e(t))},W=(e,t)=>{let r;return n=>{clearTimeout(r),r=setTimeout((()=>{r=null,e(n)}),t)}},x=(e,t,r)=>{null==r||!1===r?e.removeAttribute(t):e.setAttribute(t,!0===r?"":"number"==typeof r||"string"==typeof r?r:"")},S={};function j(e,t,r){let n=S[t];if(!n){let l=/^[\n\s]*if.*\(.*\)/.test(t)||/\b(let|const)\s/.test(t)&&!r.startsWith(":on")?`(() => {${t}})()`:t;try{n=S[t]=new Function("__scope",`with (__scope) { return ${l.trim()} };`)}catch(n){return E(n,e,t,r)}}return l=>{let s;try{s=n.call(e,l)}catch(n){return E(n,e,t,r)}return s}}function E(e,t,n,l){Object.assign(e,{element:t,expression:n}),console.warn(`∴ ${e.message}\n\n${l}=${n?`"${n}"\n\n`:""}`,t),r((()=>{throw e}),0)}O.globals=c;var N=new WeakMap;function O(e,t){if(!e.children)return;if(N.has(e))return Object.assign(N.get(e),t);const r=p(t||{}),n=[],l=(e,t=e.parentNode)=>{for(let l in g){let s=":"+l;if(e.hasAttribute?.(s)){let i=e.getAttribute(s);if(e.removeAttribute(s),n.push(g[l](e,i,r,l)),N.has(e))return;if(e.parentNode!==t)return!1}}if(e.attributes)for(let t=0;t<e.attributes.length;){let l=e.attributes[t];if(":"!==l.name[0]){t++;continue}e.removeAttribute(l.name);let s=l.value,i=l.name.slice(1).split(":");for(let t of i){let l=d[t]||b;n.push(l(e,s,r,t))}}for(let t,r=0;t=e.children[r];r++)!1===l(t,e)&&r--};l(e);for(let e of n)if(e){let t;y((()=>{"function"==typeof t&&t(),t=e(r)}))}return N.set(e,r),r}document.currentScript&&O(document.documentElement)})();
|
package/sprae.js
CHANGED
|
@@ -222,12 +222,6 @@ primary["if"] = (el, expr) => {
|
|
|
222
222
|
}
|
|
223
223
|
};
|
|
224
224
|
};
|
|
225
|
-
primary["with"] = (el, expr, rootState) => {
|
|
226
|
-
let evaluate = parseExpr(el, expr, ":with");
|
|
227
|
-
const localState = evaluate(rootState);
|
|
228
|
-
let state2 = state(localState, rootState);
|
|
229
|
-
sprae(el, state2);
|
|
230
|
-
};
|
|
231
225
|
var _each = Symbol(":each");
|
|
232
226
|
primary["each"] = (tpl, expr) => {
|
|
233
227
|
let each = parseForExpression(expr);
|
|
@@ -248,7 +242,7 @@ primary["each"] = (tpl, expr) => {
|
|
|
248
242
|
if (!list)
|
|
249
243
|
list = [];
|
|
250
244
|
else if (typeof list === "number")
|
|
251
|
-
list = Array.from({ length: list }, (_, i) => [i
|
|
245
|
+
list = Array.from({ length: list }, (_, i) => [i + 1, i]);
|
|
252
246
|
else if (Array.isArray(list))
|
|
253
247
|
list = list.map((item, i) => [i + 1, item]);
|
|
254
248
|
else if (typeof list === "object")
|
|
@@ -278,6 +272,12 @@ primary["each"] = (tpl, expr) => {
|
|
|
278
272
|
}
|
|
279
273
|
};
|
|
280
274
|
};
|
|
275
|
+
primary["with"] = (el, expr, rootState) => {
|
|
276
|
+
let evaluate = parseExpr(el, expr, ":with");
|
|
277
|
+
const localState = evaluate(rootState);
|
|
278
|
+
let state2 = state(localState, rootState);
|
|
279
|
+
sprae(el, state2);
|
|
280
|
+
};
|
|
281
281
|
primary["ref"] = (el, expr, state2) => {
|
|
282
282
|
state2[expr] = el;
|
|
283
283
|
};
|
package/sprae.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e,t,r=Promise.prototype.then.bind(Promise.resolve()),n=new WeakMap,l=class extends Map{#e=new FinalizationRegistry((e=>super.delete(e)));get size(){return[...this].length}constructor(e=[]){super();for(const[t,r]of e)this.set(t,r)}get(e){return super.get(e)?.deref()}set(e,t){let r=super.get(e);return r&&this.#e.unregister(r),r=(e=>n.get(e)||(e=>{const t=new WeakRef(e);return n.set(e,t),t})(e))(t),this.#e.register(t,e,r),super.set(e,r)}},s=new Set,i=new WeakMap,o=new WeakMap,a=new WeakMap,u=Symbol("parent"),c={Array:Array,Object:Object,Number:Number,String:String,Boolean:Boolean,Date:Date,console:console,window:window,document:document,history:history,location:location},f={has:()=>!0,get(t,r){if("symbol"==typeof r)return t[r];if(!(r in t))return t[u]?.[r];if(r in Object.prototype||Array.isArray(t)&&r in Array.prototype&&"length"!==r)return t[r];let n=t[r];if(e){let n=i.get(t);n||i.set(t,n={}),n[r]?n[r].includes(e)||n[r].push(e):n[r]=[e]}if(n&&n.constructor===Object||Array.isArray(n)){let e=o.get(n);return e||o.set(n,e=new Proxy(n,f)),e}return n},set(e,t,r){if(!(t in e)&&e[u]&&t in e[u])return e[u][t]=r;if(!Array.isArray(e)&&Object.is(e[t],r))return!0;e[t]=r;let n=i.get(e)?.[t];if(n)for(let e of n)s.add(e);return h(),!0},deleteProperty:(e,t)=>(e[t]=void 0,delete e[t],!0)},p=(e,t)=>{if(o.has(e))return o.get(e);if(a.has(e))return e;let r=new Proxy(e,f);o.set(e,r),a.set(r,e);let n=Object.getOwnPropertyDescriptors(e);for(let t in n){let l=n[t];l.get&&l.get&&(l.get=l.get.bind(r),Object.defineProperty(e,t,l))}return e[u]=t?p(t):c,r},y=t=>{const r=()=>{let n=e;e=r,t(),e=n};return r(),r},h=()=>{t||(t=!0,r((()=>{for(let e of s)e.call();s.clear(),t=!1})))},g={},d={};g.if=(e,t)=>{let r=document.createTextNode(""),n=[j(e,t,":if")],l=[e],s=e;for(;(s=e.nextElementSibling)&&s.hasAttribute(":else");)s.removeAttribute(":else"),(t=s.getAttribute(":if"))?(s.removeAttribute(":if"),s.remove(),l.push(s),n.push(j(e,t,":else :if"))):(s.remove(),l.push(s),n.push((()=>1)));return e.replaceWith(s=r),e=>{let t=n.findIndex((t=>t(e)));l[t]!=s&&((s[m]||s).replaceWith(s=l[t]||r),O(s,e))}}
|
|
1
|
+
var e,t,r=Promise.prototype.then.bind(Promise.resolve()),n=new WeakMap,l=class extends Map{#e=new FinalizationRegistry((e=>super.delete(e)));get size(){return[...this].length}constructor(e=[]){super();for(const[t,r]of e)this.set(t,r)}get(e){return super.get(e)?.deref()}set(e,t){let r=super.get(e);return r&&this.#e.unregister(r),r=(e=>n.get(e)||(e=>{const t=new WeakRef(e);return n.set(e,t),t})(e))(t),this.#e.register(t,e,r),super.set(e,r)}},s=new Set,i=new WeakMap,o=new WeakMap,a=new WeakMap,u=Symbol("parent"),c={Array:Array,Object:Object,Number:Number,String:String,Boolean:Boolean,Date:Date,console:console,window:window,document:document,history:history,location:location},f={has:()=>!0,get(t,r){if("symbol"==typeof r)return t[r];if(!(r in t))return t[u]?.[r];if(r in Object.prototype||Array.isArray(t)&&r in Array.prototype&&"length"!==r)return t[r];let n=t[r];if(e){let n=i.get(t);n||i.set(t,n={}),n[r]?n[r].includes(e)||n[r].push(e):n[r]=[e]}if(n&&n.constructor===Object||Array.isArray(n)){let e=o.get(n);return e||o.set(n,e=new Proxy(n,f)),e}return n},set(e,t,r){if(!(t in e)&&e[u]&&t in e[u])return e[u][t]=r;if(!Array.isArray(e)&&Object.is(e[t],r))return!0;e[t]=r;let n=i.get(e)?.[t];if(n)for(let e of n)s.add(e);return h(),!0},deleteProperty:(e,t)=>(e[t]=void 0,delete e[t],!0)},p=(e,t)=>{if(o.has(e))return o.get(e);if(a.has(e))return e;let r=new Proxy(e,f);o.set(e,r),a.set(r,e);let n=Object.getOwnPropertyDescriptors(e);for(let t in n){let l=n[t];l.get&&l.get&&(l.get=l.get.bind(r),Object.defineProperty(e,t,l))}return e[u]=t?p(t):c,r},y=t=>{const r=()=>{let n=e;e=r,t(),e=n};return r(),r},h=()=>{t||(t=!0,r((()=>{for(let e of s)e.call();s.clear(),t=!1})))},g={},d={};g.if=(e,t)=>{let r=document.createTextNode(""),n=[j(e,t,":if")],l=[e],s=e;for(;(s=e.nextElementSibling)&&s.hasAttribute(":else");)s.removeAttribute(":else"),(t=s.getAttribute(":if"))?(s.removeAttribute(":if"),s.remove(),l.push(s),n.push(j(e,t,":else :if"))):(s.remove(),l.push(s),n.push((()=>1)));return e.replaceWith(s=r),e=>{let t=n.findIndex((t=>t(e)));l[t]!=s&&((s[m]||s).replaceWith(s=l[t]||r),O(s,e))}};var m=Symbol(":each");g.each=(e,t)=>{let r=function(e){let t=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,r=e.match(/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/);if(!r)return;let n=r[2].trim(),l=r[1].replace(/^\s*\(|\)\s*$/g,"").trim(),s=l.match(t);return s?[l.replace(t,"").trim(),s[1].trim(),n]:[l,"",n]}(t);if(!r)return E(new Error,e,t,":each");const n=e[m]=document.createTextNode("");e.replaceWith(n);const s=j(e,r[2],":each"),i=e.getAttribute(":key"),o=i?j(null,i,":each"):null;e.removeAttribute(":key");const a=e.getAttribute(":ref"),u=new l,c=new l;let f=[];return l=>{let i=s(l);i?"number"==typeof i?i=Array.from({length:i},((e,t)=>[t+1,t])):Array.isArray(i)?i=i.map(((e,t)=>[t+1,e])):"object"==typeof i?i=Object.entries(i):E(Error("Bad list value"),e,t,":each"):i=[];let y=[],h=[];for(let[t,n]of i){let s,i,f=o?.({[r[0]]:n,[r[1]]:t});null==f?s=e.cloneNode(!0):(s=c.get(f))||c.set(f,s=e.cloneNode(!0)),y.push(s),null!=f&&(i=u.get(f))?i[r[0]]=n:(i=p({[r[0]]:n,[a||""]:null,[r[1]]:t},l),null!=f&&u.set(f,i)),h.push(i)}!function(e,t,r,n){const l=new Map,s=new Map;let i,o;for(i=0;i<t.length;i++)l.set(t[i],i);for(i=0;i<r.length;i++)s.set(r[i],i);for(i=o=0;i!==t.length||o!==r.length;){var a=t[i],u=r[o];if(null===a)i++;else if(r.length<=o)e.removeChild(t[i]),i++;else if(t.length<=i)e.insertBefore(u,t[i]||n),o++;else if(a===u)i++,o++;else{var c=s.get(a),f=l.get(u);void 0===c?(e.removeChild(t[i]),i++):void 0===f?(e.insertBefore(u,t[i]||n),o++):(e.insertBefore(t[f],t[i]||n),t[f]=null,f>i+1&&i++,o++)}}}(n.parentNode,f,y,n),f=y;for(let e=0;e<y.length;e++)O(y[e],h[e])}},g.with=(e,t,r)=>{const n=j(e,t,":with")(r);O(e,p(n,r))},g.ref=(e,t,r)=>{r[t]=e},d.render=(e,t,r)=>{let n=j(e,t,":render")(r);n||E(new Error("Template not found"),e,t,":render");let l=n.content.cloneNode(!0);e.replaceChildren(l),O(e,r)},d.id=(e,t)=>{let r=j(e,t,":id");return t=>{return n=r(t),e.id=n||0===n?n:"";var n}},d.class=(e,t)=>{let r=j(e,t,":class"),n=e.getAttribute("class");return t=>{let l=r(t),s=[n];l&&("string"==typeof l?s.push(l):Array.isArray(l)?s.push(...l):s.push(...Object.entries(l).map((([e,t])=>t?e:"")))),(s=s.filter(Boolean).join(" "))?e.setAttribute("class",s):e.removeAttribute("class")}},d.style=(e,t)=>{let r=j(e,t,":style"),n=e.getAttribute("style")||"";return n.endsWith(";")||(n+="; "),t=>{let l=r(t);if("string"==typeof l)e.setAttribute("style",n+l);else{e.setAttribute("style",n);for(let t in l)e.style.setProperty(t,l[t])}}},d.text=(e,t)=>{let r=j(e,t,":text");return t=>{let n=r(t);e.textContent=null==n?"":n}},d[""]=(e,t)=>{let r=j(e,t,":");if(r)return t=>{let n=r(t);for(let t in n)x(e,t.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(e=>"-"+e.toLowerCase())),n[t])}},d.value=(e,t)=>{let r,n,l=j(e,t,":value"),s="text"===e.type||""===e.type?t=>e.setAttribute("value",e.value=null==t?"":t):"TEXTAREA"===e.tagName||"text"===e.type||""===e.type?t=>(r=e.selectionStart,n=e.selectionEnd,e.setAttribute("value",e.value=null==t?"":t),r&&e.setSelectionRange(r,n)):"checkbox"===e.type?t=>(e.value=t?"on":"",x(e,"checked",t)):"select-one"===e.type?t=>{for(let t in e.options)t.removeAttribute("selected");e.value=t,e.selectedOptions[0]?.setAttribute("selected","")}:t=>e.value=t;return e=>s(l(e))},d.on=(e,t)=>{let r=j(e,t,":on");return t=>{let n=r(t),l=[];for(let t in n)l.push(v(e,t,n[t]));return()=>{for(let e of l)e()}}};var b=(e,t,r,n)=>{let l=n.startsWith("on")&&n.slice(2),s=j(e,t,":"+n);if(s)return l?t=>{let r=s(t)||(()=>{});return v(e,l,r)}:t=>x(e,n,s(t))},v=(e,t,r)=>{if(!r)return;let n=t.split("..").map((t=>{let r={evt:"",target:e,test:()=>!0};return r.evt=(t.startsWith("on")?t.slice(2):t).replace(/\.(\w+)?-?([-\w]+)?/g,((e,t,n="")=>(r.test=A[t]?.(r,...n.split("-"))||r.test,""))),r}));if(1==n.length)return i(r,n[0]);const l=(t,r=0)=>{let s;return s=i((i=>{r&&s();let o=t.call(e,i);"function"!=typeof o&&(o=()=>{}),r+1<n.length&&l(o,r?r+1:1)}),n[r])};let s=l(r);return()=>s();function i(e,{evt:t,target:r,test:n,defer:l,stop:s,prevent:i,...o}){l&&(e=l(e));let a=t=>n(t)&&(s&&t.stopPropagation(),i&&t.preventDefault(),e.call(r,t));return r.addEventListener(t,a,o),()=>r.removeEventListener(t,a,o)}},A={prevent(e){e.prevent=!0},stop(e){e.stop=!0},once(e){e.once=!0},passive(e){e.passive=!0},capture(e){e.capture=!0},window(e){e.target=window},document(e){e.target=document},toggle(e){e.defer=(t,r)=>n=>r?(r.call?.(e.target,n),r=null):r=t()},throttle(e,t){e.defer=e=>k(e,t?Number(t)||0:108)},debounce(e,t){e.defer=e=>W(e,t?Number(t)||0:108)},outside:e=>t=>{let r=e.target;return!(r.contains(t.target)||!1===t.target.isConnected||r.offsetWidth<1&&r.offsetHeight<1)},self:e=>t=>t.target===e.target,ctrl:(e,...t)=>e=>w.ctrl(e)&&t.every((t=>w[t]?w[t](e):e.key===t)),shift:(e,...t)=>e=>w.shift(e)&&t.every((t=>w[t]?w[t](e):e.key===t)),alt:(e,...t)=>e=>w.alt(e)&&t.every((t=>w[t]?w[t](e):e.key===t)),meta:(e,...t)=>e=>w.meta(e)&&t.every((t=>w[t]?w[t](e):e.key===t)),arrow:e=>w.arrow,enter:e=>w.enter,escape:e=>w.escape,tab:e=>w.tab,space:e=>w.space,backspace:e=>w.backspace,delete:e=>w.delete,digit:e=>w.digit,letter:e=>w.letter,character:e=>w.character},w={ctrl:e=>e.ctrlKey||"Control"===e.key||"Ctrl"===e.key,shift:e=>e.shiftKey||"Shift"===e.key,alt:e=>e.altKey||"Alt"===e.key,meta:e=>e.metaKey||"Meta"===e.key||"Command"===e.key,arrow:e=>e.key.startsWith("Arrow"),enter:e=>"Enter"===e.key,escape:e=>e.key.startsWith("Esc"),tab:e=>"Tab"===e.key,space:e=>" "===e.key||"Space"===e.key||" "===e.key,backspace:e=>"Backspace"===e.key,delete:e=>"Delete"===e.key,digit:e=>/^\d$/.test(e.key),letter:e=>/^[a-zA-Z]$/.test(e.key),character:e=>/^\S$/.test(e.key)},k=(e,t)=>{let r,n,l=s=>{r=!0,setTimeout((()=>{if(r=!1,n)return n=!1,l(s),e(s)}),t)};return t=>r?n=!0:(l(t),e(t))},W=(e,t)=>{let r;return n=>{clearTimeout(r),r=setTimeout((()=>{r=null,e(n)}),t)}},x=(e,t,r)=>{null==r||!1===r?e.removeAttribute(t):e.setAttribute(t,!0===r?"":"number"==typeof r||"string"==typeof r?r:"")},S={};function j(e,t,r){let n=S[t];if(!n){let l=/^[\n\s]*if.*\(.*\)/.test(t)||/\b(let|const)\s/.test(t)&&!r.startsWith(":on")?`(() => {${t}})()`:t;try{n=S[t]=new Function("__scope",`with (__scope) { return ${l.trim()} };`)}catch(n){return E(n,e,t,r)}}return l=>{let s;try{s=n.call(e,l)}catch(n){return E(n,e,t,r)}return s}}function E(e,t,n,l){Object.assign(e,{element:t,expression:n}),console.warn(`∴ ${e.message}\n\n${l}=${n?`"${n}"\n\n`:""}`,t),r((()=>{throw e}),0)}O.globals=c;var N=new WeakMap;function O(e,t){if(!e.children)return;if(N.has(e))return Object.assign(N.get(e),t);const r=p(t||{}),n=[],l=(e,t=e.parentNode)=>{for(let l in g){let s=":"+l;if(e.hasAttribute?.(s)){let i=e.getAttribute(s);if(e.removeAttribute(s),n.push(g[l](e,i,r,l)),N.has(e))return;if(e.parentNode!==t)return!1}}if(e.attributes)for(let t=0;t<e.attributes.length;){let l=e.attributes[t];if(":"!==l.name[0]){t++;continue}e.removeAttribute(l.name);let s=l.value,i=l.name.slice(1).split(":");for(let t of i){let l=d[t]||b;n.push(l(e,s,r,t))}}for(let t,r=0;t=e.children[r];r++)!1===l(t,e)&&r--};l(e);for(let e of n)if(e){let t;y((()=>{"function"==typeof t&&t(),t=e(r)}))}return N.set(e,r),r}var $=O;document.currentScript&&O(document.documentElement);export{$ as default};
|
package/src/directives.js
CHANGED
|
@@ -45,14 +45,6 @@ primary['if'] = (el, expr) => {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
// :with must come before :each, but :if has primary importance
|
|
49
|
-
primary['with'] = (el, expr, rootState) => {
|
|
50
|
-
let evaluate = parseExpr(el, expr, ':with')
|
|
51
|
-
const localState = evaluate(rootState)
|
|
52
|
-
let state = createState(localState, rootState)
|
|
53
|
-
sprae(el, state);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
48
|
const _each = Symbol(':each')
|
|
57
49
|
|
|
58
50
|
// :each must init before :ref, :id or any others, since it defines scope
|
|
@@ -82,7 +74,7 @@ primary['each'] = (tpl, expr) => {
|
|
|
82
74
|
let list = evaluate(state)
|
|
83
75
|
|
|
84
76
|
if (!list) list = []
|
|
85
|
-
else if (typeof list === 'number') list = Array.from({length: list}, (_, i)=>[i, i
|
|
77
|
+
else if (typeof list === 'number') list = Array.from({length: list}, (_, i)=>[i+1, i])
|
|
86
78
|
else if (Array.isArray(list)) list = list.map((item,i) => [i+1, item])
|
|
87
79
|
else if (typeof list === 'object') list = Object.entries(list)
|
|
88
80
|
else exprError(Error('Bad list value'), tpl, expr, ':each', list)
|
|
@@ -120,6 +112,15 @@ primary['each'] = (tpl, expr) => {
|
|
|
120
112
|
}
|
|
121
113
|
}
|
|
122
114
|
|
|
115
|
+
// `:each` can redefine scope as `:each="a in {myScope}"`,
|
|
116
|
+
// same time per-item scope as `:each="..." :with="{collapsed:true}"` is useful
|
|
117
|
+
primary['with'] = (el, expr, rootState) => {
|
|
118
|
+
let evaluate = parseExpr(el, expr, ':with')
|
|
119
|
+
const localState = evaluate(rootState)
|
|
120
|
+
let state = createState(localState, rootState)
|
|
121
|
+
sprae(el, state);
|
|
122
|
+
}
|
|
123
|
+
|
|
123
124
|
// ref must be last within primaries, since that must be skipped by :each, but before secondaries
|
|
124
125
|
primary['ref'] = (el, expr, state) => {
|
|
125
126
|
// FIXME: wait for complex ref use-case
|
package/test/dom.js
CHANGED
|
@@ -447,10 +447,10 @@ test('each: loop within condition', async () => {
|
|
|
447
447
|
|
|
448
448
|
const params = sprae(el, { a: 1 })
|
|
449
449
|
|
|
450
|
-
is(el.innerHTML, '<x><y>
|
|
450
|
+
is(el.innerHTML, '<x><y>0</y></x>')
|
|
451
451
|
params.a = 2
|
|
452
452
|
await tick()
|
|
453
|
-
is(el.innerHTML, '<x><y
|
|
453
|
+
is(el.innerHTML, '<x><y>0</y><y>-1</y></x>')
|
|
454
454
|
params.a = 0
|
|
455
455
|
await tick()
|
|
456
456
|
is(el.innerHTML, '')
|
|
@@ -481,7 +481,7 @@ test('each: next items have own "this", not single one', async () => {
|
|
|
481
481
|
let el = h`<div><x :each="x in 3" :data-x="x" :x="log.push(x, this.dataset.x)"></x></div>`
|
|
482
482
|
let log = []
|
|
483
483
|
let state = sprae(el, {log})
|
|
484
|
-
is(state.log, [1,'1',2,'2'
|
|
484
|
+
is(state.log, [0,'0',1,'1',2,'2'])
|
|
485
485
|
})
|
|
486
486
|
|
|
487
487
|
test('each: unkeyed', async () => {
|
|
@@ -520,7 +520,7 @@ test('each: keyed', async () => {
|
|
|
520
520
|
test('each: wrapped source', async () => {
|
|
521
521
|
let el = h`<div><x :each="i in (x || 2)" :text="i"></x></div>`
|
|
522
522
|
sprae(el, {x:0})
|
|
523
|
-
is(el.innerHTML, `<x>
|
|
523
|
+
is(el.innerHTML, `<x>0</x><x>1</x>`)
|
|
524
524
|
})
|
|
525
525
|
|
|
526
526
|
test('each: unmounted elements remove listeners', async () => {
|
|
@@ -564,6 +564,12 @@ test('each: key-based caching is in-sync with direct elements', () => {
|
|
|
564
564
|
is(el.outerHTML, el2.outerHTML)
|
|
565
565
|
})
|
|
566
566
|
|
|
567
|
+
test('each: with :with', () => {
|
|
568
|
+
let el = h`<ul><li :each="i in 3" :with="{x:i}" :text="x"></li></ul>`
|
|
569
|
+
sprae(el)
|
|
570
|
+
is(el.outerHTML, `<ul><li>0</li><li>1</li><li>2</li></ul>`)
|
|
571
|
+
})
|
|
572
|
+
|
|
567
573
|
test('on: base', async () => {
|
|
568
574
|
let el = h`<div :on="{click(e){log.push('click')}, x}"></div>`
|
|
569
575
|
let log = []
|
package/todo.md
CHANGED
|
@@ -50,4 +50,5 @@
|
|
|
50
50
|
* [x] Autorun
|
|
51
51
|
* [x] There's some bug with prostogreen not triggering effect. (caused by special array.length case)
|
|
52
52
|
* [x] Getters must become evaluable
|
|
53
|
-
* [ ] `:with="{likes:[], like(){ /* likes should not be undefined here */ }}"`
|
|
53
|
+
* [ ] `:with="{likes:[], like(){ /* likes should not be undefined here */ }}"`
|
|
54
|
+
* [ ] `<li :each="item in items" :with="{collapsed:true}"><button :onclick='e=>collapsed=false'></li>`
|