sprae 2.6.0 → 2.7.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/readme.md +17 -3
- package/sprae.js +127 -120
- package/sprae.min.js +1 -1
- package/src/core.js +27 -7
- package/src/directives.js +67 -71
- package/test/test.js +17 -0
- package/todo.md +2 -2
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -261,7 +261,21 @@ This way, for example, _@preact/signals_ or _rxjs_ can be connected directly byp
|
|
|
261
261
|
|
|
262
262
|
## Hints
|
|
263
263
|
|
|
264
|
-
**1.**
|
|
264
|
+
**1.** To batch-update state (avoid multiple DOM changes), rerun sprae with new state:
|
|
265
|
+
|
|
266
|
+
```html
|
|
267
|
+
<li :each="item, id in items" :key="id" :text="item"></li>
|
|
268
|
+
|
|
269
|
+
<script type="module">
|
|
270
|
+
sprae(el, {items: ['foo', 'bar', 'baz']})
|
|
271
|
+
// <li>foo</li><li>bar</li><li>baz</li>
|
|
272
|
+
|
|
273
|
+
sprae(el, {items: ['foo', 'qux']})
|
|
274
|
+
// <li>foo</li><li>qux</li>
|
|
275
|
+
</script>
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
**2.** Data supports signal values, which can be an alternative way to control template state:
|
|
265
279
|
|
|
266
280
|
```html
|
|
267
281
|
<div id="done" :text="loading ? 'loading' : result">...</div>
|
|
@@ -283,7 +297,7 @@ This way, for example, _@preact/signals_ or _rxjs_ can be connected directly byp
|
|
|
283
297
|
</script>
|
|
284
298
|
```
|
|
285
299
|
|
|
286
|
-
**
|
|
300
|
+
**3.** Data recognizes reactive values as inputs as well: _Promise_ / _Thenable_, _Observable_ / _Subscribable_, _AsyncIterable_ (etc., see [sube](https://github.com/dy/sube/blob/main/README.md)). This way, for example, _rxjs_ can be connected to template directly.
|
|
287
301
|
|
|
288
302
|
```html
|
|
289
303
|
<div :text="clicks">#</div> clicks
|
|
@@ -297,7 +311,7 @@ This way, for example, _@preact/signals_ or _rxjs_ can be connected directly byp
|
|
|
297
311
|
</script>
|
|
298
312
|
```
|
|
299
313
|
|
|
300
|
-
**
|
|
314
|
+
**4.** Getters turn into computed values automatically (setters remain as is):
|
|
301
315
|
|
|
302
316
|
```html
|
|
303
317
|
<div id="x-plus-y">
|
package/sprae.js
CHANGED
|
@@ -6,23 +6,23 @@ function t() {
|
|
|
6
6
|
if (!(n > 1)) {
|
|
7
7
|
var i2, t2 = false;
|
|
8
8
|
while (void 0 !== r) {
|
|
9
|
-
var
|
|
9
|
+
var h2 = r;
|
|
10
10
|
r = void 0;
|
|
11
11
|
s++;
|
|
12
|
-
while (void 0 !==
|
|
13
|
-
var o2 =
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (!(8 &
|
|
12
|
+
while (void 0 !== h2) {
|
|
13
|
+
var o2 = h2.o;
|
|
14
|
+
h2.o = void 0;
|
|
15
|
+
h2.f &= -3;
|
|
16
|
+
if (!(8 & h2.f) && d(h2))
|
|
17
17
|
try {
|
|
18
|
-
|
|
19
|
-
} catch (
|
|
18
|
+
h2.c();
|
|
19
|
+
} catch (h3) {
|
|
20
20
|
if (!t2) {
|
|
21
|
-
i2 =
|
|
21
|
+
i2 = h3;
|
|
22
22
|
t2 = true;
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
h2 = o2;
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
s = 0;
|
|
@@ -32,6 +32,16 @@ function t() {
|
|
|
32
32
|
} else
|
|
33
33
|
n--;
|
|
34
34
|
}
|
|
35
|
+
function h(i2) {
|
|
36
|
+
if (n > 0)
|
|
37
|
+
return i2();
|
|
38
|
+
n++;
|
|
39
|
+
try {
|
|
40
|
+
return i2();
|
|
41
|
+
} finally {
|
|
42
|
+
t();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
35
45
|
var o = void 0;
|
|
36
46
|
var r = void 0;
|
|
37
47
|
var n = 0;
|
|
@@ -79,25 +89,25 @@ e.prototype.S = function(i2) {
|
|
|
79
89
|
}
|
|
80
90
|
};
|
|
81
91
|
e.prototype.U = function(i2) {
|
|
82
|
-
var t2 = i2.e,
|
|
92
|
+
var t2 = i2.e, h2 = i2.x;
|
|
83
93
|
if (void 0 !== t2) {
|
|
84
|
-
t2.x =
|
|
94
|
+
t2.x = h2;
|
|
85
95
|
i2.e = void 0;
|
|
86
96
|
}
|
|
87
|
-
if (void 0 !==
|
|
88
|
-
|
|
97
|
+
if (void 0 !== h2) {
|
|
98
|
+
h2.e = t2;
|
|
89
99
|
i2.x = void 0;
|
|
90
100
|
}
|
|
91
101
|
if (i2 === this.t)
|
|
92
|
-
this.t =
|
|
102
|
+
this.t = h2;
|
|
93
103
|
};
|
|
94
104
|
e.prototype.subscribe = function(i2) {
|
|
95
105
|
var t2 = this;
|
|
96
106
|
return b(function() {
|
|
97
|
-
var
|
|
107
|
+
var h2 = t2.value, o2 = 32 & this.f;
|
|
98
108
|
this.f &= -33;
|
|
99
109
|
try {
|
|
100
|
-
i2(
|
|
110
|
+
i2(h2);
|
|
101
111
|
} finally {
|
|
102
112
|
this.f |= o2;
|
|
103
113
|
}
|
|
@@ -117,11 +127,11 @@ Object.defineProperty(e.prototype, "value", { get: function() {
|
|
|
117
127
|
if (void 0 !== i2)
|
|
118
128
|
i2.i = this.i;
|
|
119
129
|
return this.v;
|
|
120
|
-
}, set: function(
|
|
121
|
-
if (
|
|
130
|
+
}, set: function(h2) {
|
|
131
|
+
if (h2 !== this.v) {
|
|
122
132
|
if (s > 100)
|
|
123
133
|
i();
|
|
124
|
-
this.v =
|
|
134
|
+
this.v = h2;
|
|
125
135
|
this.i++;
|
|
126
136
|
f++;
|
|
127
137
|
n++;
|
|
@@ -144,33 +154,33 @@ function d(i2) {
|
|
|
144
154
|
}
|
|
145
155
|
function c(i2) {
|
|
146
156
|
for (var t2 = i2.s; void 0 !== t2; t2 = t2.n) {
|
|
147
|
-
var
|
|
148
|
-
if (void 0 !==
|
|
149
|
-
t2.r =
|
|
157
|
+
var h2 = t2.S.n;
|
|
158
|
+
if (void 0 !== h2)
|
|
159
|
+
t2.r = h2;
|
|
150
160
|
t2.S.n = t2;
|
|
151
161
|
t2.i = -1;
|
|
152
162
|
}
|
|
153
163
|
}
|
|
154
164
|
function a(i2) {
|
|
155
|
-
var t2 = i2.s,
|
|
165
|
+
var t2 = i2.s, h2 = void 0;
|
|
156
166
|
while (void 0 !== t2) {
|
|
157
167
|
var o2 = t2.n;
|
|
158
168
|
if (-1 === t2.i) {
|
|
159
169
|
t2.S.U(t2);
|
|
160
170
|
t2.n = void 0;
|
|
161
171
|
} else {
|
|
162
|
-
if (void 0 !==
|
|
163
|
-
|
|
172
|
+
if (void 0 !== h2)
|
|
173
|
+
h2.p = t2;
|
|
164
174
|
t2.p = void 0;
|
|
165
|
-
t2.n =
|
|
166
|
-
|
|
175
|
+
t2.n = h2;
|
|
176
|
+
h2 = t2;
|
|
167
177
|
}
|
|
168
178
|
t2.S.n = t2.r;
|
|
169
179
|
if (void 0 !== t2.r)
|
|
170
180
|
t2.r = void 0;
|
|
171
181
|
t2 = o2;
|
|
172
182
|
}
|
|
173
|
-
i2.s =
|
|
183
|
+
i2.s = h2;
|
|
174
184
|
}
|
|
175
185
|
function l(i2) {
|
|
176
186
|
e.call(this, void 0);
|
|
@@ -259,14 +269,14 @@ function w(i2) {
|
|
|
259
269
|
return new l(i2);
|
|
260
270
|
}
|
|
261
271
|
function y(i2) {
|
|
262
|
-
var
|
|
272
|
+
var h2 = i2.u;
|
|
263
273
|
i2.u = void 0;
|
|
264
|
-
if ("function" == typeof
|
|
274
|
+
if ("function" == typeof h2) {
|
|
265
275
|
n++;
|
|
266
276
|
var r2 = o;
|
|
267
277
|
o = void 0;
|
|
268
278
|
try {
|
|
269
|
-
|
|
279
|
+
h2();
|
|
270
280
|
} catch (t2) {
|
|
271
281
|
i2.f &= -2;
|
|
272
282
|
i2.f |= 8;
|
|
@@ -474,39 +484,13 @@ var primitive_pool_default = (key) => {
|
|
|
474
484
|
};
|
|
475
485
|
|
|
476
486
|
// src/directives.js
|
|
477
|
-
var
|
|
478
|
-
var
|
|
479
|
-
|
|
480
|
-
let evaluate = parseExpr(el, expr, ":" + name);
|
|
481
|
-
if (evaluate)
|
|
482
|
-
return evt ? (state) => {
|
|
483
|
-
let value = evaluate(state);
|
|
484
|
-
if (value) {
|
|
485
|
-
addListener(el, evt, value);
|
|
486
|
-
return () => removeListener(el, evt, value);
|
|
487
|
-
}
|
|
488
|
-
} : (state) => attr(el, name, evaluate(state));
|
|
489
|
-
};
|
|
490
|
-
var attr = (el, name, v2) => {
|
|
491
|
-
if (v2 == null || v2 === false)
|
|
492
|
-
el.removeAttribute(name);
|
|
493
|
-
else
|
|
494
|
-
el.setAttribute(name, v2 === true ? "" : typeof v2 === "number" || typeof v2 === "string" ? v2 : "");
|
|
495
|
-
};
|
|
496
|
-
directives[""] = (el, expr) => {
|
|
497
|
-
let evaluate = parseExpr(el, expr, ":");
|
|
498
|
-
if (evaluate)
|
|
499
|
-
return (state) => {
|
|
500
|
-
let value = evaluate(state);
|
|
501
|
-
for (let key in value)
|
|
502
|
-
attr(el, dashcase(key), value[key]);
|
|
503
|
-
};
|
|
504
|
-
};
|
|
505
|
-
directives["with"] = (el, expr, rootState) => {
|
|
487
|
+
var primary = {};
|
|
488
|
+
var secondary = {};
|
|
489
|
+
primary["with"] = (el, expr, rootState) => {
|
|
506
490
|
let evaluate = parseExpr(el, expr, "with");
|
|
507
491
|
sprae(el, signalStruct(evaluate(rootState), rootState));
|
|
508
492
|
};
|
|
509
|
-
|
|
493
|
+
primary["if"] = (el, expr) => {
|
|
510
494
|
let holder = document.createTextNode(""), clauses = [parseExpr(el, expr, ":if")], els = [el], cur = el;
|
|
511
495
|
while (cur = el.nextElementSibling) {
|
|
512
496
|
if (cur.hasAttribute(":else")) {
|
|
@@ -533,31 +517,14 @@ directives["if"] = (el, expr) => {
|
|
|
533
517
|
};
|
|
534
518
|
};
|
|
535
519
|
var _each = Symbol(":each");
|
|
536
|
-
|
|
537
|
-
var _key = Symbol(":key");
|
|
538
|
-
directives["ref"] = (el, expr, state) => {
|
|
539
|
-
if (el.hasAttribute(":each")) {
|
|
540
|
-
el[_ref] = expr;
|
|
541
|
-
return;
|
|
542
|
-
}
|
|
543
|
-
;
|
|
544
|
-
state[expr] = el;
|
|
545
|
-
};
|
|
546
|
-
directives["key"] = (el, expr, state) => {
|
|
547
|
-
if (el.hasAttribute(":each")) {
|
|
548
|
-
el[_key] = expr;
|
|
549
|
-
return;
|
|
550
|
-
}
|
|
551
|
-
;
|
|
552
|
-
};
|
|
553
|
-
directives["each"] = (tpl, expr) => {
|
|
520
|
+
primary["each"] = (tpl, expr) => {
|
|
554
521
|
let each = parseForExpression(expr);
|
|
555
522
|
if (!each)
|
|
556
523
|
return exprError(new Error(), tpl, expr);
|
|
557
524
|
const holder = tpl[_each] = document.createTextNode("");
|
|
558
525
|
tpl.replaceWith(holder);
|
|
559
|
-
const evaluate = parseExpr(tpl, each
|
|
560
|
-
const keyExpr = tpl
|
|
526
|
+
const evaluate = parseExpr(tpl, each[2], ":each");
|
|
527
|
+
const keyExpr = tpl.getAttribute(":key");
|
|
561
528
|
const itemKey = keyExpr ? parseExpr(null, keyExpr) : null;
|
|
562
529
|
tpl.removeAttribute(":key");
|
|
563
530
|
const scopes = /* @__PURE__ */ new WeakMap();
|
|
@@ -577,7 +544,7 @@ directives["each"] = (tpl, expr) => {
|
|
|
577
544
|
exprError(Error("Bad list value"), tpl, expr, ":each", list);
|
|
578
545
|
let newEls = [], elScopes = [];
|
|
579
546
|
for (let [idx, item] of list) {
|
|
580
|
-
let el, scope, key = itemKey?.({ [each
|
|
547
|
+
let el, scope, key = itemKey?.({ [each[0]]: item, [each[1]]: idx });
|
|
581
548
|
if (isPrimitive(key))
|
|
582
549
|
key = primitive_pool_default(key);
|
|
583
550
|
if (key == null)
|
|
@@ -586,15 +553,11 @@ directives["each"] = (tpl, expr) => {
|
|
|
586
553
|
(el = itemEls.get(key)) || itemEls.set(key, el = tpl.cloneNode(true));
|
|
587
554
|
newEls.push(el);
|
|
588
555
|
if (key == null || !(scope = scopes.get(key))) {
|
|
589
|
-
scope =
|
|
590
|
-
scope[each.item] = item;
|
|
591
|
-
if (each.index)
|
|
592
|
-
scope[each.index] = idx;
|
|
593
|
-
if (tpl[_ref])
|
|
594
|
-
scope[tpl[_ref]] = el;
|
|
556
|
+
scope = signalStruct({ [each[0]]: item, [each[1]]: idx }, state);
|
|
595
557
|
if (key != null)
|
|
596
558
|
scopes.set(key, scope);
|
|
597
|
-
}
|
|
559
|
+
} else
|
|
560
|
+
scope[each[0]] = item;
|
|
598
561
|
elScopes.push(scope);
|
|
599
562
|
}
|
|
600
563
|
swap_inflate_default(holder.parentNode, curEls, newEls, holder);
|
|
@@ -611,24 +574,26 @@ function parseForExpression(expression) {
|
|
|
611
574
|
let inMatch = expression.match(forAliasRE);
|
|
612
575
|
if (!inMatch)
|
|
613
576
|
return;
|
|
614
|
-
let
|
|
615
|
-
res.items = inMatch[2].trim();
|
|
577
|
+
let items = inMatch[2].trim();
|
|
616
578
|
let item = inMatch[1].replace(stripParensRE, "").trim();
|
|
617
579
|
let iteratorMatch = item.match(forIteratorRE);
|
|
618
|
-
if (iteratorMatch)
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
return
|
|
580
|
+
if (iteratorMatch)
|
|
581
|
+
return [
|
|
582
|
+
item.replace(forIteratorRE, "").trim(),
|
|
583
|
+
iteratorMatch[1].trim(),
|
|
584
|
+
items
|
|
585
|
+
];
|
|
586
|
+
return [item, "", items];
|
|
625
587
|
}
|
|
626
|
-
|
|
588
|
+
secondary["ref"] = (el, expr, state) => {
|
|
589
|
+
state[expr] = el;
|
|
590
|
+
};
|
|
591
|
+
secondary["id"] = (el, expr) => {
|
|
627
592
|
let evaluate = parseExpr(el, expr, ":id");
|
|
628
593
|
const update = (v2) => el.id = v2 || v2 === 0 ? v2 : "";
|
|
629
594
|
return (state) => update(evaluate(state));
|
|
630
595
|
};
|
|
631
|
-
|
|
596
|
+
secondary["class"] = (el, expr) => {
|
|
632
597
|
let evaluate = parseExpr(el, expr, ":class");
|
|
633
598
|
let initClassName = el.className;
|
|
634
599
|
return (state) => {
|
|
@@ -636,7 +601,7 @@ directives["class"] = (el, expr) => {
|
|
|
636
601
|
el.className = initClassName + typeof v2 === "string" ? v2 : (Array.isArray(v2) ? v2 : Object.entries(v2).map(([k, v3]) => v3 ? k : "")).filter(Boolean).join(" ");
|
|
637
602
|
};
|
|
638
603
|
};
|
|
639
|
-
|
|
604
|
+
secondary["style"] = (el, expr) => {
|
|
640
605
|
let evaluate = parseExpr(el, expr, ":style");
|
|
641
606
|
let initStyle = el.getAttribute("style") || "";
|
|
642
607
|
if (!initStyle.endsWith(";"))
|
|
@@ -650,14 +615,14 @@ directives["style"] = (el, expr) => {
|
|
|
650
615
|
el.style[k] = v2[k];
|
|
651
616
|
};
|
|
652
617
|
};
|
|
653
|
-
|
|
618
|
+
secondary["text"] = (el, expr) => {
|
|
654
619
|
let evaluate = parseExpr(el, expr, ":text");
|
|
655
620
|
return (state) => {
|
|
656
621
|
let value = evaluate(state);
|
|
657
622
|
el.textContent = value == null ? "" : value;
|
|
658
623
|
};
|
|
659
624
|
};
|
|
660
|
-
|
|
625
|
+
secondary["value"] = (el, expr) => {
|
|
661
626
|
let evaluate = parseExpr(el, expr, ":value");
|
|
662
627
|
let from, to;
|
|
663
628
|
let update = el.type === "text" || el.type === "" ? (value) => el.setAttribute("value", el.value = value == null ? "" : value) : el.tagName === "TEXTAREA" || el.type === "text" || el.type === "" ? (value) => (from = el.selectionStart, to = el.selectionEnd, el.setAttribute("value", el.value = value == null ? "" : value), from && el.setSelectionRange(from, to)) : el.type === "checkbox" ? (value) => (el.value = value ? "on" : "", attr(el, "checked", value)) : el.type === "select-one" ? (value) => {
|
|
@@ -668,7 +633,7 @@ directives["value"] = (el, expr) => {
|
|
|
668
633
|
} : (value) => el.value = value;
|
|
669
634
|
return (state) => update(evaluate(state));
|
|
670
635
|
};
|
|
671
|
-
|
|
636
|
+
secondary["on"] = (el, expr) => {
|
|
672
637
|
let evaluate = parseExpr(el, expr, ":on");
|
|
673
638
|
return (state) => {
|
|
674
639
|
let listeners = evaluate(state);
|
|
@@ -707,7 +672,7 @@ var removeListener = (el, evt, fn) => {
|
|
|
707
672
|
fn[_stop] = true;
|
|
708
673
|
el.removeEventListener(evt, fn);
|
|
709
674
|
};
|
|
710
|
-
|
|
675
|
+
secondary["data"] = (el, expr) => {
|
|
711
676
|
let evaluate = parseExpr(el, expr, ":data");
|
|
712
677
|
return (state) => {
|
|
713
678
|
let value = evaluate(state);
|
|
@@ -715,7 +680,7 @@ directives["data"] = (el, expr) => {
|
|
|
715
680
|
el.dataset[key] = value[key];
|
|
716
681
|
};
|
|
717
682
|
};
|
|
718
|
-
|
|
683
|
+
secondary["aria"] = (el, expr) => {
|
|
719
684
|
let evaluate = parseExpr(el, expr, ":aria");
|
|
720
685
|
const update = (value) => {
|
|
721
686
|
for (let key in value)
|
|
@@ -723,6 +688,33 @@ directives["aria"] = (el, expr) => {
|
|
|
723
688
|
};
|
|
724
689
|
return (state) => update(evaluate(state));
|
|
725
690
|
};
|
|
691
|
+
secondary[""] = (el, expr) => {
|
|
692
|
+
let evaluate = parseExpr(el, expr, ":");
|
|
693
|
+
if (evaluate)
|
|
694
|
+
return (state) => {
|
|
695
|
+
let value = evaluate(state);
|
|
696
|
+
for (let key in value)
|
|
697
|
+
attr(el, dashcase(key), value[key]);
|
|
698
|
+
};
|
|
699
|
+
};
|
|
700
|
+
var directives_default = (el, expr, values, name) => {
|
|
701
|
+
let evt = name.startsWith("on") && name.slice(2);
|
|
702
|
+
let evaluate = parseExpr(el, expr, ":" + name);
|
|
703
|
+
if (evaluate)
|
|
704
|
+
return evt ? (state) => {
|
|
705
|
+
let value = evaluate(state);
|
|
706
|
+
if (value) {
|
|
707
|
+
addListener(el, evt, value);
|
|
708
|
+
return () => removeListener(el, evt, value);
|
|
709
|
+
}
|
|
710
|
+
} : (state) => attr(el, name, evaluate(state));
|
|
711
|
+
};
|
|
712
|
+
var attr = (el, name, v2) => {
|
|
713
|
+
if (v2 == null || v2 === false)
|
|
714
|
+
el.removeAttribute(name);
|
|
715
|
+
else
|
|
716
|
+
el.setAttribute(name, v2 === true ? "" : typeof v2 === "number" || typeof v2 === "string" ? v2 : "");
|
|
717
|
+
};
|
|
726
718
|
var evaluatorMemo = {};
|
|
727
719
|
function parseExpr(el, expression, dir) {
|
|
728
720
|
let evaluate = evaluatorMemo[expression];
|
|
@@ -767,11 +759,26 @@ var memo = /* @__PURE__ */ new WeakMap();
|
|
|
767
759
|
function sprae(container, values) {
|
|
768
760
|
if (!container.children)
|
|
769
761
|
return;
|
|
770
|
-
if (memo.has(container))
|
|
771
|
-
|
|
762
|
+
if (memo.has(container)) {
|
|
763
|
+
let state2 = memo.get(container);
|
|
764
|
+
h(() => Object.assign(state2, values));
|
|
765
|
+
return state2;
|
|
766
|
+
}
|
|
772
767
|
const state = signalStruct(values || {});
|
|
773
768
|
const updates = [];
|
|
774
769
|
const init = (el, parent = el.parentNode) => {
|
|
770
|
+
for (let name in primary) {
|
|
771
|
+
let attrName = ":" + name;
|
|
772
|
+
if (el.hasAttribute?.(attrName)) {
|
|
773
|
+
let expr = el.getAttribute(attrName);
|
|
774
|
+
el.removeAttribute(attrName);
|
|
775
|
+
if (!expr)
|
|
776
|
+
continue;
|
|
777
|
+
updates.push(primary[name](el, expr, state, name));
|
|
778
|
+
if (memo.has(el) || el.parentNode !== parent)
|
|
779
|
+
return false;
|
|
780
|
+
}
|
|
781
|
+
}
|
|
775
782
|
if (el.attributes) {
|
|
776
783
|
for (let i2 = 0; i2 < el.attributes.length; ) {
|
|
777
784
|
let attr2 = el.attributes[i2];
|
|
@@ -785,9 +792,8 @@ function sprae(container, values) {
|
|
|
785
792
|
continue;
|
|
786
793
|
let attrNames = attr2.name.slice(1).split(":");
|
|
787
794
|
for (let attrName of attrNames) {
|
|
788
|
-
let dir =
|
|
789
|
-
updates.push(dir(el, expr, state, attrName)
|
|
790
|
-
}));
|
|
795
|
+
let dir = secondary[attrName] || directives_default;
|
|
796
|
+
updates.push(dir(el, expr, state, attrName));
|
|
791
797
|
if (memo.has(el) || el.parentNode !== parent)
|
|
792
798
|
return false;
|
|
793
799
|
}
|
|
@@ -799,14 +805,15 @@ function sprae(container, values) {
|
|
|
799
805
|
}
|
|
800
806
|
};
|
|
801
807
|
init(container);
|
|
802
|
-
for (let update of updates)
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
teardown
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
808
|
+
for (let update of updates)
|
|
809
|
+
if (update) {
|
|
810
|
+
let teardown;
|
|
811
|
+
b(() => {
|
|
812
|
+
if (typeof teardown === "function")
|
|
813
|
+
teardown();
|
|
814
|
+
teardown = update(state);
|
|
815
|
+
});
|
|
816
|
+
}
|
|
810
817
|
Object.seal(state);
|
|
811
818
|
memo.set(container, state);
|
|
812
819
|
return state;
|
package/sprae.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function t(){throw new Error("Cycle detected")}function e(){if(n>1)n--;else{for(var t,e=!1;void 0!==r;){var i=r;for(r=void 0,o++;void 0!==i;){var s=i.o;if(i.o=void 0,i.f&=-3,!(8&i.f)&&f(i))try{i.c()}catch(i){e||(t=i,e=!0)}i=s}}if(o=0,n--,e)throw t}}var i=void 0,r=void 0,n=0,o=0,s=0;function l(t){if(void 0!==i){var e=t.n;if(void 0===e||e.t!==i)return i.s=e={i:0,S:t,p:void 0,n:i.s,t:i,e:void 0,x:void 0,r:e},t.n=e,32&i.f&&t.S(e),e;if(-1===e.i)return e.i=0,void 0!==e.p&&(e.p.n=e.n,void 0!==e.n&&(e.n.p=e.p),e.p=void 0,e.n=i.s,i.s.p=e,i.s=e),e}}function a(t){this.v=t,this.i=0,this.n=void 0,this.t=void 0}function f(t){for(var e=t.s;void 0!==e;e=e.n)if(e.S.i!==e.i||!e.S.h()||e.S.i!==e.i)return!0;return!1}function u(t){for(var e=t.s;void 0!==e;e=e.n){var i=e.S.n;void 0!==i&&(e.r=i),e.S.n=e,e.i=-1}}function h(t){for(var e=t.s,i=void 0;void 0!==e;){var r=e.n;-1===e.i?(e.S.U(e),e.n=void 0):(void 0!==i&&(i.p=e),e.p=void 0,e.n=i,i=e),e.S.n=e.r,void 0!==e.r&&(e.r=void 0),e=r}t.s=i}function c(t){a.call(this,void 0),this.x=t,this.s=void 0,this.g=s-1,this.f=4}function v(t){var r=t.u;if(t.u=void 0,"function"==typeof r){n++;var o=i;i=void 0;try{r()}catch(e){throw t.f&=-2,t.f|=8,p(t),e}finally{i=o,e()}}}function p(t){for(var e=t.s;void 0!==e;e=e.n)e.S.U(e);t.x=void 0,t.s=void 0,v(t)}function d(t){if(i!==this)throw new Error("Out-of-order effect");h(this),i=t,this.f&=-2,8&this.f&&p(this),e()}function y(t){this.x=t,this.u=void 0,this.s=void 0,this.o=void 0,this.f=32}function b(t){var e=new y(t);return e.c(),e.d.bind(e)}a.prototype.h=function(){return!0},a.prototype.S=function(t){this.t!==t&&void 0===t.e&&(t.x=this.t,void 0!==this.t&&(this.t.e=t),this.t=t)},a.prototype.U=function(t){var e=t.e,i=t.x;void 0!==e&&(e.x=i,t.e=void 0),void 0!==i&&(i.e=e,t.x=void 0),t===this.t&&(this.t=i)},a.prototype.subscribe=function(t){var e=this;return b((function(){var i=e.value,r=32&this.f;this.f&=-33;try{t(i)}finally{this.f|=r}}))},a.prototype.valueOf=function(){return this.value},a.prototype.toString=function(){return this.value+""},a.prototype.peek=function(){return this.v},Object.defineProperty(a.prototype,"value",{get:function(){var t=l(this);return void 0!==t&&(t.i=this.i),this.v},set:function(i){if(i!==this.v){o>100&&t(),this.v=i,this.i++,s++,n++;try{for(var r=this.t;void 0!==r;r=r.x)r.t.N()}finally{e()}}}}),(c.prototype=new a).h=function(){if(this.f&=-3,1&this.f)return!1;if(32==(36&this.f))return!0;if(this.f&=-5,this.g===s)return!0;if(this.g=s,this.f|=1,this.i>0&&!f(this))return this.f&=-2,!0;var t=i;try{u(this),i=this;var e=this.x();(16&this.f||this.v!==e||0===this.i)&&(this.v=e,this.f&=-17,this.i++)}catch(t){this.v=t,this.f|=16,this.i++}return i=t,h(this),this.f&=-2,!0},c.prototype.S=function(t){if(void 0===this.t){this.f|=36;for(var e=this.s;void 0!==e;e=e.n)e.S.S(e)}a.prototype.S.call(this,t)},c.prototype.U=function(t){if(a.prototype.U.call(this,t),void 0===this.t){this.f&=-33;for(var e=this.s;void 0!==e;e=e.n)e.S.U(e)}},c.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(var t=this.t;void 0!==t;t=t.x)t.t.N()}},c.prototype.peek=function(){if(this.h()||t(),16&this.f)throw this.v;return this.v},Object.defineProperty(c.prototype,"value",{get:function(){1&this.f&&t();var e=l(this);if(this.h(),void 0!==e&&(e.i=this.i),16&this.f)throw this.v;return this.v}}),y.prototype.c=function(){var t=this.S();try{8&this.f||void 0===this.x||(this.u=this.x())}finally{t()}},y.prototype.S=function(){1&this.f&&t(),this.f|=1,this.f&=-9,v(this),u(this),n++;var e=i;return i=this,d.bind(this,e)},y.prototype.N=function(){2&this.f||(this.f|=2,this.o=r,r=this)},y.prototype.d=function(){this.f|=8,1&this.f||p(this)},Symbol.observable||=Symbol("observable");var m=new FinalizationRegistry((t=>t.call?.())),g=(t,e,i,r,n,o)=>{return t&&(s=(t[Symbol.observable]?.()||t).subscribe?.(e,i,r),o=s&&(()=>s.unsubscribe?.())||t.set&&t.call?.(n,e)||(t.then?.((t=>(!n&&e(t),r?.())),i)||(async o=>{try{for await(o of t){if(n)return;e(o)}r?.()}catch(t){i?.(t)}})())&&(t=>n=1),m.register(t,o),o);var s},S=t=>t&&t[x],x=Symbol("signal-struct");function A(t,e){if(S(t)&&!e)return t;if(w(t)){const n=Object.create(e||Object.getPrototypeOf(t)),o={},s=Object.getOwnPropertyDescriptors(t);for(let t in s){let e=s[t];if(e.get){let i=o[t]=new c(e.get.bind(n));Object.defineProperty(n,t,{get:()=>i.value,set:e.set?.bind(n),configurable:!1,enumerable:!0})}else{let s=e.value,l=(r=s)&&!!(r[Symbol.observable]||r[Symbol.asyncIterator]||r.call&&r.set||r.subscribe||r.then),f=o[t]=(i=s)&&i.peek?s:new a(l?void 0:w(s)?Object.seal(A(s)):Array.isArray(s)?A(s):s);l&&g(s,(t=>f.value=t)),Object.defineProperty(n,t,{get:()=>f.value,set(t){if(w(t)){if(w(f.value))try{return void Object.assign(f.value,t)}catch(t){}f.value=Object.seal(A(t))}else Array.isArray(t)?f.value=A(t):f.value=t},enumerable:!0,configurable:!1})}}return Object.defineProperty(n,x,{configurable:!1,enumerable:!1,value:!0}),n}var i,r;return Array.isArray(t)&&!S(t[0])?t.map((t=>A(t))):t}function w(t){return t&&t.constructor===Object}A.isStruct=S;var O=(t,e,i,r=null)=>{let n,o,s,l=0,a=i.length,f=e.length,{remove:u,same:h,insert:c,replace:v}=O;for(;l<a&&l<f&&h(e[l],i[l]);)l++;for(;l<a&&l<f&&h(i[a-1],e[f-1]);)r=i[(--f,--a)];if(l==f)for(;l<a;)c(r,i[l++],t);else{for(n=e[l];l<a;)s=i[l++],o=n?n.nextSibling:r,h(n,s)?n=o:l<a&&h(i[l],o)?(v(n,s,t),n=o):c(n,s,t);for(;!h(n,r);)o=n.nextSibling,u(n,t),n=o}return i};O.same=(t,e)=>t==e,O.replace=(t,e,i)=>i.replaceChild(e,t),O.insert=(t,e,i)=>i.insertBefore(e,t),O.remove=(t,e)=>e.removeChild(t);var j=O,N={},E={},k={},W=t=>null===t?E:void 0===t?k:"number"==typeof t||t instanceof Number?N[t]||(N[t]=new Number(t)):"string"==typeof t||t instanceof String?N[t]||(N[t]=new String(t)):"boolean"==typeof t||t instanceof Boolean?N[t]||(N[t]=new Boolean(t)):t,$={},P=(t,e,i,r)=>{let n=r.startsWith("on")&&r.slice(2),o=R(t,e,":"+r);if(o)return n?e=>{let i=o(e);if(i)return D(t,n,i),()=>_(t,n,i)}:e=>C(t,r,o(e))},C=(t,e,i)=>{null==i||!1===i?t.removeAttribute(e):t.setAttribute(e,!0===i?"":"number"==typeof i||"string"==typeof i?i:"")};$[""]=(t,e)=>{let i=R(t,e,":");if(i)return e=>{let r=i(e);for(let e in r)C(t,I(e),r[e])}},$.with=(t,e,i)=>{X(t,A(R(t,e,"with")(i),i))},$.if=(t,e)=>{let i=document.createTextNode(""),r=[R(t,e,":if")],n=[t],o=t;for(;(o=t.nextElementSibling)&&o.hasAttribute(":else");)o.removeAttribute(":else"),(e=o.getAttribute(":if"))?(o.removeAttribute(":if"),o.remove(),n.push(o),r.push(R(t,e,":else :if"))):(o.remove(),n.push(o),r.push((()=>1)));return t.replaceWith(o=i),t=>{let e=r.findIndex((e=>e(t)));n[e]!=o&&((o[U]||o).replaceWith(o=n[e]||i),X(o,t))}};var U=Symbol(":each"),B=Symbol(":ref"),L=Symbol(":key");$.ref=(t,e,i)=>{t.hasAttribute(":each")?t[B]=e:i[e]=t},$.key=(t,e,i)=>{t.hasAttribute(":each")&&(t[L]=e)},$.each=(t,e)=>{let i=function(t){let e=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,i=t.match(/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/);if(!i)return;let r={};r.items=i[2].trim();let n=i[1].replace(/^\s*\(|\)\s*$/g,"").trim(),o=n.match(e);return o?(r.item=n.replace(e,"").trim(),r.index=o[1].trim()):r.item=n,r}(e);if(!i)return F(new Error,t,e);const r=t[U]=document.createTextNode("");t.replaceWith(r);const n=R(t,i.items,":each"),o=t[L]||t.getAttribute(":key"),s=o?R(null,o):null;t.removeAttribute(":key");const l=new WeakMap,a=new WeakMap;let f=[];return o=>{let u=n(o);u?"number"==typeof u?u=Array.from({length:u},((t,e)=>[e,e+1])):Array.isArray(u)?u=u.map(((t,e)=>[e+1,t])):"object"==typeof u?u=Object.entries(u):F(Error("Bad list value"),t,e,":each"):u=[];let h=[],c=[];for(let[e,r]of u){let n,f,u=s?.({[i.item]:r});("string"==typeof(v=u)||"boolean"==typeof v||"number"==typeof v)&&(u=W(u)),null==u?n=t.cloneNode(!0):(n=a.get(u))||a.set(u,n=t.cloneNode(!0)),h.push(n),null!=u&&(f=l.get(u))||(f=Object.create(o),f[i.item]=r,i.index&&(f[i.index]=e),t[B]&&(f[t[B]]=n),null!=u&&l.set(u,f)),c.push(f)}var v;j(r.parentNode,f,h,r),f=h;for(let t=0;t<h.length;t++)X(h[t],c[t])}},$.id=(t,e)=>{let i=R(t,e,":id");return e=>{return r=i(e),t.id=r||0===r?r:"";var r}},$.class=(t,e)=>{let i=R(t,e,":class"),r=t.className;return e=>{let n=i(e);t.className=r+typeof n=="string"?n:(Array.isArray(n)?n:Object.entries(n).map((([t,e])=>e?t:""))).filter(Boolean).join(" ")}},$.style=(t,e)=>{let i=R(t,e,":style"),r=t.getAttribute("style")||"";return r.endsWith(";")||(r+="; "),e=>{let n=i(e);if("string"==typeof n)t.setAttribute("style",r+n);else for(let e in n)t.style[e]=n[e]}},$.text=(t,e)=>{let i=R(t,e,":text");return e=>{let r=i(e);t.textContent=null==r?"":r}},$.value=(t,e)=>{let i,r,n=R(t,e,":value"),o="text"===t.type||""===t.type?e=>t.setAttribute("value",t.value=null==e?"":e):"TEXTAREA"===t.tagName||"text"===t.type||""===t.type?e=>(i=t.selectionStart,r=t.selectionEnd,t.setAttribute("value",t.value=null==e?"":e),i&&t.setSelectionRange(i,r)):"checkbox"===t.type?e=>(t.value=e?"on":"",C(t,"checked",e)):"select-one"===t.type?e=>{for(let e in t.options)e.removeAttribute("selected");t.value=e,t.selectedOptions[0]?.setAttribute("selected","")}:e=>t.value=e;return t=>o(n(t))},$.on=(t,e)=>{let i=R(t,e,":on");return e=>{let r=i(e);for(let e in r)D(t,e,r[e]);return()=>{for(let e in r)_(t,e,r[e])}}};var T=Symbol("stop"),D=(t,e,i)=>{if(e.indexOf("..")<0)t.addEventListener(e,i);else{const r=e.split("..").map((t=>t.startsWith("on")?t.slice(2):t)),n=(e,o=0)=>{let s=l=>{t.removeEventListener(r[o],s),"function"!=typeof(e=e.call(t,l))&&(e=()=>{}),++o<r.length?n(e,o):i[T]||n(i)};t.addEventListener(r[o],s)};n(i)}},_=(t,e,i)=>{e.indexOf("..")>=0&&(i[T]=!0),t.removeEventListener(e,i)};$.data=(t,e)=>{let i=R(t,e,":data");return e=>{let r=i(e);for(let e in r)t.dataset[e]=r[e]}},$.aria=(t,e)=>{let i=R(t,e,":aria");return e=>(e=>{for(let i in e)C(t,"aria-"+I(i),null==e[i]?null:e[i]+"")})(i(e))};var M={};function R(t,e,i){let r=M[e];if(!r){let n=/^[\n\s]*if.*\(.*\)/.test(e)||/^(let|const)\s/.test(e)?`(() => { ${e} })()`:e;try{r=M[e]=new Function("__scope",`with (__scope) { return ${n} };`)}catch(r){return F(r,t,e,i)}}return n=>{let o;try{o=r.call(t,n)}catch(r){return F(r,t,e,i)}return o}}function F(t,e,i,r){Object.assign(t,{element:e,expression:i}),console.warn(`∴ ${t.message}\n\n${r}=${i?`"${i}"\n\n`:""}`,e),setTimeout((()=>{throw t}),0)}function I(t){return t.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(t=>"-"+t.toLowerCase()))}var z=new WeakMap;function X(t,e){if(!t.children)return;if(z.has(t))return z.get(t);const i=A(e||{}),r=[],n=(t,e=t.parentNode)=>{if(t.attributes)for(let n=0;n<t.attributes.length;){let o=t.attributes[n];if(":"!==o.name[0]){n++;continue}t.removeAttribute(o.name);let s=o.value;if(!s)continue;let l=o.name.slice(1).split(":");for(let n of l){let o=$[n]||P;if(r.push(o(t,s,i,n)||(()=>{})),z.has(t)||t.parentNode!==e)return!1}}for(let e,i=0;e=t.children[i];i++)!1===n(e,t)&&i--};n(t);for(let t of r){let e;b((()=>{"function"==typeof e&&e(),e=t(i)}))}return Object.seal(i),z.set(t,i),i}var Z=X;export{Z as default};
|
|
1
|
+
function t(){throw new Error("Cycle detected")}function e(){if(n>1)n--;else{for(var t,e=!1;void 0!==r;){var i=r;for(r=void 0,o++;void 0!==i;){var s=i.o;if(i.o=void 0,i.f&=-3,!(8&i.f)&&u(i))try{i.c()}catch(i){e||(t=i,e=!0)}i=s}}if(o=0,n--,e)throw t}}var i=void 0,r=void 0,n=0,o=0,s=0;function l(t){if(void 0!==i){var e=t.n;if(void 0===e||e.t!==i)return i.s=e={i:0,S:t,p:void 0,n:i.s,t:i,e:void 0,x:void 0,r:e},t.n=e,32&i.f&&t.S(e),e;if(-1===e.i)return e.i=0,void 0!==e.p&&(e.p.n=e.n,void 0!==e.n&&(e.n.p=e.p),e.p=void 0,e.n=i.s,i.s.p=e,i.s=e),e}}function f(t){this.v=t,this.i=0,this.n=void 0,this.t=void 0}function u(t){for(var e=t.s;void 0!==e;e=e.n)if(e.S.i!==e.i||!e.S.h()||e.S.i!==e.i)return!0;return!1}function a(t){for(var e=t.s;void 0!==e;e=e.n){var i=e.S.n;void 0!==i&&(e.r=i),e.S.n=e,e.i=-1}}function h(t){for(var e=t.s,i=void 0;void 0!==e;){var r=e.n;-1===e.i?(e.S.U(e),e.n=void 0):(void 0!==i&&(i.p=e),e.p=void 0,e.n=i,i=e),e.S.n=e.r,void 0!==e.r&&(e.r=void 0),e=r}t.s=i}function c(t){f.call(this,void 0),this.x=t,this.s=void 0,this.g=s-1,this.f=4}function v(t){var r=t.u;if(t.u=void 0,"function"==typeof r){n++;var o=i;i=void 0;try{r()}catch(e){throw t.f&=-2,t.f|=8,p(t),e}finally{i=o,e()}}}function p(t){for(var e=t.s;void 0!==e;e=e.n)e.S.U(e);t.x=void 0,t.s=void 0,v(t)}function d(t){if(i!==this)throw new Error("Out-of-order effect");h(this),i=t,this.f&=-2,8&this.f&&p(this),e()}function y(t){this.x=t,this.u=void 0,this.s=void 0,this.o=void 0,this.f=32}function b(t){var e=new y(t);return e.c(),e.d.bind(e)}f.prototype.h=function(){return!0},f.prototype.S=function(t){this.t!==t&&void 0===t.e&&(t.x=this.t,void 0!==this.t&&(this.t.e=t),this.t=t)},f.prototype.U=function(t){var e=t.e,i=t.x;void 0!==e&&(e.x=i,t.e=void 0),void 0!==i&&(i.e=e,t.x=void 0),t===this.t&&(this.t=i)},f.prototype.subscribe=function(t){var e=this;return b((function(){var i=e.value,r=32&this.f;this.f&=-33;try{t(i)}finally{this.f|=r}}))},f.prototype.valueOf=function(){return this.value},f.prototype.toString=function(){return this.value+""},f.prototype.peek=function(){return this.v},Object.defineProperty(f.prototype,"value",{get:function(){var t=l(this);return void 0!==t&&(t.i=this.i),this.v},set:function(i){if(i!==this.v){o>100&&t(),this.v=i,this.i++,s++,n++;try{for(var r=this.t;void 0!==r;r=r.x)r.t.N()}finally{e()}}}}),(c.prototype=new f).h=function(){if(this.f&=-3,1&this.f)return!1;if(32==(36&this.f))return!0;if(this.f&=-5,this.g===s)return!0;if(this.g=s,this.f|=1,this.i>0&&!u(this))return this.f&=-2,!0;var t=i;try{a(this),i=this;var e=this.x();(16&this.f||this.v!==e||0===this.i)&&(this.v=e,this.f&=-17,this.i++)}catch(t){this.v=t,this.f|=16,this.i++}return i=t,h(this),this.f&=-2,!0},c.prototype.S=function(t){if(void 0===this.t){this.f|=36;for(var e=this.s;void 0!==e;e=e.n)e.S.S(e)}f.prototype.S.call(this,t)},c.prototype.U=function(t){if(f.prototype.U.call(this,t),void 0===this.t){this.f&=-33;for(var e=this.s;void 0!==e;e=e.n)e.S.U(e)}},c.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(var t=this.t;void 0!==t;t=t.x)t.t.N()}},c.prototype.peek=function(){if(this.h()||t(),16&this.f)throw this.v;return this.v},Object.defineProperty(c.prototype,"value",{get:function(){1&this.f&&t();var e=l(this);if(this.h(),void 0!==e&&(e.i=this.i),16&this.f)throw this.v;return this.v}}),y.prototype.c=function(){var t=this.S();try{8&this.f||void 0===this.x||(this.u=this.x())}finally{t()}},y.prototype.S=function(){1&this.f&&t(),this.f|=1,this.f&=-9,v(this),a(this),n++;var e=i;return i=this,d.bind(this,e)},y.prototype.N=function(){2&this.f||(this.f|=2,this.o=r,r=this)},y.prototype.d=function(){this.f|=8,1&this.f||p(this)},Symbol.observable||=Symbol("observable");var m=new FinalizationRegistry((t=>t.call?.())),g=(t,e,i,r,n,o)=>{return t&&(s=(t[Symbol.observable]?.()||t).subscribe?.(e,i,r),o=s&&(()=>s.unsubscribe?.())||t.set&&t.call?.(n,e)||(t.then?.((t=>(!n&&e(t),r?.())),i)||(async o=>{try{for await(o of t){if(n)return;e(o)}r?.()}catch(t){i?.(t)}})())&&(t=>n=1),m.register(t,o),o);var s},S=t=>t&&t[A],A=Symbol("signal-struct");function w(t,e){if(S(t)&&!e)return t;if(x(t)){const n=Object.create(e||Object.getPrototypeOf(t)),o={},s=Object.getOwnPropertyDescriptors(t);for(let t in s){let e=s[t];if(e.get){let i=o[t]=new c(e.get.bind(n));Object.defineProperty(n,t,{get:()=>i.value,set:e.set?.bind(n),configurable:!1,enumerable:!0})}else{let s=e.value,l=(r=s)&&!!(r[Symbol.observable]||r[Symbol.asyncIterator]||r.call&&r.set||r.subscribe||r.then),u=o[t]=(i=s)&&i.peek?s:new f(l?void 0:x(s)?Object.seal(w(s)):Array.isArray(s)?w(s):s);l&&g(s,(t=>u.value=t)),Object.defineProperty(n,t,{get:()=>u.value,set(t){if(x(t)){if(x(u.value))try{return void Object.assign(u.value,t)}catch(t){}u.value=Object.seal(w(t))}else Array.isArray(t)?u.value=w(t):u.value=t},enumerable:!0,configurable:!1})}}return Object.defineProperty(n,A,{configurable:!1,enumerable:!1,value:!0}),n}var i,r;return Array.isArray(t)&&!S(t[0])?t.map((t=>w(t))):t}function x(t){return t&&t.constructor===Object}w.isStruct=S;var O=(t,e,i,r=null)=>{let n,o,s,l=0,f=i.length,u=e.length,{remove:a,same:h,insert:c,replace:v}=O;for(;l<f&&l<u&&h(e[l],i[l]);)l++;for(;l<f&&l<u&&h(i[f-1],e[u-1]);)r=i[(--u,--f)];if(l==u)for(;l<f;)c(r,i[l++],t);else{for(n=e[l];l<f;)s=i[l++],o=n?n.nextSibling:r,h(n,s)?n=o:l<f&&h(i[l],o)?(v(n,s,t),n=o):c(n,s,t);for(;!h(n,r);)o=n.nextSibling,a(n,t),n=o}return i};O.same=(t,e)=>t==e,O.replace=(t,e,i)=>i.replaceChild(e,t),O.insert=(t,e,i)=>i.insertBefore(e,t),O.remove=(t,e)=>e.removeChild(t);var j=O,N={},E={},k={},W=t=>null===t?E:void 0===t?k:"number"==typeof t||t instanceof Number?N[t]||(N[t]=new Number(t)):"string"==typeof t||t instanceof String?N[t]||(N[t]=new String(t)):"boolean"==typeof t||t instanceof Boolean?N[t]||(N[t]=new Boolean(t)):t,$={},P={};$.with=(t,e,i)=>{z(t,w(M(t,e,"with")(i),i))},$.if=(t,e)=>{let i=document.createTextNode(""),r=[M(t,e,":if")],n=[t],o=t;for(;(o=t.nextElementSibling)&&o.hasAttribute(":else");)o.removeAttribute(":else"),(e=o.getAttribute(":if"))?(o.removeAttribute(":if"),o.remove(),n.push(o),r.push(M(t,e,":else :if"))):(o.remove(),n.push(o),r.push((()=>1)));return t.replaceWith(o=i),t=>{let e=r.findIndex((e=>e(t)));n[e]!=o&&((o[C]||o).replaceWith(o=n[e]||i),z(o,t))}};var C=Symbol(":each");$.each=(t,e)=>{let i=function(t){let e=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,i=t.match(/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/);if(!i)return;let r=i[2].trim(),n=i[1].replace(/^\s*\(|\)\s*$/g,"").trim(),o=n.match(e);return o?[n.replace(e,"").trim(),o[1].trim(),r]:[n,"",r]}(e);if(!i)return R(new Error,t,e);const r=t[C]=document.createTextNode("");t.replaceWith(r);const n=M(t,i[2],":each"),o=t.getAttribute(":key"),s=o?M(null,o):null;t.removeAttribute(":key");const l=new WeakMap,f=new WeakMap;let u=[];return o=>{let a=n(o);a?"number"==typeof a?a=Array.from({length:a},((t,e)=>[e,e+1])):Array.isArray(a)?a=a.map(((t,e)=>[e+1,t])):"object"==typeof a?a=Object.entries(a):R(Error("Bad list value"),t,e,":each"):a=[];let h=[],c=[];for(let[e,r]of a){let n,u,a=s?.({[i[0]]:r,[i[1]]:e});("string"==typeof(v=a)||"boolean"==typeof v||"number"==typeof v)&&(a=W(a)),null==a?n=t.cloneNode(!0):(n=f.get(a))||f.set(a,n=t.cloneNode(!0)),h.push(n),null!=a&&(u=l.get(a))?u[i[0]]=r:(u=w({[i[0]]:r,[i[1]]:e},o),null!=a&&l.set(a,u)),c.push(u)}var v;j(r.parentNode,u,h,r),u=h;for(let t=0;t<h.length;t++)z(h[t],c[t])}},P.ref=(t,e,i)=>{i[e]=t},P.id=(t,e)=>{let i=M(t,e,":id");return e=>{return r=i(e),t.id=r||0===r?r:"";var r}},P.class=(t,e)=>{let i=M(t,e,":class"),r=t.className;return e=>{let n=i(e);t.className=r+typeof n=="string"?n:(Array.isArray(n)?n:Object.entries(n).map((([t,e])=>e?t:""))).filter(Boolean).join(" ")}},P.style=(t,e)=>{let i=M(t,e,":style"),r=t.getAttribute("style")||"";return r.endsWith(";")||(r+="; "),e=>{let n=i(e);if("string"==typeof n)t.setAttribute("style",r+n);else for(let e in n)t.style[e]=n[e]}},P.text=(t,e)=>{let i=M(t,e,":text");return e=>{let r=i(e);t.textContent=null==r?"":r}},P.value=(t,e)=>{let i,r,n=M(t,e,":value"),o="text"===t.type||""===t.type?e=>t.setAttribute("value",t.value=null==e?"":e):"TEXTAREA"===t.tagName||"text"===t.type||""===t.type?e=>(i=t.selectionStart,r=t.selectionEnd,t.setAttribute("value",t.value=null==e?"":e),i&&t.setSelectionRange(i,r)):"checkbox"===t.type?e=>(t.value=e?"on":"",D(t,"checked",e)):"select-one"===t.type?e=>{for(let e in t.options)e.removeAttribute("selected");t.value=e,t.selectedOptions[0]?.setAttribute("selected","")}:e=>t.value=e;return t=>o(n(t))},P.on=(t,e)=>{let i=M(t,e,":on");return e=>{let r=i(e);for(let e in r)B(t,e,r[e]);return()=>{for(let e in r)L(t,e,r[e])}}};var U=Symbol("stop"),B=(t,e,i)=>{if(e.indexOf("..")<0)t.addEventListener(e,i);else{const r=e.split("..").map((t=>t.startsWith("on")?t.slice(2):t)),n=(e,o=0)=>{let s=l=>{t.removeEventListener(r[o],s),"function"!=typeof(e=e.call(t,l))&&(e=()=>{}),++o<r.length?n(e,o):i[U]||n(i)};t.addEventListener(r[o],s)};n(i)}},L=(t,e,i)=>{e.indexOf("..")>=0&&(i[U]=!0),t.removeEventListener(e,i)};P.data=(t,e)=>{let i=M(t,e,":data");return e=>{let r=i(e);for(let e in r)t.dataset[e]=r[e]}},P.aria=(t,e)=>{let i=M(t,e,":aria");return e=>(e=>{for(let i in e)D(t,"aria-"+F(i),null==e[i]?null:e[i]+"")})(i(e))},P[""]=(t,e)=>{let i=M(t,e,":");if(i)return e=>{let r=i(e);for(let e in r)D(t,F(e),r[e])}};var T=(t,e,i,r)=>{let n=r.startsWith("on")&&r.slice(2),o=M(t,e,":"+r);if(o)return n?e=>{let i=o(e);if(i)return B(t,n,i),()=>L(t,n,i)}:e=>D(t,r,o(e))},D=(t,e,i)=>{null==i||!1===i?t.removeAttribute(e):t.setAttribute(e,!0===i?"":"number"==typeof i||"string"==typeof i?i:"")},_={};function M(t,e,i){let r=_[e];if(!r){let n=/^[\n\s]*if.*\(.*\)/.test(e)||/^(let|const)\s/.test(e)?`(() => { ${e} })()`:e;try{r=_[e]=new Function("__scope",`with (__scope) { return ${n} };`)}catch(r){return R(r,t,e,i)}}return n=>{let o;try{o=r.call(t,n)}catch(r){return R(r,t,e,i)}return o}}function R(t,e,i,r){Object.assign(t,{element:e,expression:i}),console.warn(`∴ ${t.message}\n\n${r}=${i?`"${i}"\n\n`:""}`,e),setTimeout((()=>{throw t}),0)}function F(t){return t.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(t=>"-"+t.toLowerCase()))}var I=new WeakMap;function z(t,i){if(!t.children)return;if(I.has(t)){let r=I.get(t);return function(t){if(n>0)return t();n++;try{t()}finally{e()}}((()=>Object.assign(r,i))),r}const r=w(i||{}),o=[],s=(t,e=t.parentNode)=>{for(let i in $){let n=":"+i;if(t.hasAttribute?.(n)){let s=t.getAttribute(n);if(t.removeAttribute(n),!s)continue;if(o.push($[i](t,s,r,i)),I.has(t)||t.parentNode!==e)return!1}}if(t.attributes)for(let i=0;i<t.attributes.length;){let n=t.attributes[i];if(":"!==n.name[0]){i++;continue}t.removeAttribute(n.name);let s=n.value;if(!s)continue;let l=n.name.slice(1).split(":");for(let i of l){let n=P[i]||T;if(o.push(n(t,s,r,i)),I.has(t)||t.parentNode!==e)return!1}}for(let e,i=0;e=t.children[i];i++)!1===s(e,t)&&i--};s(t);for(let t of o)if(t){let e;b((()=>{"function"==typeof e&&e(),e=t(r)}))}return Object.seal(r),I.set(t,r),r}var X=z;export{X as default};
|
package/src/core.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import signalStruct from 'signal-struct';
|
|
2
|
-
import defaultDirective, {
|
|
3
|
-
import { effect } from '@preact/signals-core'
|
|
2
|
+
import defaultDirective, { primary, secondary } from './directives.js';
|
|
3
|
+
import { effect, batch } from '@preact/signals-core'
|
|
4
4
|
|
|
5
5
|
// sprae element: apply directives
|
|
6
6
|
const memo = new WeakMap
|
|
7
7
|
export default function sprae(container, values) {
|
|
8
8
|
if (!container.children) return
|
|
9
|
-
if (memo.has(container))
|
|
9
|
+
if (memo.has(container)) {
|
|
10
|
+
let state = memo.get(container)
|
|
11
|
+
batch(() => Object.assign(state, values))
|
|
12
|
+
return state
|
|
13
|
+
}
|
|
10
14
|
|
|
11
15
|
// signalStruct returns values if it's signalStruct already
|
|
12
16
|
const state = signalStruct(values || {});
|
|
@@ -14,6 +18,21 @@ export default function sprae(container, values) {
|
|
|
14
18
|
|
|
15
19
|
// init directives on element
|
|
16
20
|
const init = (el, parent=el.parentNode) => {
|
|
21
|
+
// init primary attributes first
|
|
22
|
+
for (let name in primary) {
|
|
23
|
+
let attrName = ':' + name
|
|
24
|
+
if (el.hasAttribute?.(attrName)) {
|
|
25
|
+
let expr = el.getAttribute(attrName)
|
|
26
|
+
el.removeAttribute(attrName)
|
|
27
|
+
if (!expr) continue
|
|
28
|
+
updates.push(primary[name](el, expr, state, name))
|
|
29
|
+
|
|
30
|
+
// stop if element was spraed by directive or skipped (detached)
|
|
31
|
+
if (memo.has(el) || el.parentNode !== parent) return false
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// catch other attributes as secondary
|
|
17
36
|
if (el.attributes) {
|
|
18
37
|
for (let i = 0; i < el.attributes.length;) {
|
|
19
38
|
let attr = el.attributes[i]
|
|
@@ -21,12 +40,13 @@ export default function sprae(container, values) {
|
|
|
21
40
|
el.removeAttribute(attr.name)
|
|
22
41
|
let expr = attr.value
|
|
23
42
|
if (!expr) continue
|
|
43
|
+
// multiple attributes like :id:for=""
|
|
24
44
|
let attrNames = attr.name.slice(1).split(':')
|
|
25
45
|
for (let attrName of attrNames) {
|
|
26
|
-
let dir =
|
|
27
|
-
updates.push(dir(el, expr, state, attrName)
|
|
46
|
+
let dir = secondary[attrName] || defaultDirective;
|
|
47
|
+
updates.push(dir(el, expr, state, attrName));
|
|
28
48
|
|
|
29
|
-
// stop if element was spraed by directive or skipped
|
|
49
|
+
// stop if element was spraed by directive or skipped (detached)
|
|
30
50
|
if (memo.has(el) || el.parentNode !== parent) return false
|
|
31
51
|
}
|
|
32
52
|
}
|
|
@@ -42,7 +62,7 @@ export default function sprae(container, values) {
|
|
|
42
62
|
|
|
43
63
|
// call updates: subscribes directives to state;
|
|
44
64
|
// state is created after inits because directives can extend init values (expose refs etc)
|
|
45
|
-
for (let update of updates) {
|
|
65
|
+
for (let update of updates) if (update) {
|
|
46
66
|
let teardown
|
|
47
67
|
effect(() => {
|
|
48
68
|
if (typeof teardown === 'function') teardown()
|
package/src/directives.js
CHANGED
|
@@ -5,42 +5,18 @@ import signalStruct from 'signal-struct'
|
|
|
5
5
|
import p from 'primitive-pool'
|
|
6
6
|
|
|
7
7
|
// reserved directives - order matters!
|
|
8
|
-
|
|
8
|
+
// primary initialized first by selector, secondary initialized by iterating attributes
|
|
9
|
+
export const primary = {}, secondary = {}
|
|
9
10
|
|
|
10
|
-
// any-prop directives
|
|
11
|
-
export default (el, expr, values, name) => {
|
|
12
|
-
let evt = name.startsWith('on') && name.slice(2)
|
|
13
|
-
let evaluate = parseExpr(el, expr, ':'+name)
|
|
14
|
-
if (evaluate) return evt ? state => {
|
|
15
|
-
let value = evaluate(state)
|
|
16
|
-
if (value) {
|
|
17
|
-
addListener(el, evt, value)
|
|
18
|
-
return () => removeListener(el, evt, value)
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
: state => attr(el, name, evaluate(state))
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// set attr
|
|
25
|
-
const attr = (el, name, v) => {
|
|
26
|
-
if (v == null || v === false) el.removeAttribute(name)
|
|
27
|
-
else el.setAttribute(name, v === true ? '' : (typeof v === 'number' || typeof v === 'string') ? v : '')
|
|
28
|
-
}
|
|
29
11
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (evaluate) return (state) => {
|
|
33
|
-
let value = evaluate(state)
|
|
34
|
-
for (let key in value) attr(el, dashcase(key), value[key]);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
directives['with'] = (el, expr, rootState) => {
|
|
12
|
+
// :with must come before :if or :each or anyone else
|
|
13
|
+
primary['with'] = (el, expr, rootState) => {
|
|
39
14
|
let evaluate = parseExpr(el, expr, 'with')
|
|
40
15
|
sprae(el, signalStruct(evaluate(rootState), rootState));
|
|
41
16
|
}
|
|
42
17
|
|
|
43
|
-
|
|
18
|
+
// :if is interchangeable with :each depending on order, :if :each or :each :if have different meanings
|
|
19
|
+
primary['if'] = (el, expr) => {
|
|
44
20
|
let holder = document.createTextNode(''),
|
|
45
21
|
clauses = [parseExpr(el, expr, ':if')],
|
|
46
22
|
els = [el], cur = el
|
|
@@ -71,23 +47,10 @@ directives['if'] = (el, expr) => {
|
|
|
71
47
|
}
|
|
72
48
|
}
|
|
73
49
|
|
|
74
|
-
const _each = Symbol(':each')
|
|
75
|
-
|
|
76
|
-
directives['ref'] = (el, expr, state) => {
|
|
77
|
-
// make sure :ref is initialized after :each (return to avoid initializing as signal)
|
|
78
|
-
if (el.hasAttribute(':each')) {el[_ref] = expr; return};
|
|
50
|
+
const _each = Symbol(':each')
|
|
79
51
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
state[expr] = el;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
directives['key'] = (el, expr, state) => {
|
|
86
|
-
// make sure :ref is initialized after :each (return to avoid initializing as signal)
|
|
87
|
-
if (el.hasAttribute(':each')) {el[_key] = expr; return};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
directives['each'] = (tpl, expr) => {
|
|
52
|
+
// :each must init before :ref, :id or any others, since it defines scope
|
|
53
|
+
primary['each'] = (tpl, expr) => {
|
|
91
54
|
let each = parseForExpression(expr);
|
|
92
55
|
if (!each) return exprError(new Error, tpl, expr);
|
|
93
56
|
|
|
@@ -96,9 +59,9 @@ directives['each'] = (tpl, expr) => {
|
|
|
96
59
|
const holder = tpl[_each] = document.createTextNode('')
|
|
97
60
|
tpl.replaceWith(holder)
|
|
98
61
|
|
|
99
|
-
const evaluate = parseExpr(tpl, each
|
|
62
|
+
const evaluate = parseExpr(tpl, each[2], ':each');
|
|
100
63
|
|
|
101
|
-
const keyExpr = tpl
|
|
64
|
+
const keyExpr = tpl.getAttribute(':key');
|
|
102
65
|
const itemKey = keyExpr ? parseExpr(null, keyExpr) : null;
|
|
103
66
|
tpl.removeAttribute(':key')
|
|
104
67
|
|
|
@@ -121,7 +84,7 @@ directives['each'] = (tpl, expr) => {
|
|
|
121
84
|
let newEls = [], elScopes = []
|
|
122
85
|
|
|
123
86
|
for (let [idx, item] of list) {
|
|
124
|
-
let el, scope, key = itemKey?.({[each
|
|
87
|
+
let el, scope, key = itemKey?.({[each[0]]: item, [each[1]]: idx})
|
|
125
88
|
if (isPrimitive(key)) key = p(key); // singletonize key
|
|
126
89
|
|
|
127
90
|
// we consider if data items are primitive, then nodes needn't be cached
|
|
@@ -132,13 +95,12 @@ directives['each'] = (tpl, expr) => {
|
|
|
132
95
|
newEls.push(el)
|
|
133
96
|
|
|
134
97
|
if (key == null || !(scope = scopes.get(key))) {
|
|
135
|
-
scope =
|
|
136
|
-
scope[each.item] = item
|
|
137
|
-
if (each.index) scope[each.index] = idx;
|
|
138
|
-
// provide ref, if indicated
|
|
139
|
-
if (tpl[_ref]) scope[tpl[_ref]] = el
|
|
98
|
+
scope = signalStruct({[each[0]]: item, [each[1]]:idx}, state)
|
|
140
99
|
if (key != null) scopes.set(key, scope)
|
|
141
100
|
}
|
|
101
|
+
// need to explicitly set item to update existing children's values
|
|
102
|
+
else scope[each[0]] = item
|
|
103
|
+
|
|
142
104
|
elScopes.push(scope)
|
|
143
105
|
}
|
|
144
106
|
|
|
@@ -162,28 +124,33 @@ function parseForExpression(expression) {
|
|
|
162
124
|
|
|
163
125
|
if (!inMatch) return
|
|
164
126
|
|
|
165
|
-
let
|
|
166
|
-
res.items = inMatch[2].trim()
|
|
127
|
+
let items = inMatch[2].trim()
|
|
167
128
|
let item = inMatch[1].replace(stripParensRE, '').trim()
|
|
168
129
|
let iteratorMatch = item.match(forIteratorRE)
|
|
169
130
|
|
|
170
|
-
if (iteratorMatch)
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
131
|
+
if (iteratorMatch) return [
|
|
132
|
+
item.replace(forIteratorRE, '').trim(),
|
|
133
|
+
iteratorMatch[1].trim(),
|
|
134
|
+
items
|
|
135
|
+
]
|
|
176
136
|
|
|
177
|
-
return
|
|
137
|
+
return [item, '', items]
|
|
178
138
|
}
|
|
179
139
|
|
|
180
|
-
|
|
140
|
+
|
|
141
|
+
secondary['ref'] = (el, expr, state) => {
|
|
142
|
+
// FIXME: wait for complex ref use-case
|
|
143
|
+
// parseExpr(el, `__scope[${expr}]=this`, ':ref')(values)
|
|
144
|
+
state[expr] = el;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
secondary['id'] = (el, expr) => {
|
|
181
148
|
let evaluate = parseExpr(el, expr, ':id')
|
|
182
149
|
const update = v => el.id = v || v === 0 ? v : ''
|
|
183
150
|
return (state) => update(evaluate(state))
|
|
184
151
|
}
|
|
185
152
|
|
|
186
|
-
|
|
153
|
+
secondary['class'] = (el, expr) => {
|
|
187
154
|
let evaluate = parseExpr(el, expr, ':class')
|
|
188
155
|
let initClassName = el.className
|
|
189
156
|
return (state) => {
|
|
@@ -192,7 +159,7 @@ directives['class'] = (el, expr) => {
|
|
|
192
159
|
}
|
|
193
160
|
}
|
|
194
161
|
|
|
195
|
-
|
|
162
|
+
secondary['style'] = (el, expr) => {
|
|
196
163
|
let evaluate = parseExpr(el, expr, ':style')
|
|
197
164
|
let initStyle = el.getAttribute('style') || ''
|
|
198
165
|
if (!initStyle.endsWith(';')) initStyle += '; '
|
|
@@ -203,7 +170,7 @@ directives['style'] = (el, expr) => {
|
|
|
203
170
|
}
|
|
204
171
|
}
|
|
205
172
|
|
|
206
|
-
|
|
173
|
+
secondary['text'] = (el, expr) => {
|
|
207
174
|
let evaluate = parseExpr(el, expr, ':text')
|
|
208
175
|
|
|
209
176
|
return (state) => {
|
|
@@ -213,7 +180,7 @@ directives['text'] = (el, expr) => {
|
|
|
213
180
|
}
|
|
214
181
|
|
|
215
182
|
// connect expr to element value
|
|
216
|
-
|
|
183
|
+
secondary['value'] = (el, expr) => {
|
|
217
184
|
let evaluate = parseExpr(el, expr, ':value')
|
|
218
185
|
|
|
219
186
|
let from, to
|
|
@@ -237,7 +204,7 @@ directives['value'] = (el, expr) => {
|
|
|
237
204
|
return (state) => update(evaluate(state))
|
|
238
205
|
}
|
|
239
206
|
|
|
240
|
-
|
|
207
|
+
secondary['on'] = (el, expr) => {
|
|
241
208
|
let evaluate = parseExpr(el, expr, ':on')
|
|
242
209
|
|
|
243
210
|
return (state) => {
|
|
@@ -273,7 +240,7 @@ const removeListener = (el, evt, fn) => {
|
|
|
273
240
|
el.removeEventListener(evt, fn);
|
|
274
241
|
}
|
|
275
242
|
|
|
276
|
-
|
|
243
|
+
secondary['data'] = (el, expr) => {
|
|
277
244
|
let evaluate = parseExpr(el, expr, ':data')
|
|
278
245
|
|
|
279
246
|
return ((state) => {
|
|
@@ -282,7 +249,7 @@ directives['data'] = (el, expr) => {
|
|
|
282
249
|
})
|
|
283
250
|
}
|
|
284
251
|
|
|
285
|
-
|
|
252
|
+
secondary['aria'] = (el, expr) => {
|
|
286
253
|
let evaluate = parseExpr(el, expr, ':aria')
|
|
287
254
|
const update = (value) => {
|
|
288
255
|
for (let key in value) attr(el, 'aria-' + dashcase(key), value[key] == null ? null : value[key] + '');
|
|
@@ -290,6 +257,35 @@ directives['aria'] = (el, expr) => {
|
|
|
290
257
|
return ((state) => update(evaluate(state)))
|
|
291
258
|
}
|
|
292
259
|
|
|
260
|
+
// set props in-bulk or run effect
|
|
261
|
+
secondary[''] = (el, expr) => {
|
|
262
|
+
let evaluate = parseExpr(el, expr, ':')
|
|
263
|
+
if (evaluate) return (state) => {
|
|
264
|
+
let value = evaluate(state)
|
|
265
|
+
for (let key in value) attr(el, dashcase(key), value[key]);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// any other prop directive
|
|
270
|
+
export default (el, expr, values, name) => {
|
|
271
|
+
let evt = name.startsWith('on') && name.slice(2)
|
|
272
|
+
let evaluate = parseExpr(el, expr, ':'+name)
|
|
273
|
+
if (evaluate) return evt ? state => {
|
|
274
|
+
let value = evaluate(state)
|
|
275
|
+
if (value) {
|
|
276
|
+
addListener(el, evt, value)
|
|
277
|
+
return () => removeListener(el, evt, value)
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
: state => attr(el, name, evaluate(state))
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// set attr
|
|
284
|
+
const attr = (el, name, v) => {
|
|
285
|
+
if (v == null || v === false) el.removeAttribute(name)
|
|
286
|
+
else el.setAttribute(name, v === true ? '' : (typeof v === 'number' || typeof v === 'string') ? v : '')
|
|
287
|
+
}
|
|
288
|
+
|
|
293
289
|
|
|
294
290
|
let evaluatorMemo = {}
|
|
295
291
|
|
package/test/test.js
CHANGED
|
@@ -404,7 +404,24 @@ test('each: keyed', async () => {
|
|
|
404
404
|
})
|
|
405
405
|
|
|
406
406
|
test.todo('each: unmounted elements remove listeners', async () => {
|
|
407
|
+
// let's hope they get removed without memory leaks :')
|
|
408
|
+
})
|
|
409
|
+
|
|
410
|
+
test('each: internal children get updated by state update, also: update by running again', () => {
|
|
411
|
+
let el = h`<><x :each="item, idx in items" :text="item" :key="idx"></x></>`
|
|
412
|
+
sprae(el, { items: [1,2,3] })
|
|
413
|
+
is(el.textContent, '123')
|
|
414
|
+
let state = sprae(el, { items: [0,2,3] })
|
|
415
|
+
is(el.textContent, '023')
|
|
416
|
+
state.items[0] = 1
|
|
417
|
+
state.items = state.items
|
|
418
|
+
is(el.textContent, '123')
|
|
419
|
+
})
|
|
407
420
|
|
|
421
|
+
test('each: :id and others must receive value from context', () => {
|
|
422
|
+
let el = h`<div><x :id="idx" :each="item, idx in items"></x></div>`
|
|
423
|
+
sprae(el, {items:[1,2,3]})
|
|
424
|
+
is(el.innerHTML,`<x id="1"></x><x id="2"></x><x id="3"></x>`)
|
|
408
425
|
})
|
|
409
426
|
|
|
410
427
|
test('on: base', () => {
|
package/todo.md
CHANGED
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
* [x] implement :with
|
|
35
35
|
* [x] update :value without losing focus / position
|
|
36
36
|
* ~~[x] run tiredown if element got removed from condition or loop (free memory)~~ no need just make sure no refs to elements stored
|
|
37
|
-
* [
|
|
38
|
-
* [
|
|
37
|
+
* [x] `sprae(el, newState)` can update element's state directly (as batch!?) -> must be tested against repeats in directives
|
|
38
|
+
* [x] :if :ref, :if :with -> context setters must come first always
|
|
39
39
|
* [ ] frameworks benchmark
|
|
40
40
|
* [ ] examples
|
|
41
41
|
* [x] todomvc
|