sprae 0.0.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +12 -8
- package/plan.md +6 -0
- package/r&d.md +63 -3
- package/readme.md +79 -65
- package/sprae.js +317 -0
- package/sprae.min.js +1 -0
- package/src/core.js +95 -35
- package/src/directives/aria.js +10 -0
- package/src/directives/common.js +15 -0
- package/src/directives/data.js +10 -0
- package/src/directives/each.js +53 -0
- package/src/directives/if.js +31 -0
- package/src/directives/index.js +11 -0
- package/src/directives/on.js +12 -0
- package/src/directives/prop.js +10 -0
- package/src/directives/text.js +10 -0
- package/src/directives/value.js +26 -0
- package/src/directives/with.js +21 -0
- package/src/index.js +12 -2
- package/test/index.html +24 -0
- package/test/test.js +303 -0
- package/src/dirs.js +0 -43
- package/src/eval.js +0 -33
- package/test.js +0 -84
package/test/test.js
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import { signal } from '@preact/signals'
|
|
2
|
+
import test, {is, any, throws} from 'tst'
|
|
3
|
+
import {tick, time} from 'wait-please'
|
|
4
|
+
import sprae from '../src/index.js'
|
|
5
|
+
import h from 'hyperf'
|
|
6
|
+
|
|
7
|
+
Object.defineProperty(DocumentFragment.prototype, 'outerHTML', {
|
|
8
|
+
get() {
|
|
9
|
+
let s = ''
|
|
10
|
+
this.childNodes.forEach(n => {
|
|
11
|
+
s += n.nodeType === 3 ? n.textContent : n.outerHTML != null ? n.outerHTML : ''
|
|
12
|
+
})
|
|
13
|
+
return s
|
|
14
|
+
}
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
test.skip('autoinit', async () => {
|
|
18
|
+
is(window.x.innerHTML, '1')
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test('hidden: core', async () => {
|
|
22
|
+
let el = h`<div :hidden="hidden"></div>`
|
|
23
|
+
let params = sprae(el, {hidden:true})
|
|
24
|
+
is(el.outerHTML, `<div class="∴hidden" hidden=""></div>`)
|
|
25
|
+
params.hidden = false
|
|
26
|
+
is(el.outerHTML, `<div class="∴hidden"></div>`)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('hidden: reactive', async () => {
|
|
30
|
+
const hidden = signal(true)
|
|
31
|
+
let el = h`<div :hidden="hidden"></div>`
|
|
32
|
+
sprae(el, {hidden})
|
|
33
|
+
is(el.outerHTML, `<div class="∴hidden" hidden=""></div>`)
|
|
34
|
+
hidden.value = false
|
|
35
|
+
is(el.outerHTML, `<div class="∴hidden"></div>`)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test('common: reactive', async () => {
|
|
39
|
+
let el = h`<label :for="name" :text="name" ></label><input :id="name" :name="name" :type="name" :disabled="!name"/><a :href="url"></a><img :src="url"/>`
|
|
40
|
+
let params = sprae(el, {name:'text', url:'//google.com'})
|
|
41
|
+
is(el.outerHTML, `<label class="∴text ∴for" for="text">text</label><input class="∴id ∴name ∴type ∴disabled" id="text" name="text" type="text"><a class="∴href" href="//google.com"></a><img class="∴src" src="//google.com">`)
|
|
42
|
+
params.name = 'email'
|
|
43
|
+
is(el.outerHTML, `<label class="∴text ∴for" for="email">email</label><input class="∴id ∴name ∴type ∴disabled" id="email" name="email" type="email"><a class="∴href" href="//google.com"></a><img class="∴src" src="//google.com">`)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test('common: style', async () => {
|
|
47
|
+
let el = h`<x :style="style"></x>`
|
|
48
|
+
let params = sprae(el, {style: "top: 1px"})
|
|
49
|
+
is(el.outerHTML, `<x class="∴style" style="top: 1px"></x>`)
|
|
50
|
+
params.style = {top: '2px'}
|
|
51
|
+
is(el.outerHTML, `<x class="∴style" style="top: 2px"></x>`)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('common: class', async () => {
|
|
55
|
+
let el = h`<x :class="a"></x><y :class="[b, c]"></y><z :class="{b:true, c:d}"></z>`
|
|
56
|
+
const c = signal('z')
|
|
57
|
+
let params = sprae(el, {a:'x', b:'y', c, d:false});
|
|
58
|
+
is(el.outerHTML, `<x class="x"></x><y class="y z"></y><z class="b"></z>`);
|
|
59
|
+
params.d = true;
|
|
60
|
+
is(el.outerHTML, `<x class="x"></x><y class="y z"></y><z class="b c"></z>`);
|
|
61
|
+
c.value = 'w'
|
|
62
|
+
is(el.outerHTML, `<x class="x"></x><y class="y w"></y><z class="b c"></z>`);
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
test('props: base', async () => {
|
|
66
|
+
let el = h`<input :prop="{for:1, title:2, help:3, type:4, placeholder: 5}"/>`
|
|
67
|
+
let params = sprae(el)
|
|
68
|
+
is(el.outerHTML, `<input class="∴prop" for="1" title="2" help="3" type="4" placeholder="5">`)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
test('data: base', async () => {
|
|
72
|
+
let el = h`<input :data="{a:1, fooBar:2}"/>`
|
|
73
|
+
let params = sprae(el)
|
|
74
|
+
is(el.outerHTML, `<input class="∴data" data-a="1" data-foo-bar="2">`)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('aria: base', async () => {
|
|
78
|
+
let el = h`<input type="text" id="jokes" role="combobox" :aria="{controls:'joketypes', autocomplete:'list', expanded:false, activeOption:'item1', activedescendant:''}"/>`
|
|
79
|
+
sprae(el)
|
|
80
|
+
is(el.outerHTML, `<input type="text" id="jokes" role="combobox" class="∴aria" aria-controls="joketypes" aria-autocomplete="list" aria-expanded="false" aria-active-option="item1" aria-activedescendant="">`)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
test('input: direct', async () => {
|
|
84
|
+
let el = h`<input :value="a" />`
|
|
85
|
+
let state = sprae(el, {a:1})
|
|
86
|
+
is(el.value, '1')
|
|
87
|
+
is(el.outerHTML, `<input class="∴value" value="1">`)
|
|
88
|
+
state.a = 2
|
|
89
|
+
is(el.value, '2')
|
|
90
|
+
is(el.outerHTML, `<input class="∴value" value="2">`)
|
|
91
|
+
|
|
92
|
+
el.value = 3
|
|
93
|
+
el.dispatchEvent(new window.Event('change'))
|
|
94
|
+
is(state.a, '3')
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
test('text: core', async () => {
|
|
98
|
+
let el = h`<div :text="text"></div>`
|
|
99
|
+
let params = sprae(el, {text:'abc'})
|
|
100
|
+
is(el.outerHTML, `<div class="∴text">abc</div>`)
|
|
101
|
+
params.text = null
|
|
102
|
+
is(el.outerHTML, `<div class="∴text"></div>`)
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
test('conditions: base', async () => {
|
|
106
|
+
let el = h`<p>
|
|
107
|
+
<span :if="a==1">a</span>
|
|
108
|
+
<span :else-if="a==2">b</span>
|
|
109
|
+
<span :else >c</span>
|
|
110
|
+
</p>`
|
|
111
|
+
|
|
112
|
+
const params = sprae(el, { a: 1 })
|
|
113
|
+
|
|
114
|
+
is(el.innerHTML, '<span class="∴if">a</span>')
|
|
115
|
+
params.a = 2
|
|
116
|
+
is(el.innerHTML, '<span class="∴else-if">b</span>')
|
|
117
|
+
params.a = 3
|
|
118
|
+
is(el.innerHTML, '<span class="∴else">c</span>')
|
|
119
|
+
|
|
120
|
+
delete params.a
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
test('conditions: short with insertions', async () => {
|
|
124
|
+
let el = h`<p>
|
|
125
|
+
<span :if="a==1" :text="'1:'+a"></span>
|
|
126
|
+
<span :else-if="a==2" :text="'2:'+a"></span>
|
|
127
|
+
<span :else :text="a"></span>
|
|
128
|
+
</p>`
|
|
129
|
+
|
|
130
|
+
const params = sprae(el, { a: 1 })
|
|
131
|
+
|
|
132
|
+
is(el.innerHTML, '<span class="∴text ∴if">1:1</span>')
|
|
133
|
+
params.a = 2
|
|
134
|
+
is(el.innerHTML, '<span class="∴text ∴else-if">2:2</span>')
|
|
135
|
+
params.a = 3
|
|
136
|
+
is(el.innerHTML, '<span class="∴text ∴else">3</span>')
|
|
137
|
+
params.a = 4
|
|
138
|
+
is(el.innerHTML, '<span class="∴text ∴else">4</span>')
|
|
139
|
+
|
|
140
|
+
params.a = 1
|
|
141
|
+
is(el.innerHTML, '<span class="∴text ∴if">1:1</span>')
|
|
142
|
+
params.a = 4
|
|
143
|
+
is(el.innerHTML, '<span class="∴text ∴else">4</span>')
|
|
144
|
+
|
|
145
|
+
delete params.a
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
test('conditions: reactive values', async () => {
|
|
149
|
+
let el = h`<p>
|
|
150
|
+
<span :if="a==1" :text="'1:'+a"></span>
|
|
151
|
+
<span :else-if="a==2" :text="'2:'+a"></span>
|
|
152
|
+
<span :else :text="a"></span>
|
|
153
|
+
</p>`
|
|
154
|
+
|
|
155
|
+
const a = signal(1)
|
|
156
|
+
sprae(el, { a })
|
|
157
|
+
|
|
158
|
+
is(el.innerHTML, '<span class="∴text ∴if">1:1</span>')
|
|
159
|
+
a.value = 2
|
|
160
|
+
is(el.innerHTML, '<span class="∴text ∴else-if">2:2</span>')
|
|
161
|
+
a.value = 3
|
|
162
|
+
is(el.innerHTML, '<span class="∴text ∴else">3</span>')
|
|
163
|
+
a.value = 4
|
|
164
|
+
is(el.innerHTML, '<span class="∴text ∴else">4</span>')
|
|
165
|
+
|
|
166
|
+
a.value = 1
|
|
167
|
+
is(el.innerHTML, '<span class="∴text ∴if">1:1</span>')
|
|
168
|
+
a.value = 4
|
|
169
|
+
is(el.innerHTML, '<span class="∴text ∴else">4</span>')
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
test('each: base', async () => {
|
|
174
|
+
// FIXME: in some conspicuous reason jsdom fails to update text nodes somehow
|
|
175
|
+
let el = h`<p>
|
|
176
|
+
<span :each="a in b" :text="a"></span>
|
|
177
|
+
</p>`
|
|
178
|
+
|
|
179
|
+
const params = sprae(el, { b: [] })
|
|
180
|
+
|
|
181
|
+
is(el.innerHTML, '')
|
|
182
|
+
params.b = [1,2]
|
|
183
|
+
is(el.innerHTML, '<span class="∴each ∴text">1</span><span class="∴each ∴text">2</span>')
|
|
184
|
+
params.b = []
|
|
185
|
+
is(el.innerHTML, '')
|
|
186
|
+
delete params.b
|
|
187
|
+
is(el.innerHTML, '')
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
test('each: reactive values', async () => {
|
|
191
|
+
let el = h`<p>
|
|
192
|
+
<span :each="a in b" :text="a"></span>
|
|
193
|
+
</p>`
|
|
194
|
+
|
|
195
|
+
const b = signal([])
|
|
196
|
+
const params = sprae(el, { b })
|
|
197
|
+
|
|
198
|
+
is(el.innerHTML, '')
|
|
199
|
+
b.value = [1,2]
|
|
200
|
+
is(el.innerHTML, '<span class="∴each ∴text">1</span><span class="∴each ∴text">2</span>')
|
|
201
|
+
b.value = []
|
|
202
|
+
is(el.innerHTML, '')
|
|
203
|
+
delete params.b
|
|
204
|
+
is(el.innerHTML, '')
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
test('each: loop with condition', async () => {
|
|
208
|
+
let el = h`<p>
|
|
209
|
+
<span :each="a in b" :text="a" :if="c"></span>
|
|
210
|
+
</p>`
|
|
211
|
+
|
|
212
|
+
const params = sprae(el, { b: [1,2], c:false })
|
|
213
|
+
|
|
214
|
+
is(el.innerHTML, '')
|
|
215
|
+
params.c = true
|
|
216
|
+
is(el.innerHTML, '<span class="∴each ∴text ∴if">1</span><span class="∴each ∴text ∴if">2</span>')
|
|
217
|
+
params.b = [1]
|
|
218
|
+
is(el.innerHTML, '<span class="∴each ∴text ∴if">1</span>')
|
|
219
|
+
delete params.b
|
|
220
|
+
is(el.innerHTML, '')
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
test('each: loop within condition', async () => {
|
|
224
|
+
let el = h`<p>
|
|
225
|
+
<x :if="a==1"><y :each="i in a" :text="i"></y></x>
|
|
226
|
+
<x :else-if="a==2"><y :each="i in a" :text="-i"></y></x>
|
|
227
|
+
</p>`
|
|
228
|
+
|
|
229
|
+
const params = sprae(el, { a: 1 })
|
|
230
|
+
|
|
231
|
+
is(el.innerHTML, '<x class="∴if"><y class="∴each ∴text">1</y></x>')
|
|
232
|
+
params.a = 2
|
|
233
|
+
is(el.innerHTML, '<x class="∴else-if"><y class="∴each ∴text">-1</y><y class="∴each ∴text">-2</y></x>')
|
|
234
|
+
params.a = 0
|
|
235
|
+
is(el.innerHTML, '')
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
test('each: condition within loop', async () => {
|
|
239
|
+
let el = h`<p>
|
|
240
|
+
<x :each="a in b">
|
|
241
|
+
<y :if="a==1" :text="'1:'+a"></y>
|
|
242
|
+
<y :else-if="a==2" :text="'2:'+a"></y>
|
|
243
|
+
<y :else :text="a"></y>
|
|
244
|
+
</x>
|
|
245
|
+
</p>`
|
|
246
|
+
|
|
247
|
+
const params = sprae(el, { b: [1,2,3] })
|
|
248
|
+
|
|
249
|
+
is(el.innerHTML, '<x class="∴each"><y class="∴text ∴if">1:1</y></x><x class="∴each"><y class="∴text ∴else-if">2:2</y></x><x class="∴each"><y class="∴text ∴else">3</y></x>')
|
|
250
|
+
params.b = [2]
|
|
251
|
+
is(el.innerHTML, '<x class="∴each"><y class="∴text ∴else-if">2:2</y></x>')
|
|
252
|
+
delete params.b
|
|
253
|
+
is(el.innerHTML, '')
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
test('on: base', () => {
|
|
257
|
+
let el = h`<div :on="{click(e){log.push('click')},x}"></div>`
|
|
258
|
+
let log = signal([])
|
|
259
|
+
let params = sprae(el, {x(){log.value.push('x')}, log})
|
|
260
|
+
|
|
261
|
+
is(el.outerHTML, `<div class="∴on"></div>`);
|
|
262
|
+
el.dispatchEvent(new window.Event('click'));
|
|
263
|
+
is(log.value, ['click'])
|
|
264
|
+
el.dispatchEvent(new window.Event('x'));
|
|
265
|
+
is(log.value, ['click','x'])
|
|
266
|
+
|
|
267
|
+
params.x = function(){log.value.push('xx')}
|
|
268
|
+
el.dispatchEvent(new window.Event('x'));
|
|
269
|
+
is(log.value, ['click','x','xx']);
|
|
270
|
+
|
|
271
|
+
delete params.x;
|
|
272
|
+
el.dispatchEvent(new window.Event('x'));
|
|
273
|
+
is(log.value, ['click','x','xx']);
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
test('with: inline', () => {
|
|
277
|
+
let el = h`<x :with="{foo:'bar', baz}"><y :text="foo + baz"></y></x>`
|
|
278
|
+
let state = sprae(el, {baz: 'qux'})
|
|
279
|
+
// FIXME: this doesn't inherit root scope baz property and instead uses hard-initialized one
|
|
280
|
+
is(el.innerHTML, `<y class="∴text">barqux</y>`)
|
|
281
|
+
state.baz = 'quux'
|
|
282
|
+
is(el.innerHTML, `<y class="∴text">barquux</y>`)
|
|
283
|
+
})
|
|
284
|
+
test('with: data', () => {
|
|
285
|
+
let el = h`<x :with="x"><y :text="foo"></y></x>`
|
|
286
|
+
let [state, update] = sprae(el, {x:{foo:'bar'}})
|
|
287
|
+
is(el.innerHTML, `<y class="∴text">bar</y>`)
|
|
288
|
+
update({x:{foo:'baz'}})
|
|
289
|
+
is(el.innerHTML, `<y class="∴text">baz</y>`)
|
|
290
|
+
})
|
|
291
|
+
test('with: inheritance', () => {
|
|
292
|
+
// NOTE: y:text initializes through directive, not through parent
|
|
293
|
+
// therefore by default :text uses parent's state, not defined by element itself
|
|
294
|
+
let el = h`<x :with="{foo:'foo'}"><y :with="b" :text="foo+bar"></y></x>`
|
|
295
|
+
sprae(el, {b:{bar:'bar'}})
|
|
296
|
+
is(el.innerHTML, `<y class="∴with ∴text">foobar</y>`)
|
|
297
|
+
})
|
|
298
|
+
test('with: reactive inheritance', () => {
|
|
299
|
+
let el = h`<x :with="{foo:1}"><y :with="b.c" :text="foo+bar"></y></x>`
|
|
300
|
+
const bar = signal('2')
|
|
301
|
+
sprae(el, {b:{c:{bar}}})
|
|
302
|
+
is(el.innerHTML, `<y class="∴with ∴text">12</y>`)
|
|
303
|
+
})
|
package/src/dirs.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { directive } from './core'
|
|
2
|
-
import { parseExpr } from './eval'
|
|
3
|
-
|
|
4
|
-
// hidden attribute directive example
|
|
5
|
-
directive(':hidden', (el, expr) => {
|
|
6
|
-
let evaluate = parseExpr(expr)
|
|
7
|
-
return (state) => {
|
|
8
|
-
let value = evaluate(state)
|
|
9
|
-
prop(el, 'hidden', value)
|
|
10
|
-
}
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
// directive(':if', (el, expr, stash) => {
|
|
15
|
-
// stasj
|
|
16
|
-
// let stash = {els: [el], clauses:[parse(expr)], holder:new Text}, current = el
|
|
17
|
-
// ifStash.set(el, stash)
|
|
18
|
-
// return state => {
|
|
19
|
-
// let idx = stash.clauses.findIndex(match => match(state))
|
|
20
|
-
// if (idx >= 0) current.replaceWith(current = els[idx])
|
|
21
|
-
// else current.replaceWith(current = holder)
|
|
22
|
-
// }
|
|
23
|
-
// })
|
|
24
|
-
// directive(':else-if', (el, expr) => {
|
|
25
|
-
// const ifNode = prev('text-with-if')
|
|
26
|
-
// const stash = ifStash.get(ifNode)
|
|
27
|
-
// stash.els.push(el)
|
|
28
|
-
// stash.els.
|
|
29
|
-
// return
|
|
30
|
-
// })
|
|
31
|
-
// directive(':else', (el, expr) => {
|
|
32
|
-
|
|
33
|
-
// })
|
|
34
|
-
|
|
35
|
-
// directive(':each', (instance, part) => {
|
|
36
|
-
// let evalLoop = part.eval
|
|
37
|
-
// part.eval = state => {
|
|
38
|
-
// let [itemId, items] = evalLoop(state), list=[]
|
|
39
|
-
// // FIXME: cache els instead of recreating. Causes difficulties tracking el children
|
|
40
|
-
// for (let item of items) list.push(new TemplateInstance(part.template, {...state,[itemId]:item}, processor))
|
|
41
|
-
// return list
|
|
42
|
-
// }
|
|
43
|
-
// })
|
package/src/eval.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
let evaluatorMemo = {}
|
|
2
|
-
|
|
3
|
-
// borrowed from alpine: https://github.com/alpinejs/alpine/blob/main/packages/alpinejs/src/evaluator.js#L61
|
|
4
|
-
// it seems to be more robust than subscript
|
|
5
|
-
export function parseExpr(expression, el) {
|
|
6
|
-
if (evaluatorMemo[expression]) return evaluatorMemo[expression]
|
|
7
|
-
|
|
8
|
-
let AsyncFunction = Object.getPrototypeOf(async function(){}).constructor
|
|
9
|
-
|
|
10
|
-
// Some expressions that are useful in Alpine are not valid as the right side of an expression.
|
|
11
|
-
// Here we'll detect if the expression isn't valid for an assignement and wrap it in a self-
|
|
12
|
-
// calling function so that we don't throw an error AND a "return" statement can b e used.
|
|
13
|
-
let rightSideSafeExpression = 0
|
|
14
|
-
// Support expressions starting with "if" statements like: "if (...) doSomething()"
|
|
15
|
-
|| /^[\n\s]*if.*\(.*\)/.test(expression)
|
|
16
|
-
// Support expressions starting with "let/const" like: "let foo = 'bar'"
|
|
17
|
-
|| /^(let|const)\s/.test(expression)
|
|
18
|
-
? `(() => { ${expression} })()`
|
|
19
|
-
: expression
|
|
20
|
-
|
|
21
|
-
const safeAsyncFunction = () => {
|
|
22
|
-
try {
|
|
23
|
-
return new AsyncFunction(['scope'], `let result; with (scope) { result = ${rightSideSafeExpression} }; return result;`)
|
|
24
|
-
} catch ( error ) {
|
|
25
|
-
Object.assign( error, { el, expression } )
|
|
26
|
-
console.warn(`∴ Expression Error: ${error.message}\n\n${ expression ? 'Expression: \"' + expression + '\"\n\n' : '' }`, el)
|
|
27
|
-
setTimeout(() => { throw error }, 0)
|
|
28
|
-
return Promise.resolve()
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return evaluatorMemo[expression] = safeAsyncFunction()
|
|
33
|
-
}
|
package/test.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import v from 'value-ref'
|
|
2
|
-
import { signal } from '@preact/signals'
|
|
3
|
-
import test, {is, throws} from 'tst'
|
|
4
|
-
import {tick, time} from 'wait-please'
|
|
5
|
-
import sprae from '../sprae.js'
|
|
6
|
-
import h from 'hyperf'
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
test.only('hidden', async () => {
|
|
10
|
-
let el = `<div :hidden="hidden"></div>`
|
|
11
|
-
let params = sprae
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
test('conditions: short', async () => {
|
|
15
|
-
let el = h`<p>
|
|
16
|
-
<span :if="a==1">a</span>
|
|
17
|
-
<span :else-if="a==2">b</span>
|
|
18
|
-
<span :else >c</span>
|
|
19
|
-
</p>`
|
|
20
|
-
|
|
21
|
-
const params = sprae(el, { a: 1 })
|
|
22
|
-
|
|
23
|
-
is(el.innerHTML, '<span>a</span>')
|
|
24
|
-
params.a = 2
|
|
25
|
-
is(el.innerHTML, '<span>b</span>')
|
|
26
|
-
params.a = 3
|
|
27
|
-
is(el.innerHTML, '<span>c</span>')
|
|
28
|
-
|
|
29
|
-
delete params.a
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
test('conditions: short with insertions', async () => {
|
|
33
|
-
let el = h`<p>
|
|
34
|
-
<span :if="a==1" :text="['1:',a]"></span>
|
|
35
|
-
<span :else-if="a==2" :text="['2:',a]"></span>
|
|
36
|
-
<span :else :text="a"></span>
|
|
37
|
-
</p>`
|
|
38
|
-
|
|
39
|
-
const params = templize(el, { a: 1 }, exprProcessor)
|
|
40
|
-
|
|
41
|
-
is(el.innerHTML, '<span>1:1</span>')
|
|
42
|
-
params.a = 2
|
|
43
|
-
is(el.innerHTML, '<span>2:2</span>')
|
|
44
|
-
params.a = 3
|
|
45
|
-
is(el.innerHTML, '<span>3</span>')
|
|
46
|
-
params.a = 4
|
|
47
|
-
is(el.innerHTML, '<span>4</span>')
|
|
48
|
-
|
|
49
|
-
params.a = 1
|
|
50
|
-
is(el.innerHTML, '<span>1:1</span>')
|
|
51
|
-
params.a = 4
|
|
52
|
-
is(el.innerHTML, '<span>4</span>')
|
|
53
|
-
|
|
54
|
-
delete params.a
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
test.todo('conditions: reactive values', async () => {
|
|
58
|
-
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
test('loops: short', async () => {
|
|
63
|
-
// FIXME: in some conspicuous reason jsdom fails to update text nodes somehow
|
|
64
|
-
let el = h`<p>
|
|
65
|
-
<span :each="item in items" :text="item"></span>
|
|
66
|
-
</p>`
|
|
67
|
-
|
|
68
|
-
const params = sprae(el, { items: [] })
|
|
69
|
-
|
|
70
|
-
is(el.innerHTML, '')
|
|
71
|
-
params.items = [1,2]
|
|
72
|
-
is(el.innerHTML, '<span>1</span><span>2</span>')
|
|
73
|
-
params.items = []
|
|
74
|
-
is(el.innerHTML, '')
|
|
75
|
-
|
|
76
|
-
delete params.items
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
test.todo('loops: reactive values', async () => {
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
test.todo('loops: condition within loop')
|
|
83
|
-
|
|
84
|
-
test.todo('loops: loop within condition')
|