sprae 9.0.0 → 9.1.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/core.js +23 -19
- package/directive/aria.js +2 -3
- package/directive/class.js +2 -3
- package/directive/data.js +2 -4
- package/directive/default.js +3 -4
- package/directive/each.js +39 -42
- package/directive/fx.js +2 -3
- package/directive/html.js +3 -3
- package/directive/if.js +2 -4
- package/directive/ref.js +2 -2
- package/directive/scope.js +2 -3
- package/directive/style.js +2 -3
- package/directive/text.js +2 -3
- package/directive/value.js +2 -4
- package/dist/sprae.js +45 -41
- package/dist/sprae.min.js +1 -1
- package/package.json +6 -4
- package/readme.md +200 -257
- package/sprae.js +17 -2
package/core.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import swapdom from 'swapdom'
|
|
2
|
-
import * as signals from 'ulive'
|
|
3
|
-
import justin from 'subscript/justin.js'
|
|
4
|
-
|
|
5
1
|
// polyfill
|
|
6
2
|
const _dispose = (Symbol.dispose ||= Symbol("dispose"));
|
|
7
3
|
|
|
@@ -9,13 +5,14 @@ const _dispose = (Symbol.dispose ||= Symbol("dispose"));
|
|
|
9
5
|
const SPRAE = `∴`
|
|
10
6
|
|
|
11
7
|
// signals impl
|
|
12
|
-
export let
|
|
8
|
+
export let signal, effect, batch, computed, untracked
|
|
13
9
|
|
|
14
10
|
// reserved directives - order matters!
|
|
15
11
|
export const directive = {};
|
|
16
12
|
|
|
17
13
|
// sprae element: apply directives
|
|
18
14
|
const memo = new WeakMap();
|
|
15
|
+
|
|
19
16
|
export default function sprae(container, values) {
|
|
20
17
|
if (!container.children) return // text nodes, comments etc
|
|
21
18
|
|
|
@@ -23,9 +20,10 @@ export default function sprae(container, values) {
|
|
|
23
20
|
if (memo.has(container)) {
|
|
24
21
|
const [state, effects] = memo.get(container)
|
|
25
22
|
// we rewrite signals instead of update, because user should have what he provided
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
for (let k in values) { state[k] = values[k] }
|
|
24
|
+
// since we call direct updates here, we have to make sure
|
|
25
|
+
// we don't subscribe outer effect, as in case of :each
|
|
26
|
+
untracked(() => { for (let fx of effects) fx() })
|
|
29
27
|
}
|
|
30
28
|
|
|
31
29
|
// take over existing state instead of creating clone
|
|
@@ -47,7 +45,9 @@ export default function sprae(container, values) {
|
|
|
47
45
|
|
|
48
46
|
// NOTE: secondary directives don't stop flow nor extend state, so no need to check
|
|
49
47
|
for (let name of names) {
|
|
50
|
-
let
|
|
48
|
+
let dir = directive[name] || directive.default
|
|
49
|
+
let evaluate = (dir.parse || parse)(attr.value, parse)
|
|
50
|
+
let update = dir(el, evaluate, state, name);
|
|
51
51
|
if (update) {
|
|
52
52
|
update[_dispose] = effect(update);
|
|
53
53
|
effects.push(update);
|
|
@@ -81,6 +81,7 @@ export default function sprae(container, values) {
|
|
|
81
81
|
while (effects.length) effects.pop()[_dispose]();
|
|
82
82
|
container.classList.remove(SPRAE)
|
|
83
83
|
memo.delete(container);
|
|
84
|
+
// NOTE: each child disposes own children etc.
|
|
84
85
|
let els = container.getElementsByClassName(SPRAE);
|
|
85
86
|
while (els.length) els[0][_dispose]?.()
|
|
86
87
|
}
|
|
@@ -91,29 +92,31 @@ export default function sprae(container, values) {
|
|
|
91
92
|
// default compiler
|
|
92
93
|
const evalMemo = {};
|
|
93
94
|
|
|
94
|
-
|
|
95
|
-
if (
|
|
95
|
+
const parse = (expr, dir, fn) => {
|
|
96
|
+
if (fn = evalMemo[expr = expr.trim()]) return fn
|
|
96
97
|
|
|
97
98
|
// static-time errors
|
|
98
|
-
try {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
catch (e) { throw Object.assign(e, { message: `${SPRAE} ${e.message}\n\n${dir}${expr ? `="${expr}"\n\n` : ""}`, expr }) }
|
|
99
|
+
try { fn = compile(expr); }
|
|
100
|
+
catch (e) { throw Object.assign(e, { message: `∴ ${e.message}\n\n${dir}${expr ? `="${expr}"\n\n` : ""}`, expr }) }
|
|
101
|
+
|
|
102
|
+
fn.expr = expr
|
|
103
103
|
|
|
104
104
|
// runtime errors
|
|
105
|
-
return evalMemo[expr] =
|
|
105
|
+
return evalMemo[expr] = fn
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
// default compiler is simple new Function (tiny obfuscation against direct new Function detection)
|
|
109
|
+
export let compile
|
|
110
|
+
|
|
108
111
|
// DOM swapper
|
|
109
|
-
export let swap
|
|
112
|
+
export let swap
|
|
110
113
|
|
|
111
114
|
// interpolate a$<b> fields from context
|
|
112
115
|
export const ipol = (v, state) => {
|
|
113
116
|
return v?.replace ? v.replace(/\$<([^>]+)>/g, (match, field) => state[field]?.valueOf?.() ?? '') : v
|
|
114
117
|
};
|
|
115
118
|
|
|
116
|
-
// configure signals/
|
|
119
|
+
// configure signals/compile/differ
|
|
117
120
|
// it's more compact than using sprae.signal = signal etc.
|
|
118
121
|
sprae.use = s => {
|
|
119
122
|
s.signal && (
|
|
@@ -124,4 +127,5 @@ sprae.use = s => {
|
|
|
124
127
|
untracked = s.untracked || batch
|
|
125
128
|
);
|
|
126
129
|
s.swap && (swap = s.swap)
|
|
130
|
+
s.compile && (compile = s.compile)
|
|
127
131
|
}
|
package/directive/aria.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { directive
|
|
1
|
+
import { directive } from "../core.js";
|
|
2
2
|
import { attr, dashcase } from './default.js'
|
|
3
3
|
|
|
4
|
-
directive['aria'] = (el,
|
|
5
|
-
let evaluate = compile(expr, 'aria')
|
|
4
|
+
directive['aria'] = (el, evaluate, state) => {
|
|
6
5
|
const update = (value) => {
|
|
7
6
|
for (let key in value) attr(el, 'aria-' + dashcase(key), value[key] == null ? null : value[key] + '');
|
|
8
7
|
}
|
package/directive/class.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { directive,
|
|
1
|
+
import { directive, ipol } from "../core.js";
|
|
2
2
|
|
|
3
|
-
directive.class = (el,
|
|
4
|
-
let evaluate = compile(expr, 'class');
|
|
3
|
+
directive.class = (el, evaluate, state) => {
|
|
5
4
|
let cur = new Set
|
|
6
5
|
return () => {
|
|
7
6
|
let v = evaluate(state);
|
package/directive/data.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { directive
|
|
2
|
-
|
|
3
|
-
directive['data'] = (el, expr, state) => {
|
|
4
|
-
let evaluate = compile(expr, 'data')
|
|
1
|
+
import { directive } from "../core.js";
|
|
5
2
|
|
|
3
|
+
directive['data'] = (el, evaluate, state) => {
|
|
6
4
|
return () => {
|
|
7
5
|
let value = evaluate(state)?.valueOf()
|
|
8
6
|
for (let key in value) el.dataset[key] = value[key];
|
package/directive/default.js
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import { directive,
|
|
1
|
+
import { directive, ipol } from "../core.js";
|
|
2
2
|
|
|
3
3
|
// set generic property directive
|
|
4
|
-
directive.default = (el,
|
|
4
|
+
directive.default = (el, evaluate, state, name) => {
|
|
5
5
|
let evt = name.startsWith("on") && name.slice(2);
|
|
6
|
-
let evaluate = compile(expr, name);
|
|
7
6
|
|
|
8
7
|
if (evt) {
|
|
9
8
|
let off
|
|
10
9
|
return () => (
|
|
11
10
|
off?.(), // intermediate teardown
|
|
12
|
-
off = on(el, evt, evaluate(state))
|
|
11
|
+
off = on(el, evt, evaluate(state)?.valueOf())
|
|
13
12
|
);
|
|
14
13
|
}
|
|
15
14
|
|
package/directive/each.js
CHANGED
|
@@ -1,64 +1,61 @@
|
|
|
1
|
-
import sprae, { directive,
|
|
1
|
+
import sprae, { directive, swap } from "../core.js";
|
|
2
2
|
|
|
3
3
|
export const _each = Symbol(":each");
|
|
4
4
|
|
|
5
|
-
const keys = {}
|
|
5
|
+
const keys = {}, _key = Symbol('key');
|
|
6
6
|
|
|
7
7
|
// :each must init before :ref, :id or any others, since it defines scope
|
|
8
|
-
directive.each = (tpl,
|
|
9
|
-
let [leftSide, itemsExpr] = expr.split(/\s+in\s+/);
|
|
10
|
-
let [itemVar, idxVar = "_$"] = leftSide.split(/\s*,\s*/);
|
|
11
|
-
|
|
8
|
+
(directive.each = (tpl, [itemVar, idxVar, evaluate], state) => {
|
|
12
9
|
// we need :if to be able to replace holder instead of tpl for :if :each case
|
|
13
|
-
const holder = (tpl[_each] = document.createTextNode(""));
|
|
10
|
+
const holder = (tpl[_each] = document.createTextNode("")), parent = tpl.parentNode;
|
|
14
11
|
tpl.replaceWith(holder);
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
tpl.removeAttribute(':key')
|
|
13
|
+
// key -> el
|
|
14
|
+
const elCache = new WeakMap, stateCache = new WeakMap
|
|
20
15
|
|
|
21
16
|
let cur = [];
|
|
22
17
|
|
|
18
|
+
const remove = el => {
|
|
19
|
+
el.remove()
|
|
20
|
+
el[Symbol.dispose]?.()
|
|
21
|
+
if (el[_key]) {
|
|
22
|
+
elCache.delete(el[_key])
|
|
23
|
+
stateCache.delete(el[_key])
|
|
24
|
+
}
|
|
25
|
+
}, { insert, replace } = swap
|
|
26
|
+
|
|
27
|
+
const options = { remove, insert, replace }
|
|
28
|
+
|
|
29
|
+
// naive approach: whenever items change we replace full list
|
|
23
30
|
return () => {
|
|
24
|
-
// naive approach: whenever items change we replace full list
|
|
25
31
|
let items = evaluate(state)?.valueOf(), els = [];
|
|
26
|
-
if (typeof items === "number") items = Array.from({ length: items }, (_, i) => i);
|
|
27
32
|
|
|
28
|
-
|
|
29
|
-
for (let idx in items) {
|
|
30
|
-
let item = items[idx]
|
|
31
|
-
// creating via prototype is faster in both creation time & reading time
|
|
32
|
-
let substate = Object.create(state, { [idxVar]: { value: idx } });
|
|
33
|
-
substate[itemVar] = item; // can be changed by subsequent updates, need to be writable
|
|
34
|
-
item = item.peek?.() ?? item; // unwrap signal
|
|
35
|
-
let key = item.key ?? item.id ?? item;
|
|
36
|
-
let el;
|
|
33
|
+
if (typeof items === "number") items = Array.from({ length: items }, (_, i) => i)
|
|
37
34
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
// let c = 0, inc = () => { if (c++ > 100) throw 'Inf recursion' }
|
|
36
|
+
const count = new WeakMap
|
|
37
|
+
for (let idx in items) {
|
|
38
|
+
let el, item = items[idx], key = item?.key ?? item?.id ?? item ?? idx
|
|
39
|
+
key = (Object(key) !== key) ? (keys[key] ||= Object(key)) : item
|
|
42
40
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
console.log(key, count.has(key))
|
|
48
|
-
count.add(key);
|
|
49
|
-
el = memo.get(key) || memo.set(key, tpl.cloneNode(true)).get(key);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
41
|
+
if (key == null || count.has(key) || tpl.content) el = (tpl.content || tpl).cloneNode(true)
|
|
42
|
+
else count.set(key, 1), (el = elCache.get(key) || (elCache.set(key, tpl.cloneNode(true)), elCache.get(key)))[_key] = key;
|
|
52
43
|
|
|
53
|
-
|
|
44
|
+
// creating via prototype is faster in both creation time & reading time
|
|
45
|
+
let substate = stateCache.get(key) || (stateCache.set(key, Object.create(state, { [idxVar]: { value: idx } })), stateCache.get(key));
|
|
46
|
+
substate[itemVar] = item; // can be changed by subsequent updates, need to be writable
|
|
54
47
|
|
|
55
|
-
sprae(el, substate)
|
|
48
|
+
sprae(el, substate);
|
|
56
49
|
|
|
57
50
|
// document fragment
|
|
58
|
-
if (el.nodeType === 11) els.push(...el.childNodes);
|
|
59
|
-
else els.push(el);
|
|
51
|
+
if (el.nodeType === 11) els.push(...el.childNodes); else els.push(el);
|
|
60
52
|
}
|
|
61
53
|
|
|
62
|
-
swap(
|
|
63
|
-
}
|
|
64
|
-
}
|
|
54
|
+
swap(parent, cur, cur = els, holder, options);
|
|
55
|
+
}
|
|
56
|
+
}).parse = (expr, parse) => {
|
|
57
|
+
let [leftSide, itemsExpr] = expr.split(/\s+in\s+/);
|
|
58
|
+
let [itemVar, idxVar = "$"] = leftSide.split(/\s*,\s*/);
|
|
59
|
+
|
|
60
|
+
return [itemVar, idxVar, parse(itemsExpr)]
|
|
61
|
+
}
|
package/directive/fx.js
CHANGED
package/directive/html.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import sprae, { directive
|
|
1
|
+
import sprae, { directive } from "../core.js";
|
|
2
2
|
|
|
3
|
-
directive.html = (el,
|
|
4
|
-
let
|
|
3
|
+
directive.html = (el, evaluate, state) => {
|
|
4
|
+
let tpl = evaluate(state);
|
|
5
5
|
|
|
6
6
|
if (!tpl) return
|
|
7
7
|
|
package/directive/if.js
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
import sprae, {
|
|
1
|
+
import sprae, { directive, swap } from "../core.js";
|
|
2
2
|
import { _each } from './each.js';
|
|
3
3
|
|
|
4
4
|
// :if is interchangeable with :each depending on order, :if :each or :each :if have different meanings
|
|
5
5
|
// as for :if :scope - :if must init first, since it is lazy, to avoid initializing component ahead of time by :scope
|
|
6
6
|
// we consider :scope={x} :if={x} case insignificant
|
|
7
7
|
const _prevIf = Symbol("if");
|
|
8
|
-
directive.if = (ifEl,
|
|
8
|
+
directive.if = (ifEl, evaluate, state) => {
|
|
9
9
|
let parent = ifEl.parentNode,
|
|
10
10
|
next = ifEl.nextElementSibling,
|
|
11
11
|
holder = document.createTextNode(''),
|
|
12
12
|
|
|
13
|
-
evaluate = compile(expr, name),
|
|
14
|
-
|
|
15
13
|
// actual replaceable els (takes <template>)
|
|
16
14
|
cur, ifs, elses, none = [];
|
|
17
15
|
|
package/directive/ref.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { directive, ipol } from "../core.js";
|
|
2
2
|
|
|
3
3
|
// ref must be last within primaries, since that must be skipped by :each, but before secondaries
|
|
4
|
-
directive.ref = (el, expr, state) => {
|
|
4
|
+
(directive.ref = (el, expr, state) => {
|
|
5
5
|
let prev;
|
|
6
6
|
return () => {
|
|
7
7
|
if (prev) delete state[prev]
|
|
8
8
|
state[prev = ipol(expr, state)] = el;
|
|
9
9
|
}
|
|
10
|
-
}
|
|
10
|
+
}).parse = expr => expr
|
package/directive/scope.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import sprae, { directive
|
|
1
|
+
import sprae, { directive } from "../core.js";
|
|
2
2
|
|
|
3
3
|
// `:each` can redefine scope as `:each="a in {myScope}"`,
|
|
4
4
|
// same time per-item scope as `:each="..." :scope="{collapsed:true}"` is useful
|
|
5
|
-
directive.scope = (el,
|
|
6
|
-
let evaluate = compile(expr, name);
|
|
5
|
+
directive.scope = (el, evaluate, rootState) => {
|
|
7
6
|
// local state may contain signals that update, so we take them over
|
|
8
7
|
return () => {
|
|
9
8
|
sprae(el, { ...rootState, ...(evaluate(rootState)?.valueOf?.() || {}) });
|
package/directive/style.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { directive,
|
|
1
|
+
import { directive, ipol } from "../core.js";
|
|
2
2
|
|
|
3
|
-
directive.style = (el,
|
|
4
|
-
let evaluate = compile(expr, 'style');
|
|
3
|
+
directive.style = (el, evaluate, state) => {
|
|
5
4
|
let initStyle = el.getAttribute("style") || "";
|
|
6
5
|
if (!initStyle.endsWith(";")) initStyle += "; ";
|
|
7
6
|
|
package/directive/text.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { directive
|
|
1
|
+
import { directive } from "../core.js";
|
|
2
2
|
|
|
3
3
|
// set text content
|
|
4
|
-
directive.text = (el,
|
|
5
|
-
let evaluate = compile(expr, 'text');
|
|
4
|
+
directive.text = (el, evaluate, state) => {
|
|
6
5
|
if (el.content) el.replaceWith(el = document.createTextNode('')) // <template :text="abc"/>
|
|
7
6
|
|
|
8
7
|
return () => {
|
package/directive/value.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import { directive
|
|
1
|
+
import { directive } from "../core.js";
|
|
2
2
|
import { attr } from './default.js';
|
|
3
3
|
|
|
4
4
|
// connect expr to element value
|
|
5
|
-
directive.value = (el,
|
|
6
|
-
let evaluate = compile(expr, 'value');
|
|
7
|
-
|
|
5
|
+
directive.value = (el, evaluate, state) => {
|
|
8
6
|
let from, to;
|
|
9
7
|
let update = el.type === "text" || el.type === ""
|
|
10
8
|
? (value) => el.setAttribute("value", (el.value = value == null ? "" : value))
|
package/dist/sprae.js
CHANGED
|
@@ -6,7 +6,7 @@ var __export = (target, all) => {
|
|
|
6
6
|
|
|
7
7
|
// node_modules/swapdom/swap-inflate.js
|
|
8
8
|
var swap = (parent, a, b, end = null) => {
|
|
9
|
-
let i = 0, cur2,
|
|
9
|
+
let i = 0, cur2, next2, bi, n = b.length, m = a.length, { remove, same, insert, replace } = swap;
|
|
10
10
|
while (i < n && i < m && same(a[i], b[i]))
|
|
11
11
|
i++;
|
|
12
12
|
while (i < n && i < m && same(b[n - 1], a[m - 1]))
|
|
@@ -17,16 +17,16 @@ var swap = (parent, a, b, end = null) => {
|
|
|
17
17
|
else {
|
|
18
18
|
cur2 = a[i];
|
|
19
19
|
while (i < n) {
|
|
20
|
-
bi = b[i++],
|
|
20
|
+
bi = b[i++], next2 = cur2 ? cur2.nextSibling : end;
|
|
21
21
|
if (same(cur2, bi))
|
|
22
|
-
cur2 =
|
|
23
|
-
else if (i < n && same(b[i],
|
|
24
|
-
replace(cur2, bi, parent), cur2 =
|
|
22
|
+
cur2 = next2;
|
|
23
|
+
else if (i < n && same(b[i], next2))
|
|
24
|
+
replace(cur2, bi, parent), cur2 = next2;
|
|
25
25
|
else
|
|
26
26
|
insert(cur2, bi, parent);
|
|
27
27
|
}
|
|
28
28
|
while (!same(cur2, end))
|
|
29
|
-
|
|
29
|
+
next2 = cur2.nextSibling, remove(cur2, parent), cur2 = next2;
|
|
30
30
|
}
|
|
31
31
|
return b;
|
|
32
32
|
};
|
|
@@ -123,32 +123,29 @@ var parse = (s) => (idx = 0, cur = s, s = expr(), cur[idx] ? err2() : s || "");
|
|
|
123
123
|
var err2 = (msg = "Bad syntax", lines = cur.slice(0, idx).split("\n"), last2 = lines.pop()) => {
|
|
124
124
|
let before = cur.slice(idx - 108, idx).split("\n").pop();
|
|
125
125
|
let after = cur.slice(idx, idx + 108).split("\n").shift();
|
|
126
|
-
throw EvalError(`${msg} at ${lines.length}:${last2.length} \`${idx >= 108 ? "\u2026" : ""}${before}\
|
|
126
|
+
throw EvalError(`${msg} at ${lines.length}:${last2.length} \`${idx >= 108 ? "\u2026" : ""}${before}\u2503${after}\``, "font-weight: bold");
|
|
127
127
|
};
|
|
128
|
-
var
|
|
129
|
-
|
|
130
|
-
idx +=
|
|
131
|
-
else
|
|
132
|
-
while (l = is(cur.charCodeAt(idx)))
|
|
133
|
-
idx += l;
|
|
128
|
+
var next = (is, from = idx, l) => {
|
|
129
|
+
while (l = is(cur.charCodeAt(idx)))
|
|
130
|
+
idx += l;
|
|
134
131
|
return cur.slice(from, idx);
|
|
135
132
|
};
|
|
133
|
+
var skip = (n = 1, from = idx) => (idx += n, cur.slice(from, idx));
|
|
136
134
|
var expr = (prec = 0, end, cc, token2, newNode, fn) => {
|
|
137
|
-
while ((cc = parse.space()) && (newNode = ((fn = lookup[cc]) && fn(token2, prec)) ?? (!token2 && parse.id
|
|
135
|
+
while ((cc = parse.space()) && (newNode = ((fn = lookup[cc]) && fn(token2, prec)) ?? (!token2 && next(parse.id))))
|
|
138
136
|
token2 = newNode;
|
|
139
137
|
if (end)
|
|
140
138
|
cc == end ? idx++ : err2();
|
|
141
139
|
return token2;
|
|
142
140
|
};
|
|
143
|
-
var
|
|
144
|
-
var id = parse.id = () => skip(isId);
|
|
141
|
+
var id = parse.id = (c) => c >= 48 && c <= 57 || c >= 65 && c <= 90 || c >= 97 && c <= 122 || c == 36 || c == 95 || c >= 192 && c != 215 && c != 247;
|
|
145
142
|
var space = parse.space = (cc) => {
|
|
146
143
|
while ((cc = cur.charCodeAt(idx)) <= SPACE)
|
|
147
144
|
idx++;
|
|
148
145
|
return cc;
|
|
149
146
|
};
|
|
150
147
|
var lookup = [];
|
|
151
|
-
var token = (op, prec = SPACE, map, c = op.charCodeAt(0), l = op.length, prev = lookup[c], word = op.toUpperCase() !== op) => lookup[c] = (a, curPrec, from = idx) => curPrec < prec && (l < 2 || cur.substr(idx, l) == op) && (!word || !
|
|
148
|
+
var token = (op, prec = SPACE, map, c = op.charCodeAt(0), l = op.length, prev = lookup[c], word = op.toUpperCase() !== op) => lookup[c] = (a, curPrec, from = idx) => curPrec < prec && (l < 2 || cur.substr(idx, l) == op) && (!word || !parse.id(cur.charCodeAt(idx + l))) && (idx += l, map(a, curPrec)) || (idx = from, prev?.(a, curPrec));
|
|
152
149
|
var binary = (op, prec, right = false) => token(op, prec, (a, b) => a && (b = expr(prec - (right ? 0.5 : 0))) && [op, a, b]);
|
|
153
150
|
var unary = (op, prec, post) => token(op, prec, (a) => post ? a && [op, a] : !a && (a = expr(prec - 0.5)) && [op, a]);
|
|
154
151
|
var nary = (op, prec) => {
|
|
@@ -171,10 +168,10 @@ var prop = (a, fn, generic, obj, path) => a[0] === "()" ? prop(a[1], fn, generic
|
|
|
171
168
|
var compile_default = compile;
|
|
172
169
|
|
|
173
170
|
// node_modules/subscript/feature/number.js
|
|
174
|
-
var num = (a) =>
|
|
171
|
+
var num = (a, _) => [, (a = +next((c) => c === PERIOD || c >= _0 && c <= _9 || (c === _E || c === _e ? 2 : 0))) != a ? err2() : a];
|
|
175
172
|
lookup[PERIOD] = (a) => !a && num();
|
|
176
173
|
for (let i = _0; i <= _9; i++)
|
|
177
|
-
lookup[i] = num;
|
|
174
|
+
lookup[i] = (a) => a ? err2() : num();
|
|
178
175
|
|
|
179
176
|
// node_modules/subscript/feature/string.js
|
|
180
177
|
var escape = { n: "\n", r: "\r", t: " ", b: "\b", f: "\f", v: "\v" };
|
|
@@ -275,14 +272,14 @@ operator("=", (a, b) => (b = compile(b), prop(a, (container, path, ctx) => conta
|
|
|
275
272
|
var subscript_default = (s) => compile_default(parse_default(s));
|
|
276
273
|
|
|
277
274
|
// node_modules/subscript/feature/comment.js
|
|
278
|
-
token("/*", PREC_TOKEN, (a, prec) => (
|
|
279
|
-
token("//", PREC_TOKEN, (a, prec) => (
|
|
275
|
+
token("/*", PREC_TOKEN, (a, prec) => (next((c) => c !== STAR && cur.charCodeAt(idx + 1) !== 47), skip(2), a || expr(prec) || []));
|
|
276
|
+
token("//", PREC_TOKEN, (a, prec) => (next((c) => c >= SPACE), a || expr(prec) || [""]));
|
|
280
277
|
|
|
281
278
|
// node_modules/subscript/feature/pow.js
|
|
282
279
|
binary("**", PREC_EXP, true), operator("**", (a, b) => b && (a = compile(a), b = compile(b), (ctx) => a(ctx) ** b(ctx)));
|
|
283
280
|
|
|
284
281
|
// node_modules/subscript/feature/ternary.js
|
|
285
|
-
token("?", PREC_ASSIGN, (a, b, c) => a && (b = expr(PREC_ASSIGN, COLON)) && (c = expr(PREC_ASSIGN
|
|
282
|
+
token("?", PREC_ASSIGN, (a, b, c) => a && (b = expr(PREC_ASSIGN - 0.5, COLON)) && (c = expr(PREC_ASSIGN - 0.5), ["?", a, b, c]));
|
|
286
283
|
operator("?", (a, b, c) => (a = compile(a), b = compile(b), c = compile(c), (ctx) => a(ctx) ? b(ctx) : c(ctx)));
|
|
287
284
|
|
|
288
285
|
// node_modules/subscript/feature/bool.js
|
|
@@ -291,13 +288,16 @@ token("false", PREC_TOKEN, (a) => a ? err() : [, false]);
|
|
|
291
288
|
|
|
292
289
|
// node_modules/subscript/feature/array.js
|
|
293
290
|
group("[]", PREC_TOKEN);
|
|
294
|
-
operator(
|
|
291
|
+
operator(
|
|
292
|
+
"[]",
|
|
293
|
+
(a, b) => (a = !a ? [] : a[0] === "," ? a.slice(1) : [a], a = a.map((a2) => a2[0] === "..." ? (a2 = compile(a2[1]), (ctx) => a2(ctx)) : (a2 = compile(a2), (ctx) => [a2(ctx)])), (ctx) => a.flatMap((a2) => a2(ctx)))
|
|
294
|
+
);
|
|
295
295
|
|
|
296
296
|
// node_modules/subscript/feature/object.js
|
|
297
297
|
group("{}", PREC_TOKEN);
|
|
298
|
-
operator("{}", (a, b) => !a ?
|
|
299
|
-
binary(":", PREC_ASSIGN, true);
|
|
300
|
-
operator(":", (a, b) => (b = compile(b),
|
|
298
|
+
operator("{}", (a, b) => (a = !a ? [] : a[0] !== "," ? [a] : a.slice(1), a = a.map((p) => compile(typeof p === "string" ? [":", p, p] : p)), (ctx) => Object.fromEntries(a.flatMap((frag) => frag(ctx)))));
|
|
299
|
+
binary(":", PREC_ASSIGN - 0.5, true);
|
|
300
|
+
operator(":", (a, b) => (b = compile(b), Array.isArray(a) ? (a = compile(a), (ctx) => [[a(ctx), b(ctx)]]) : (ctx) => [[a, b(ctx)]]));
|
|
301
301
|
|
|
302
302
|
// node_modules/subscript/feature/arrow.js
|
|
303
303
|
binary("=>", PREC_ASSIGN, true);
|
|
@@ -315,11 +315,15 @@ token("?.", PREC_ACCESS, (a, b) => a && (b = expr(PREC_ACCESS), !b?.map) && ["?.
|
|
|
315
315
|
operator("?.", (a, b) => b && (a = compile(a), (ctx) => a(ctx)?.[b]));
|
|
316
316
|
operator("(", (a, b, container, args, path, optional) => a[0] === "?." && (a[2] || Array.isArray(a[1])) && (args = !b ? () => [] : b[0] === "," ? (b = b.slice(1).map(compile), (ctx) => b.map((a2) => a2(ctx))) : (b = compile(b), (ctx) => [b(ctx)]), !a[2] && (optional = true, a = a[1]), a[0] === "[" ? path = compile(a[2]) : path = () => a[2], container = compile(a[1]), optional ? (ctx) => container(ctx)?.[path(ctx)]?.(...args(ctx)) : (ctx) => container(ctx)?.[path(ctx)](...args(ctx))));
|
|
317
317
|
|
|
318
|
+
// node_modules/subscript/feature/spread.js
|
|
319
|
+
unary("...", PREC_PREFIX);
|
|
320
|
+
operator("...", (a) => (a = compile(a), (ctx) => Object.entries(a(ctx))));
|
|
321
|
+
|
|
318
322
|
// node_modules/subscript/justin.js
|
|
319
323
|
binary("in", PREC_COMP), operator("in", (a, b) => b && (a = compile_default(a), b = compile_default(b), (ctx) => a(ctx) in b(ctx)));
|
|
320
324
|
binary("===", PREC_EQ), binary("!==", 9);
|
|
321
325
|
operator("===", (a, b) => (a = compile_default(a), b = compile_default(b), (ctx) => a(ctx) === b(ctx)));
|
|
322
|
-
operator("
|
|
326
|
+
operator("!==", (a, b) => (a = compile_default(a), b = compile_default(b), (ctx) => a(ctx) !== b(ctx)));
|
|
323
327
|
binary("??", PREC_LOR);
|
|
324
328
|
operator("??", (a, b) => b && (a = compile_default(a), b = compile_default(b), (ctx) => a(ctx) ?? b(ctx)));
|
|
325
329
|
binary("??=", PREC_ASSIGN, true);
|
|
@@ -344,10 +348,13 @@ function sprae(container, values) {
|
|
|
344
348
|
return;
|
|
345
349
|
if (memo.has(container)) {
|
|
346
350
|
const [state2, effects2] = memo.get(container);
|
|
347
|
-
for (let k in values)
|
|
351
|
+
for (let k in values) {
|
|
348
352
|
state2[k] = values[k];
|
|
349
|
-
|
|
350
|
-
|
|
353
|
+
}
|
|
354
|
+
untracked2(() => {
|
|
355
|
+
for (let fx of effects2)
|
|
356
|
+
fx();
|
|
357
|
+
});
|
|
351
358
|
}
|
|
352
359
|
const state = values || {};
|
|
353
360
|
const effects = [];
|
|
@@ -439,9 +446,7 @@ directive.each = (tpl, expr2, state, name) => {
|
|
|
439
446
|
let item = items[idx2];
|
|
440
447
|
let substate = Object.create(state, { [idxVar]: { value: idx2 } });
|
|
441
448
|
substate[itemVar] = item;
|
|
442
|
-
|
|
443
|
-
let key = item.key ?? item.id ?? item;
|
|
444
|
-
let el;
|
|
449
|
+
let el, key = item.key ?? item.id ?? item;
|
|
445
450
|
if (key == null)
|
|
446
451
|
el = tpl.cloneNode(true);
|
|
447
452
|
else {
|
|
@@ -450,7 +455,6 @@ directive.each = (tpl, expr2, state, name) => {
|
|
|
450
455
|
if (count.has(key)) {
|
|
451
456
|
console.warn("Duplicate key", key), el = tpl.cloneNode(true);
|
|
452
457
|
} else {
|
|
453
|
-
console.log(key, count.has(key));
|
|
454
458
|
count.add(key);
|
|
455
459
|
el = memo2.get(key) || memo2.set(key, tpl.cloneNode(true)).get(key);
|
|
456
460
|
}
|
|
@@ -470,24 +474,24 @@ directive.each = (tpl, expr2, state, name) => {
|
|
|
470
474
|
// directive/if.js
|
|
471
475
|
var _prevIf = Symbol("if");
|
|
472
476
|
directive.if = (ifEl, expr2, state, name) => {
|
|
473
|
-
let parent = ifEl.parentNode,
|
|
477
|
+
let parent = ifEl.parentNode, next2 = ifEl.nextElementSibling, holder = document.createTextNode(""), evaluate = compile2(expr2, name), cur2, ifs, elses, none = [];
|
|
474
478
|
ifEl.after(holder);
|
|
475
479
|
if (ifEl.content)
|
|
476
480
|
cur2 = none, ifEl.remove(), ifs = [...ifEl.content.childNodes];
|
|
477
481
|
else
|
|
478
482
|
ifs = cur2 = [ifEl];
|
|
479
|
-
if (
|
|
480
|
-
|
|
481
|
-
if (
|
|
483
|
+
if (next2?.hasAttribute(":else")) {
|
|
484
|
+
next2.removeAttribute(":else");
|
|
485
|
+
if (next2.hasAttribute(":if"))
|
|
482
486
|
elses = none;
|
|
483
487
|
else
|
|
484
|
-
|
|
488
|
+
next2.remove(), elses = next2.content ? [...next2.content.childNodes] : [next2];
|
|
485
489
|
} else
|
|
486
490
|
elses = none;
|
|
487
491
|
return () => {
|
|
488
492
|
const newEls = evaluate(state)?.valueOf() ? ifs : ifEl[_prevIf] ? none : elses;
|
|
489
|
-
if (
|
|
490
|
-
|
|
493
|
+
if (next2)
|
|
494
|
+
next2[_prevIf] = newEls === ifs;
|
|
491
495
|
if (cur2 != newEls) {
|
|
492
496
|
if (cur2[0]?.[_each])
|
|
493
497
|
cur2 = [cur2[0][_each]];
|