sprae 5.1.0 → 5.2.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/examples/todomvc.html +8 -10
- package/package.json +1 -1
- package/r&d.md +1 -2
- package/readme.md +16 -21
- package/sprae.auto.js +21 -2
- package/sprae.auto.min.js +1 -1
- package/sprae.js +21 -2
- package/sprae.min.js +1 -1
- package/src/directives.js +8 -2
- package/src/state.js +11 -0
- package/test/dom.js +22 -9
- package/todo.md +3 -1
package/examples/todomvc.html
CHANGED
|
@@ -40,22 +40,20 @@
|
|
|
40
40
|
:onchange="e => (item.done = !item.done, save(todos))"
|
|
41
41
|
/>
|
|
42
42
|
<label :text="item.text"></label>
|
|
43
|
-
<button class="destroy" :onclick="e => save(todos = todos.filter(i => i !== item))"></button>
|
|
43
|
+
<button class="destroy" :onclick="e => (save(todos = todos.filter(i => i.text !== item.text)))"></button>
|
|
44
44
|
</div>
|
|
45
45
|
<input class=edit
|
|
46
46
|
:value="item.text"
|
|
47
|
-
:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
keypress(e) { e.key === 'Enter' ? e.target.blur() : null },
|
|
51
|
-
}"
|
|
47
|
+
:oninput="e => {item.text = e.target.value; save(todos)}"
|
|
48
|
+
:onblur="e => li.classList.remove('editing');"
|
|
49
|
+
:onkeypress="(e) => { e.key === 'Enter' ? e.target.blur() : null }"
|
|
52
50
|
/>
|
|
53
51
|
</li>
|
|
54
52
|
</ul>
|
|
55
53
|
</section>
|
|
56
54
|
<footer class="footer">
|
|
57
55
|
<span class="todo-count">
|
|
58
|
-
<strong :text="count">#</strong> <span :text="plur('item', count)">items</span> left
|
|
56
|
+
<strong :text="count()">#</strong> <span :text="plur('item', count())">items</span> left
|
|
59
57
|
</span>
|
|
60
58
|
<ul class="filters">
|
|
61
59
|
<li :each="label, key in {'#/': 'All', '#/active': 'Active', '#/completed': 'Completed'}">
|
|
@@ -77,19 +75,19 @@
|
|
|
77
75
|
<script src="https://unpkg.com/todomvc-common/base.js"></script>
|
|
78
76
|
<script type="importmap"> {
|
|
79
77
|
"imports": {
|
|
80
|
-
"sprae": "https://cdn.
|
|
78
|
+
"sprae": "https://cdn.jsdelivr.net/npm/sprae/sprae.min.js",
|
|
81
79
|
"plur": "https://cdn.skypack.dev/plur"
|
|
82
80
|
}
|
|
83
81
|
}
|
|
84
82
|
</script>
|
|
85
83
|
<script type="module">
|
|
86
|
-
import sprae from 'sprae'
|
|
84
|
+
import sprae from '../sprae.js'
|
|
87
85
|
import plur from 'plur'
|
|
88
86
|
|
|
89
87
|
let state = sprae(document.body, {
|
|
90
88
|
plur,
|
|
91
89
|
todos: JSON.parse(localStorage.getItem('todomvc.items') || '[]'),
|
|
92
|
-
|
|
90
|
+
count() { return this.todos.filter(item => !item.done).length },
|
|
93
91
|
hash: window.location.hash || '#/',
|
|
94
92
|
save: items => localStorage.setItem('todomvc.items', JSON.stringify(items))
|
|
95
93
|
})
|
package/package.json
CHANGED
package/r&d.md
CHANGED
|
@@ -448,8 +448,6 @@
|
|
|
448
448
|
* onkey.after, onkey.microtask, onkey.defer, onkey.immediate
|
|
449
449
|
* onkey.tick-1?
|
|
450
450
|
|
|
451
|
-
### [ ] onkey.unfocusable
|
|
452
|
-
|
|
453
451
|
## [ ] Prop modifiers
|
|
454
452
|
|
|
455
453
|
- overall seems code complication without much benefit
|
|
@@ -475,6 +473,7 @@
|
|
|
475
473
|
* [ ] x.watch-a-b-c - update by change of any of the deps
|
|
476
474
|
* [ ] :x.always - update by _any_ dep change
|
|
477
475
|
* [ ] :class.active="active"
|
|
476
|
+
* [ ] :x.persist="v"
|
|
478
477
|
|
|
479
478
|
## [x] Writing props on elements (like ones in :each) -> nah, just use `:x="this.x=abc"`
|
|
480
479
|
|
package/readme.md
CHANGED
|
@@ -63,14 +63,12 @@ Control flow of elements.
|
|
|
63
63
|
Multiply element. `index` value starts from 1.
|
|
64
64
|
|
|
65
65
|
```html
|
|
66
|
-
<ul>
|
|
67
|
-
<li :each="item in items" :text="item">Untitled</li>
|
|
68
|
-
</ul>
|
|
66
|
+
<ul><li :each="item in items" :text="item"></ul>
|
|
69
67
|
|
|
70
68
|
<!-- Cases -->
|
|
71
69
|
<li :each="item, idx in list" />
|
|
72
70
|
<li :each="val, key in obj" />
|
|
73
|
-
<li :each="
|
|
71
|
+
<li :each="idx1, idx0 in number" />
|
|
74
72
|
|
|
75
73
|
<!-- Loop by condition -->
|
|
76
74
|
<li :if="items" :each="item in items" :text="item" />
|
|
@@ -78,9 +76,6 @@ Multiply element. `index` value starts from 1.
|
|
|
78
76
|
|
|
79
77
|
<!-- Key items to reuse elements -->
|
|
80
78
|
<li :each="item in items" :key="item.id" :text="item.value" />
|
|
81
|
-
|
|
82
|
-
<!-- To avoid FOUC -->
|
|
83
|
-
<style>[:each]{visibility: hidden}</style>
|
|
84
79
|
```
|
|
85
80
|
|
|
86
81
|
#### `:text="value"`
|
|
@@ -131,7 +126,7 @@ Set value of an input, textarea or select. Takes handle of `checked` and `select
|
|
|
131
126
|
|
|
132
127
|
#### `:<prop>="value?"`
|
|
133
128
|
|
|
134
|
-
Set any attribute value or run effect.
|
|
129
|
+
Set any attribute value or run an effect.
|
|
135
130
|
|
|
136
131
|
```html
|
|
137
132
|
<!-- Single property -->
|
|
@@ -166,10 +161,8 @@ Add event listener or events chain.
|
|
|
166
161
|
<!-- Sequence of events -->
|
|
167
162
|
<button :onfocus..onblur="e => {
|
|
168
163
|
// onfocus
|
|
169
|
-
let id = setInterval(track,200)
|
|
170
164
|
return e => {
|
|
171
165
|
// onblur
|
|
172
|
-
clearInterval(id)
|
|
173
166
|
}
|
|
174
167
|
}">
|
|
175
168
|
|
|
@@ -223,6 +216,7 @@ Expose element to current data scope with the `id`:
|
|
|
223
216
|
```html
|
|
224
217
|
<!-- single item -->
|
|
225
218
|
<textarea :ref="text" placeholder="Enter text..."></textarea>
|
|
219
|
+
<span :text="text.value"></span>
|
|
226
220
|
|
|
227
221
|
<!-- iterable items -->
|
|
228
222
|
<ul>
|
|
@@ -230,14 +224,6 @@ Expose element to current data scope with the `id`:
|
|
|
230
224
|
<input :onfocus..onblur="e => (item.classList.add('editing'), e => item.classList.remove('editing'))"/>
|
|
231
225
|
</li>
|
|
232
226
|
</ul>
|
|
233
|
-
|
|
234
|
-
<script type="module">
|
|
235
|
-
import sprae from 'sprae';
|
|
236
|
-
let state = sprae(document, {items: ['a','b','c']})
|
|
237
|
-
|
|
238
|
-
// element is in the state
|
|
239
|
-
state.text // <textarea></textarea>
|
|
240
|
-
</script>
|
|
241
227
|
```
|
|
242
228
|
|
|
243
229
|
## Sandbox
|
|
@@ -252,10 +238,20 @@ Expressions are sandboxed, ie. have no access to global or window (since sprae c
|
|
|
252
238
|
Default sandbox provides: _window_, _document_, _console_, _history_, _location_, _Array_, _Object_, _Number_, _String_, _Boolean_, _Date_, _Set_, _Map_.<br/>
|
|
253
239
|
Sandbox can be extended as `Object.assign(sprae.globals, { BigInt })`.
|
|
254
240
|
|
|
241
|
+
## FOUC
|
|
242
|
+
|
|
243
|
+
To avoid _flash of unstyled content_, you can hide sprae attribute or add a custom effect, eg. `:hidden` - that will be removed once sprae is initialized:
|
|
244
|
+
|
|
245
|
+
```html
|
|
246
|
+
<div :hidden></div>
|
|
247
|
+
<style>[:each],[:hidden] {visibility: hidden}</style>
|
|
248
|
+
```
|
|
249
|
+
|
|
255
250
|
## Examples
|
|
256
251
|
|
|
257
252
|
* TODO MVC: [demo](https://dy.github.io/sprae/examples/todomvc), [code](https://github.com/dy/sprae/blob/main/examples/todomvc.html)
|
|
258
253
|
* Wavearea: [demo](https://dy.github.io/wavearea?src=//cdn.freesound.org/previews/586/586281_2332564-lq.mp3), [code](https://github.com/dy/wavearea)
|
|
254
|
+
* Prostogreen [demo](http://web-being.org/prostogreen/), [code](https://github.com/web-being/prostogreen/)
|
|
259
255
|
|
|
260
256
|
## Justification
|
|
261
257
|
|
|
@@ -263,15 +259,14 @@ Sandbox can be extended as `Object.assign(sprae.globals, { BigInt })`.
|
|
|
263
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.
|
|
264
260
|
* 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).
|
|
265
261
|
|
|
266
|
-
_Sprae_ takes convention of _templize directives_ (_alpine_/_vue_ attrs) and builds upon <del>[_@preact/signals_](https://ghub.io/@preact/signals)</del> simple
|
|
262
|
+
_Sprae_ takes convention of _templize directives_ (_alpine_/_vue_ attrs) and builds upon <del>[_@preact/signals_](https://ghub.io/@preact/signals)</del> simple reactive state.
|
|
267
263
|
|
|
268
|
-
* It doesn't break or modify
|
|
264
|
+
* It doesn't break or modify static html markup.
|
|
269
265
|
* It falls back to element content if uninitialized.
|
|
270
266
|
* It doesn't enforce SPA nor JSX.
|
|
271
267
|
* It enables island hydration.
|
|
272
268
|
* It reserves minimal syntax space as `:` convention (keeping tree neatly decorated, not scattered).
|
|
273
269
|
* Expressions are naturally reactive and incur minimal updates.
|
|
274
|
-
* Input data may contain [signals](https://ghub.io/@preact/signals) or [reactive values](https://ghub.io/sube).
|
|
275
270
|
* Elements / data API is open and enable easy interop.
|
|
276
271
|
|
|
277
272
|
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.
|
package/sprae.auto.js
CHANGED
|
@@ -108,6 +108,14 @@
|
|
|
108
108
|
let proxy = new Proxy(obj, handler);
|
|
109
109
|
targetProxy.set(obj, proxy);
|
|
110
110
|
proxyTarget.set(proxy, obj);
|
|
111
|
+
let descriptors = Object.getOwnPropertyDescriptors(obj);
|
|
112
|
+
for (let name in descriptors) {
|
|
113
|
+
let desc = descriptors[name];
|
|
114
|
+
if (desc.get) {
|
|
115
|
+
if (desc.get)
|
|
116
|
+
desc.get = desc.get.bind(proxy), Object.defineProperty(obj, name, desc);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
111
119
|
obj[_parent] = parent ? state(parent) : sandbox;
|
|
112
120
|
return proxy;
|
|
113
121
|
};
|
|
@@ -310,8 +318,19 @@
|
|
|
310
318
|
let initClassName = el.getAttribute("class");
|
|
311
319
|
return (state2) => {
|
|
312
320
|
let v = evaluate(state2);
|
|
313
|
-
let className =
|
|
314
|
-
|
|
321
|
+
let className = [initClassName];
|
|
322
|
+
if (v) {
|
|
323
|
+
if (typeof v === "string")
|
|
324
|
+
className.push(v);
|
|
325
|
+
else if (Array.isArray(v))
|
|
326
|
+
className.push(...v);
|
|
327
|
+
else
|
|
328
|
+
className.push(...Object.entries(v).map(([k, v2]) => v2 ? k : ""));
|
|
329
|
+
}
|
|
330
|
+
if (className = className.filter(Boolean).join(" "))
|
|
331
|
+
el.setAttribute("class", className);
|
|
332
|
+
else
|
|
333
|
+
el.removeAttribute("class");
|
|
315
334
|
};
|
|
316
335
|
};
|
|
317
336
|
secondary["style"] = (el, expr) => {
|
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);
|
|
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))}},g.with=(e,t,r)=>{const n=j(e,t,":with")(r);O(e,p(n,r))};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,t+1])):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.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
|
@@ -107,6 +107,14 @@ var state = (obj, parent) => {
|
|
|
107
107
|
let proxy = new Proxy(obj, handler);
|
|
108
108
|
targetProxy.set(obj, proxy);
|
|
109
109
|
proxyTarget.set(proxy, obj);
|
|
110
|
+
let descriptors = Object.getOwnPropertyDescriptors(obj);
|
|
111
|
+
for (let name in descriptors) {
|
|
112
|
+
let desc = descriptors[name];
|
|
113
|
+
if (desc.get) {
|
|
114
|
+
if (desc.get)
|
|
115
|
+
desc.get = desc.get.bind(proxy), Object.defineProperty(obj, name, desc);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
110
118
|
obj[_parent] = parent ? state(parent) : sandbox;
|
|
111
119
|
return proxy;
|
|
112
120
|
};
|
|
@@ -309,8 +317,19 @@ secondary["class"] = (el, expr) => {
|
|
|
309
317
|
let initClassName = el.getAttribute("class");
|
|
310
318
|
return (state2) => {
|
|
311
319
|
let v = evaluate(state2);
|
|
312
|
-
let className =
|
|
313
|
-
|
|
320
|
+
let className = [initClassName];
|
|
321
|
+
if (v) {
|
|
322
|
+
if (typeof v === "string")
|
|
323
|
+
className.push(v);
|
|
324
|
+
else if (Array.isArray(v))
|
|
325
|
+
className.push(...v);
|
|
326
|
+
else
|
|
327
|
+
className.push(...Object.entries(v).map(([k, v2]) => v2 ? k : ""));
|
|
328
|
+
}
|
|
329
|
+
if (className = className.filter(Boolean).join(" "))
|
|
330
|
+
el.setAttribute("class", className);
|
|
331
|
+
else
|
|
332
|
+
el.removeAttribute("class");
|
|
314
333
|
};
|
|
315
334
|
};
|
|
316
335
|
secondary["style"] = (el, expr) => {
|
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);
|
|
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))}},g.with=(e,t,r)=>{const n=j(e,t,":with")(r);O(e,p(n,r))};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,t+1])):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.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
|
@@ -172,8 +172,14 @@ secondary['class'] = (el, expr) => {
|
|
|
172
172
|
let initClassName = el.getAttribute('class')
|
|
173
173
|
return (state) => {
|
|
174
174
|
let v = evaluate(state)
|
|
175
|
-
let className =
|
|
176
|
-
|
|
175
|
+
let className = [initClassName]
|
|
176
|
+
if (v) {
|
|
177
|
+
if (typeof v === 'string') className.push(v)
|
|
178
|
+
else if (Array.isArray(v)) className.push(...v)
|
|
179
|
+
else className.push(...Object.entries(v).map(([k,v])=>v?k:''))
|
|
180
|
+
}
|
|
181
|
+
if (className = className.filter(Boolean).join(' ')) el.setAttribute('class', className);
|
|
182
|
+
else el.removeAttribute('class')
|
|
177
183
|
}
|
|
178
184
|
}
|
|
179
185
|
|
package/src/state.js
CHANGED
|
@@ -50,6 +50,7 @@ const handler = {
|
|
|
50
50
|
},
|
|
51
51
|
|
|
52
52
|
set(target, prop, value) {
|
|
53
|
+
// "fake" prototype chain, since regular one doesn't fit
|
|
53
54
|
if (!(prop in target) && (target[_parent] && prop in target[_parent])) return target[_parent][prop] = value
|
|
54
55
|
|
|
55
56
|
// avoid bumping unchanged values
|
|
@@ -84,6 +85,16 @@ export const state = (obj, parent) => {
|
|
|
84
85
|
targetProxy.set(obj, proxy)
|
|
85
86
|
proxyTarget.set(proxy, obj)
|
|
86
87
|
|
|
88
|
+
// bind all getters here to proxy
|
|
89
|
+
// FIXME: alternatively we can store getters somewhere
|
|
90
|
+
let descriptors = Object.getOwnPropertyDescriptors(obj)
|
|
91
|
+
for (let name in descriptors) {
|
|
92
|
+
let desc = descriptors[name]
|
|
93
|
+
if (desc.get) {
|
|
94
|
+
if (desc.get) desc.get = desc.get.bind(proxy), Object.defineProperty(obj, name, desc)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
87
98
|
// inherit from parent state
|
|
88
99
|
obj[_parent] = parent ? state(parent) : sandbox
|
|
89
100
|
|
package/test/dom.js
CHANGED
|
@@ -109,6 +109,12 @@ test('class', async () => {
|
|
|
109
109
|
// is(el.outerHTML, `<x class="base x"></x><y class="y w"></y><z class="b c"></z>`);
|
|
110
110
|
})
|
|
111
111
|
|
|
112
|
+
test('class: undefined value', async () => {
|
|
113
|
+
let el = h`<x :class="a"></x><y :class="[b]"></y><z :class="{c}"></z>`
|
|
114
|
+
sprae(el, {a:undefined, b:undefined, c:undefined})
|
|
115
|
+
is(el.outerHTML, `<x></x><y></y><z></z>`)
|
|
116
|
+
})
|
|
117
|
+
|
|
112
118
|
test('class: old svg fun', async () => {
|
|
113
119
|
// raw html creates svganimatedstring
|
|
114
120
|
let el = document.createElement('div')
|
|
@@ -1015,18 +1021,25 @@ test(':: scope directives must come first', async () => {
|
|
|
1015
1021
|
is(a.outerHTML, `<x>1</x>`)
|
|
1016
1022
|
})
|
|
1017
1023
|
|
|
1018
|
-
test.
|
|
1019
|
-
let
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1024
|
+
test.todo('immediate scope', async () => {
|
|
1025
|
+
let el = h`<x :with="{arr:[], inc(){ arr.push(1) }}" :onx="e=>inc()" :text="arr[0]"></x>`
|
|
1026
|
+
sprae(el)
|
|
1027
|
+
is(el.outerHTML, `<x></x>`)
|
|
1028
|
+
el.dispatchEvent(new CustomEvent('x'))
|
|
1029
|
+
await tick()
|
|
1030
|
+
is(el.outerHTML, `<x>1</x>`)
|
|
1031
|
+
})
|
|
1032
|
+
|
|
1033
|
+
test('getters', async () => {
|
|
1034
|
+
let x = h`<h2 :text="doubledCount >= 1 ? 1 : 0"></h2>`
|
|
1025
1035
|
let state = sprae(x, {
|
|
1026
1036
|
count:0,
|
|
1027
|
-
get doubledCount(){
|
|
1028
|
-
increment(){ this.count++ }
|
|
1037
|
+
get doubledCount(){ return this.count * 2 }
|
|
1029
1038
|
})
|
|
1039
|
+
is(x.outerHTML, `<h2>0</h2>`)
|
|
1040
|
+
state.count++
|
|
1041
|
+
await tick()
|
|
1042
|
+
is(x.outerHTML, `<h2>1</h2>`)
|
|
1030
1043
|
})
|
|
1031
1044
|
|
|
1032
1045
|
test('sandbox', async () => {
|
package/todo.md
CHANGED
|
@@ -48,4 +48,6 @@
|
|
|
48
48
|
* [x] parallel chains
|
|
49
49
|
* [x] Sandbox
|
|
50
50
|
* [x] Autorun
|
|
51
|
-
* [x] There's some bug with prostogreen not triggering effect. (caused by special array.length case)
|
|
51
|
+
* [x] There's some bug with prostogreen not triggering effect. (caused by special array.length case)
|
|
52
|
+
* [x] Getters must become evaluable
|
|
53
|
+
* [ ] `:with="{likes:[], like(){ /* likes should not be undefined here */ }}"`
|