sprae 5.3.0 → 6.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/examples/todomvc.html +14 -15
- package/package.json +2 -2
- package/r&d.md +45 -16
- package/readme.md +63 -66
- package/sprae.auto.js +24 -63
- package/sprae.auto.min.js +1 -1
- package/sprae.js +24 -63
- package/sprae.min.js +1 -1
- package/src/core.js +16 -11
- package/src/directives.js +22 -56
- package/test/{dom.js → attrs.js} +1 -323
- package/test/events.js +138 -0
- package/test/test.js +12 -1
package/examples/todomvc.html
CHANGED
|
@@ -14,39 +14,38 @@
|
|
|
14
14
|
<section class="todoapp">
|
|
15
15
|
<header class="header">
|
|
16
16
|
<h1>todos</h1>
|
|
17
|
-
<input class="new-todo" placeholder="What needs to be done?" autofocus
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}">
|
|
17
|
+
<input class="new-todo" placeholder="What needs to be done?" autofocus @keypress.enter="
|
|
18
|
+
save(todos = [...todos, { text: this.value, done: false}])
|
|
19
|
+
this.value = ''
|
|
20
|
+
">
|
|
22
21
|
</header>
|
|
23
22
|
<section class="main">
|
|
24
|
-
<input id="toggle-all" class="toggle-all" type="checkbox"
|
|
23
|
+
<input id="toggle-all" class="toggle-all" type="checkbox" @click="
|
|
25
24
|
const all = todos.every(item => item.done)
|
|
26
25
|
save(todos = todos.map(item => (item.done = !all, item)))
|
|
27
|
-
|
|
26
|
+
">
|
|
28
27
|
<label for="toggle-all">Mark all as complete</label>
|
|
29
28
|
<ul class="todo-list">
|
|
30
29
|
<li :ref="li" :each="item in todos"
|
|
31
30
|
:class="{completed: item.done}"
|
|
32
31
|
:hidden="hash === '#/active' ? item.done : hash === '#/completed' ? !item.done : false"
|
|
33
|
-
|
|
32
|
+
@dblclick="
|
|
34
33
|
li.querySelector('.edit').focus()
|
|
35
34
|
li.classList.add('editing')
|
|
36
|
-
|
|
35
|
+
">
|
|
37
36
|
<div class="view">
|
|
38
37
|
<input class="toggle" type="checkbox"
|
|
39
38
|
:checked="item.done"
|
|
40
|
-
|
|
39
|
+
@change="item.done = !item.done, save(todos)"
|
|
41
40
|
/>
|
|
42
41
|
<label :text="item.text"></label>
|
|
43
|
-
<button class="destroy"
|
|
42
|
+
<button class="destroy" @click="save(todos = todos.filter(i => i.text !== item.text))"></button>
|
|
44
43
|
</div>
|
|
45
44
|
<input class=edit
|
|
46
45
|
:value="item.text"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
@input="item.text = this.value; save(todos)"
|
|
47
|
+
@blur="li.classList.remove('editing');"
|
|
48
|
+
@keypress.enter="this.blur()"
|
|
50
49
|
/>
|
|
51
50
|
</li>
|
|
52
51
|
</ul>
|
|
@@ -62,7 +61,7 @@
|
|
|
62
61
|
</ul>
|
|
63
62
|
<button class="clear-completed"
|
|
64
63
|
:hidden="todos.every(item => !item.done)"
|
|
65
|
-
|
|
64
|
+
@click="save(todos = todos.filter(item => !item.done ? true : false))">
|
|
66
65
|
Clear completed
|
|
67
66
|
</button>
|
|
68
67
|
</footer>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sprae",
|
|
3
3
|
"description": "DOM microhydration.",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "6.0.0",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"module": "src/index.js",
|
|
7
7
|
"type": "module",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"@preact/signals": "^1.1.3",
|
|
13
13
|
"es-module-shims": "^1.6.2",
|
|
14
14
|
"esbuild": "^0.15.14",
|
|
15
|
-
"hyperf": "^1.
|
|
15
|
+
"hyperf": "^1.6.2",
|
|
16
16
|
"jsdom": "^21.1.0",
|
|
17
17
|
"signal-struct": "^1.10.0",
|
|
18
18
|
"terser": "^5.15.1",
|
package/r&d.md
CHANGED
|
@@ -381,12 +381,57 @@
|
|
|
381
381
|
+ less problem detecting `const/let` in code
|
|
382
382
|
- conflicts with regular attrs logic: the code is immediately invoked and can assign a function.
|
|
383
383
|
- `:oninput="e => (handleCaret(e), updateTimecodes())"`
|
|
384
|
+
~ `:oninput="handleCaret(event), updateTimecodes()"`
|
|
384
385
|
- `:onbeforeinput="handleBeforeInput"`
|
|
386
|
+
~ `:onbeforeinput="handleBeforeInput(event)"`
|
|
385
387
|
- `:ondragenter..ondragleave:ondragenter..ondrop="e=>(this.classList.add('w-dragover'),e=>this.classList.remove('w-dragover'))"`
|
|
388
|
+
~ `:ondragenter..ondragleave:ondragenter..ondrop="this.classList.add('w-dragover'), e=>this.classList.remove('w-dragover')"`
|
|
386
389
|
- `:ondrop="e=>console.log(e.dataTransfer.types)||e.preventDefault()"`
|
|
390
|
+
~ `:ondrop.prevent="console.log(event.dataTransfer.types)"`
|
|
387
391
|
- `:onfocus="e => (e.relatedTarget ? e.relatedTarget.focus() : e.target.blur())"`
|
|
392
|
+
~ `:onfocus="event.relatedTarget ? event.relatedTarget.focus() : event.target.blur()"`
|
|
388
393
|
- `:onpopstate.window="e => goto(e.state)"`
|
|
394
|
+
~ `:onpopstate.window="goto(event.state)"`
|
|
389
395
|
- `:onclick.toggle="play"`
|
|
396
|
+
~ `:onclick.toggle="play()"`
|
|
397
|
+
|
|
398
|
+
## [ ] Should we introduce `@click` for short-notation events?
|
|
399
|
+
+ gives shorter code for majority of cases
|
|
400
|
+
+ can be non-conflicting
|
|
401
|
+
+ compatible with all frameworks (vue, alpine, lucia, lit)
|
|
402
|
+
+ gives better meaning to modifiers - moves them outside of `:` attribute
|
|
403
|
+
- multiple events `@input@change="code"` is not nice
|
|
404
|
+
~ that's fine and even meaningful
|
|
405
|
+
- chain of events `@focus..@blur="return (e)=>{}"` creates confusing `return` outside of body, as well as inconsistent chain pattern
|
|
406
|
+
? remove that pattern
|
|
407
|
+
+ it's still unsatisfactory: `@mousedown.document..@mouseup.document="e=> (isMouseDown = true, e=> isMouseDown = false)"` works, but what if we want to add `@touchstart..@touchend`, or
|
|
408
|
+
. `@click..@click="play" @keydown.alt-space..@keydown.alt-space="play"`, so in other words we need cross-reaction `@click_or_altspace..@click_or_altspace`, not just one single chain.
|
|
409
|
+
+ actually here `@click@keydown.space..@click@keydown.space` is possible, unlike `:ona..onb` case, the question is how to provide sequence in attribute
|
|
410
|
+
+ the thing is that local state, introduced by initiator events, is not useful by itself, detached from scope.
|
|
411
|
+
. the state is better reflected in data scope, rather than by initiator event.
|
|
412
|
+
? what about temporaries like `@a..@b="id=setTimeout(),()=>clearTimeout(id)"` or `@a.toggle="stop=play(),stop"`
|
|
413
|
+
. use `:with={id:null} @a="id=setTimeout()" @b="clearTimeout(id)"`
|
|
414
|
+
- introduces illicit `event` variable ~ although compatible with standard, still obscure
|
|
415
|
+
- `@` prefix is unchangeable ~ can be removed, not set, but still on the verge.
|
|
416
|
+
- `@click.toggle="code"` has same problem as `@a..@b` - how can we make code separation in attribute?
|
|
417
|
+
+ remove toggle
|
|
418
|
+
+ overall less code
|
|
419
|
+
|
|
420
|
+
## [x] Multiple chain events resolution -> redirect to main event for now
|
|
421
|
+
* Consider
|
|
422
|
+
```
|
|
423
|
+
:onclick..onclick="play"
|
|
424
|
+
:onkeydown.document.alt-space..onkeydown.document.alt-space="play"
|
|
425
|
+
```
|
|
426
|
+
* When started by click and ended by alt-space, it doesn't clear the onclick
|
|
427
|
+
* We actually want here `:onclick:onkeydown.document.alt-space..onclick:onkeydown.document.alt-space`.
|
|
428
|
+
- this makes inconsistency of `..onclick` - colon is missing
|
|
429
|
+
- also it makes precedence of `:` and `..` unclear - what comes before what after.
|
|
430
|
+
|
|
431
|
+
? Can we use `:onclick.toggle="play"`?
|
|
432
|
+
- it doesn't help with switch-over
|
|
433
|
+
? Some 'or' character `:onclick--onkeydown`
|
|
434
|
+
? We can redirect to main event, that's it for now
|
|
390
435
|
|
|
391
436
|
## [x] Should getters convert to computed? -> yes, that's relatively cheap and useful
|
|
392
437
|
|
|
@@ -513,22 +558,6 @@
|
|
|
513
558
|
5. `:x="this.x=value"`
|
|
514
559
|
+ yepyepyep
|
|
515
560
|
|
|
516
|
-
## [x] Multiple chain events resolution -> redirect to main event for now
|
|
517
|
-
* Consider
|
|
518
|
-
```
|
|
519
|
-
:onclick..onclick="play"
|
|
520
|
-
:onkeydown.document.alt-space..onkeydown.document.alt-space="play"
|
|
521
|
-
```
|
|
522
|
-
* When started by click and ended by alt-space, it doesn't clear the onclick
|
|
523
|
-
* We actually want here `:onclick:onkeydown.document.alt-space..onclick:onkeydown.document.alt-space`.
|
|
524
|
-
- this makes inconsistency of `..onclick` - colon is missing
|
|
525
|
-
- also it makes precedence of `:` and `..` unclear - what comes before what after.
|
|
526
|
-
|
|
527
|
-
? Can we use `:onclick.toggle="play"`?
|
|
528
|
-
- it doesn't help with switch-over
|
|
529
|
-
? Some 'or' character `:onclick--onkeydown`
|
|
530
|
-
? We can redirect to main event, that's it for now
|
|
531
|
-
|
|
532
561
|
## [x] Insert content by reusing the node/template -> use `:render="ref" :with="data"`
|
|
533
562
|
|
|
534
563
|
* Makes easy use of repeatable fragments, instead of web-components
|
package/readme.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> DOM microhydration with `:` attributes.
|
|
4
4
|
|
|
5
|
-
_Sprae_ is tiny progressive enhancement framework, a minimal essential alternative to [alpine](https://github.com/alpinejs/alpine)/[lucia](https://github.com/aidenybai/lucia), [petite-vue](https://github.com/vuejs/petite-vue) or [template-parts](https://github.com/github/template-parts) with improved ergonomics[*](#justification). It enables simple markup logic without external scripts. Perfect for small websites, prototypes or UI logic.
|
|
5
|
+
_Sprae_ is tiny progressive enhancement framework, a minimal essential alternative to [alpine](https://github.com/alpinejs/alpine)/[lucia](https://github.com/aidenybai/lucia), [petite-vue](https://github.com/vuejs/petite-vue) or [template-parts](https://github.com/github/template-parts) with improved ergonomics[*](#justification--alternatives). It enables simple markup logic without external scripts. Perfect for small websites, prototypes or UI logic.
|
|
6
6
|
|
|
7
7
|
## Use
|
|
8
8
|
|
|
@@ -116,63 +116,6 @@ Set value of an input, textarea or select. Takes handle of `checked` and `select
|
|
|
116
116
|
</select>
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
-
#### `:<prop>="value?"`
|
|
120
|
-
|
|
121
|
-
Set any attribute value or run an effect.
|
|
122
|
-
|
|
123
|
-
```html
|
|
124
|
-
<!-- Single property -->
|
|
125
|
-
<label :for="name" :text="name" />
|
|
126
|
-
|
|
127
|
-
<!-- Multiple properties -->
|
|
128
|
-
<input :id:name="name" />
|
|
129
|
-
|
|
130
|
-
<!-- Effect (triggers any time bar changes) -->
|
|
131
|
-
<div :fx="void bar()" ></div>
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
#### `:="props?"`
|
|
135
|
-
|
|
136
|
-
Spread multiple attibures.
|
|
137
|
-
|
|
138
|
-
```html
|
|
139
|
-
<input :="{ id: name, name, type:'text', value }" />
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
#### `:on<event>="handler"`, `:on<in>..on<out>="handler"`
|
|
143
|
-
|
|
144
|
-
Add event listener or events chain.
|
|
145
|
-
|
|
146
|
-
```html
|
|
147
|
-
<!-- Single event -->
|
|
148
|
-
<input type="checkbox" :onchange="e => isChecked=e.target.value">
|
|
149
|
-
|
|
150
|
-
<!-- Multiple events -->
|
|
151
|
-
<input :value="text" :oninput:onchange="e => text=e.target.value">
|
|
152
|
-
|
|
153
|
-
<!-- Sequence of events -->
|
|
154
|
-
<button :onfocus..onblur="e => {
|
|
155
|
-
// onfocus
|
|
156
|
-
return e => {
|
|
157
|
-
// onblur
|
|
158
|
-
}
|
|
159
|
-
}">
|
|
160
|
-
|
|
161
|
-
<!-- Event modifiers -->
|
|
162
|
-
<button :onclick.throttle-500="handler">Not too often</button>
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
##### Event modifiers
|
|
166
|
-
|
|
167
|
-
* `.once`, `.passive`, `.capture` – listener [options](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options).
|
|
168
|
-
* `.prevent`, `.stop` – prevent default or stop propagation.
|
|
169
|
-
* `.window`, `.document`, `.outside`, `.self` – specify event target.
|
|
170
|
-
* `.throttle-<ms>`, `.debounce-<ms>` – defer function call with one of the methods.
|
|
171
|
-
* `.toggle` – run function and its result in turn.
|
|
172
|
-
* `.ctrl`, `.shift`, `.alt`, `.meta`, `.arrow`, `.enter`, `.escape`, `.tab`, `.space`, `.backspace`, `.delete`, `.digit`, `.letter`, `.character` – filter by [`event.key`](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values).
|
|
173
|
-
* `.ctrl-<key>, .alt-<key>, .meta-<key>, .shift-<key>` – key combinations, eg. `.ctrl-alt-delete` or `.meta-x`.
|
|
174
|
-
* `.*` – any other modifier has no effect, but allows binding multiple handlers to same event (like jQuery event classes).
|
|
175
|
-
|
|
176
119
|
#### `:with="data"`
|
|
177
120
|
|
|
178
121
|
Define or extend data scope for a subtree.
|
|
@@ -197,8 +140,8 @@ Include template as element content.
|
|
|
197
140
|
```html
|
|
198
141
|
<template :ref="foo"><span :text="foo"></span></template>
|
|
199
142
|
|
|
200
|
-
<div :render="foo" :with="{foo:'bar'}"
|
|
201
|
-
<div :render="foo" :with="{foo:'baz'}"
|
|
143
|
+
<div :render="foo" :with="{foo:'bar'}">...inserted here...</div>
|
|
144
|
+
<div :render="foo" :with="{foo:'baz'}">...inserted here...</div>
|
|
202
145
|
```
|
|
203
146
|
|
|
204
147
|
#### `:ref="id"`
|
|
@@ -213,18 +156,73 @@ Expose element to current data scope with the `id`:
|
|
|
213
156
|
<!-- iterable items -->
|
|
214
157
|
<ul>
|
|
215
158
|
<li :each="item in items" :ref="item">
|
|
216
|
-
<input
|
|
159
|
+
<input @focus="item.classList.add('editing')" @blur="item.classList.remove('editing')"/>
|
|
217
160
|
</li>
|
|
218
161
|
</ul>
|
|
219
162
|
```
|
|
220
163
|
|
|
164
|
+
#### `:="props?"`
|
|
165
|
+
|
|
166
|
+
Spread multiple attibures.
|
|
167
|
+
|
|
168
|
+
```html
|
|
169
|
+
<input :="{ id: name, name, type:'text', value }" />
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
#### `:<prop>="value?"`
|
|
173
|
+
|
|
174
|
+
Set any attribute value or run an effect.
|
|
175
|
+
|
|
176
|
+
```html
|
|
177
|
+
<!-- Single property -->
|
|
178
|
+
<label :for="name" :text="name" />
|
|
179
|
+
|
|
180
|
+
<!-- Multiple properties -->
|
|
181
|
+
<input :id:name="name" />
|
|
182
|
+
|
|
183
|
+
<!-- Effect - returns undefined, triggers any time bar changes -->
|
|
184
|
+
<div :fx="void bar()" ></div>
|
|
185
|
+
|
|
186
|
+
<!-- Raw event listener (see events) -->
|
|
187
|
+
<div :onclick="e=>e.preventDefault()"></div>
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
## Events
|
|
192
|
+
|
|
193
|
+
#### `@<event>="handler"`, `@<foo>@<bar>.<baz>="handler"`
|
|
194
|
+
|
|
195
|
+
Attach event listener or multiple listeners with possible modifiers, `event` variable holds current event.
|
|
196
|
+
|
|
197
|
+
```html
|
|
198
|
+
<!-- Single event -->
|
|
199
|
+
<input type="checkbox" @change="isChecked = event.target.value">
|
|
200
|
+
|
|
201
|
+
<!-- Multiple events -->
|
|
202
|
+
<input :value="text" @input@change="text = event.target.value">
|
|
203
|
+
|
|
204
|
+
<!-- Event modifiers -->
|
|
205
|
+
<button @click.throttle-500="handler(event)">Not too often</button>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
##### Event modifiers
|
|
209
|
+
|
|
210
|
+
* `.once`, `.passive`, `.capture` – listener [options](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options).
|
|
211
|
+
* `.prevent`, `.stop` – prevent default or stop propagation.
|
|
212
|
+
* `.window`, `.document`, `.outside`, `.self` – specify event target.
|
|
213
|
+
* `.throttle-<ms>`, `.debounce-<ms>` – defer function call with one of the methods.
|
|
214
|
+
* `.ctrl`, `.shift`, `.alt`, `.meta`, `.arrow`, `.enter`, `.escape`, `.tab`, `.space`, `.backspace`, `.delete`, `.digit`, `.letter`, `.character` – filter by [`event.key`](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values).
|
|
215
|
+
* `.ctrl-<key>, .alt-<key>, .meta-<key>, .shift-<key>` – key combinations, eg. `.ctrl-alt-delete` or `.meta-x`.
|
|
216
|
+
* `.*` – any other modifier has no effect, but allows binding multiple handlers to same event (like jQuery event classes).
|
|
217
|
+
|
|
218
|
+
|
|
221
219
|
## Sandbox
|
|
222
220
|
|
|
223
221
|
Expressions are sandboxed, ie. have no access to global or window (since sprae can be run in server environment).
|
|
224
222
|
|
|
225
223
|
```html
|
|
226
|
-
<div :x="
|
|
227
|
-
<!--
|
|
224
|
+
<div :x="global.x"></div>
|
|
225
|
+
<!-- global is undefined -->
|
|
228
226
|
```
|
|
229
227
|
|
|
230
228
|
Default sandbox provides: _window_, _document_, _console_, _history_, _location_, _Array_, _Object_, _Number_, _String_, _Boolean_, _Date_, _Set_, _Map_.<br/>
|
|
@@ -247,8 +245,8 @@ To avoid _flash of unstyled content_, you can hide sprae attribute or add a cust
|
|
|
247
245
|
|
|
248
246
|
## Justification & alternatives
|
|
249
247
|
|
|
250
|
-
* [Template-parts](https://github.com/dy/template-parts) / [templize](https://github.com/dy/templize) is progressive, but is stuck with native HTML quirks ([parsing table](https://github.com/github/template-parts/issues/24), [SVG attributes](https://github.com/github/template-parts/issues/25), [liquid syntax](https://shopify.github.io/liquid/tags/template/#raw) conflict etc). Also ergonomics of `attr="{{}}"` is inferior to `:attr=""` since it creates flash of uninitialized values.
|
|
251
|
-
* [Alpine](https://github.com/alpinejs/alpine) / [vue](https://github.com/vuejs/petite-vue) / [lit](https://github.com/lit/lit/tree/main/packages/lit-html) / [lucia](https://github.com/aidenybai/lucia)
|
|
248
|
+
* [Template-parts](https://github.com/dy/template-parts) / [templize](https://github.com/dy/templize) is progressive, but is stuck with native HTML quirks ([parsing table](https://github.com/github/template-parts/issues/24), [SVG attributes](https://github.com/github/template-parts/issues/25), [liquid syntax](https://shopify.github.io/liquid/tags/template/#raw) conflict etc). Also ergonomics of `attr="{{}}"` is inferior to `:attr=""` since it creates flash of uninitialized values. Also it's just nice to keep `{{}}` generic, regardless of markup, and attributes as part of markup.
|
|
249
|
+
* [Alpine](https://github.com/alpinejs/alpine) / [vue](https://github.com/vuejs/petite-vue) / [lit](https://github.com/lit/lit/tree/main/packages/lit-html) / [lucia](https://github.com/aidenybai/lucia) escape native HTML quirks, but the syntax (`:attr`, `v-*`,`x-*`, `l-*` `@evt`, `{{}}`) and functionality is too broad and can be reduced to essence: "perfection is when there's nothing to take away, not add". Also they tend to [self-encapsulate](https://github.com/alpinejs/alpine/discussions/3223) making interop hard, invent own tooling or complex reactivity.
|
|
252
250
|
* React/[preact](https://ghub.io/preact) does the job wiring up JS to HTML, but with an extreme of migrating HTML to JSX and enforcing SPA, which is not organic for HTML. Also it doesn't support reactive fields (needs render call).
|
|
253
251
|
|
|
254
252
|
_Sprae_ takes idea of _templize directives_/_alpine_/_vue_ attrs and builds upon <del>[_@preact/signals_](https://ghub.io/@preact/signals)</del> simple reactive state.
|
|
@@ -260,7 +258,6 @@ _Sprae_ takes idea of _templize directives_/_alpine_/_vue_ attrs and builds upon
|
|
|
260
258
|
* It reserves minimal syntax space as `:` convention (keeping tree neatly decorated, not scattered).
|
|
261
259
|
* Expressions are naturally reactive and incur minimal updates.
|
|
262
260
|
* Elements / data API is open and enable easy interop.
|
|
263
|
-
* It's just nice separation: attributes belong to client and template fields to server.
|
|
264
261
|
|
|
265
262
|
It is reminiscent of [XSLT](https://www.w3schools.com/xml/xsl_intro.asp), considered a [buried treasure](https://github.com/bahrus/be-restated) by web-connoisseurs.
|
|
266
263
|
|
package/sprae.auto.js
CHANGED
|
@@ -376,19 +376,6 @@
|
|
|
376
376
|
} : (value) => el.value = value;
|
|
377
377
|
return (state2) => update(evaluate(state2));
|
|
378
378
|
};
|
|
379
|
-
secondary["on"] = (el, expr) => {
|
|
380
|
-
let evaluate = parseExpr(el, expr, ":on");
|
|
381
|
-
return (state2) => {
|
|
382
|
-
let listeners = evaluate(state2);
|
|
383
|
-
let offs = [];
|
|
384
|
-
for (let evt in listeners)
|
|
385
|
-
offs.push(on(el, evt, listeners[evt]));
|
|
386
|
-
return () => {
|
|
387
|
-
for (let off of offs)
|
|
388
|
-
off();
|
|
389
|
-
};
|
|
390
|
-
};
|
|
391
|
-
};
|
|
392
379
|
var directives_default = (el, expr, state2, name) => {
|
|
393
380
|
let evt = name.startsWith("on") && name.slice(2);
|
|
394
381
|
let evaluate = parseExpr(el, expr, ":" + name);
|
|
@@ -402,43 +389,20 @@
|
|
|
402
389
|
};
|
|
403
390
|
return (state3) => attr(el, name, evaluate(state3));
|
|
404
391
|
};
|
|
405
|
-
var on = (
|
|
406
|
-
if (!
|
|
392
|
+
var on = (el, e, fn) => {
|
|
393
|
+
if (!fn)
|
|
407
394
|
return;
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
let off;
|
|
420
|
-
let curListener = (e) => {
|
|
421
|
-
if (cur)
|
|
422
|
-
off();
|
|
423
|
-
let nextFn = fn.call(target, e);
|
|
424
|
-
if (typeof nextFn !== "function")
|
|
425
|
-
nextFn = () => {
|
|
426
|
-
};
|
|
427
|
-
if (cur + 1 < ctxs.length)
|
|
428
|
-
onFn(nextFn, !cur ? 1 : cur + 1);
|
|
429
|
-
};
|
|
430
|
-
return off = addListenerWithMods(curListener, ctxs[cur]);
|
|
431
|
-
};
|
|
432
|
-
let rootOff = onFn(origFn);
|
|
433
|
-
return () => rootOff();
|
|
434
|
-
function addListenerWithMods(fn, { evt: evt2, target: target2, test, defer, stop, prevent, ...opts }) {
|
|
435
|
-
if (defer)
|
|
436
|
-
fn = defer(fn);
|
|
437
|
-
let cb = (e) => test(e) && (stop && e.stopPropagation(), prevent && e.preventDefault(), fn.call(target2, e));
|
|
438
|
-
target2.addEventListener(evt2, cb, opts);
|
|
439
|
-
return () => target2.removeEventListener(evt2, cb, opts);
|
|
440
|
-
}
|
|
441
|
-
;
|
|
395
|
+
const ctx = { evt: "", target: el, test: () => true };
|
|
396
|
+
ctx.evt = (e.startsWith("on") ? e.slice(2) : e).replace(
|
|
397
|
+
/\.(\w+)?-?([-\w]+)?/g,
|
|
398
|
+
(match, mod, param = "") => (ctx.test = mods[mod]?.(ctx, ...param.split("-")) || ctx.test, "")
|
|
399
|
+
);
|
|
400
|
+
const { evt, target, test, defer, stop, prevent, ...opts } = ctx;
|
|
401
|
+
if (defer)
|
|
402
|
+
fn = defer(fn);
|
|
403
|
+
const cb = (e2) => test(e2) && (stop && e2.stopPropagation(), prevent && e2.preventDefault(), fn.call(target, e2));
|
|
404
|
+
target.addEventListener(evt, cb, opts);
|
|
405
|
+
return () => target.removeEventListener(evt, cb, opts);
|
|
442
406
|
};
|
|
443
407
|
var mods = {
|
|
444
408
|
prevent(ctx) {
|
|
@@ -462,9 +426,6 @@
|
|
|
462
426
|
document(ctx) {
|
|
463
427
|
ctx.target = document;
|
|
464
428
|
},
|
|
465
|
-
toggle(ctx) {
|
|
466
|
-
ctx.defer = (fn, out) => (e) => out ? (out.call?.(ctx.target, e), out = null) : out = fn();
|
|
467
|
-
},
|
|
468
429
|
throttle(ctx, limit) {
|
|
469
430
|
ctx.defer = (fn) => throttle(fn, limit ? Number(limit) || 0 : 108);
|
|
470
431
|
},
|
|
@@ -606,18 +567,18 @@ ${directive}=${expression ? `"${expression}"
|
|
|
606
567
|
}
|
|
607
568
|
if (el.attributes) {
|
|
608
569
|
for (let i = 0; i < el.attributes.length; ) {
|
|
609
|
-
let attr2 = el.attributes[i];
|
|
610
|
-
if (
|
|
570
|
+
let attr2 = el.attributes[i], prefix = attr2.name[0];
|
|
571
|
+
if (prefix === ":" || prefix === "@") {
|
|
572
|
+
el.removeAttribute(attr2.name);
|
|
573
|
+
let expr = prefix === "@" ? `event=>{${attr2.value}}` : attr2.value, names = attr2.name.slice(1).split(prefix);
|
|
574
|
+
for (let name of names) {
|
|
575
|
+
if (prefix === "@")
|
|
576
|
+
name = `on` + name;
|
|
577
|
+
let dir = secondary[name] || directives_default;
|
|
578
|
+
updates.push(dir(el, expr, state2, name));
|
|
579
|
+
}
|
|
580
|
+
} else
|
|
611
581
|
i++;
|
|
612
|
-
continue;
|
|
613
|
-
}
|
|
614
|
-
el.removeAttribute(attr2.name);
|
|
615
|
-
let expr = attr2.value;
|
|
616
|
-
let attrNames = attr2.name.slice(1).split(":");
|
|
617
|
-
for (let attrName of attrNames) {
|
|
618
|
-
let dir = secondary[attrName] || directives_default;
|
|
619
|
-
updates.push(dir(el, expr, state2, attrName));
|
|
620
|
-
}
|
|
621
582
|
}
|
|
622
583
|
}
|
|
623
584
|
for (let i = 0, child; child = el.children[i]; i++) {
|
package/sprae.auto.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{var e,t,r=Promise.prototype.then.bind(Promise.resolve()),n=new WeakMap,
|
|
1
|
+
(()=>{var e,t,r=Promise.prototype.then.bind(Promise.resolve()),n=new WeakMap,s=class extends Map{#e=new FinalizationRegistry((e=>super.delete(e)));get size(){return[...this].length}constructor(e=[]){super();for(const[t,r]of e)this.set(t,r)}get(e){return super.get(e)?.deref()}set(e,t){let r=super.get(e);return r&&this.#e.unregister(r),r=(e=>n.get(e)||(e=>{const t=new WeakRef(e);return n.set(e,t),t})(e))(t),this.#e.register(t,e,r),super.set(e,r)}},l=new Set,i=new WeakMap,o=new WeakMap,a=new WeakMap,u=Symbol("parent"),c={Array:Array,Object:Object,Number:Number,String:String,Boolean:Boolean,Date:Date,console:console,window:window,document:document,history:history,location:location},f={has:()=>!0,get(t,r){if("symbol"==typeof r)return t[r];if(!(r in t))return t[u]?.[r];if(r in Object.prototype||Array.isArray(t)&&r in Array.prototype&&"length"!==r)return t[r];let n=t[r];if(e){let n=i.get(t);n||i.set(t,n={}),n[r]?n[r].includes(e)||n[r].push(e):n[r]=[e]}if(n&&n.constructor===Object||Array.isArray(n)){let e=o.get(n);return e||o.set(n,e=new Proxy(n,f)),e}return n},set(e,t,r){if(!(t in e)&&e[u]&&t in e[u])return e[u][t]=r;if(!Array.isArray(e)&&Object.is(e[t],r))return!0;e[t]=r;let n=i.get(e)?.[t];if(n)for(let e of n)l.add(e);return h(),!0},deleteProperty:(e,t)=>(e[t]=void 0,delete e[t],!0)},p=(e,t)=>{if(o.has(e))return o.get(e);if(a.has(e))return e;let r=new Proxy(e,f);o.set(e,r),a.set(r,e);let n=Object.getOwnPropertyDescriptors(e);for(let t in n){let s=n[t];s.get&&s.get&&(s.get=s.get.bind(r),Object.defineProperty(e,t,s))}return e[u]=t?p(t):c,r},y=t=>{const r=()=>{let n=e;e=r,t(),e=n};return r(),r},h=()=>{t||(t=!0,r((()=>{for(let e of l)e.call();l.clear(),t=!1})))},d={},g={};d.if=(e,t)=>{let r=document.createTextNode(""),n=[j(e,t,":if")],s=[e],l=e;for(;(l=e.nextElementSibling)&&l.hasAttribute(":else");)l.removeAttribute(":else"),(t=l.getAttribute(":if"))?(l.removeAttribute(":if"),l.remove(),s.push(l),n.push(j(e,t,":else :if"))):(l.remove(),s.push(l),n.push((()=>1)));return e.replaceWith(l=r),e=>{let t=n.findIndex((t=>t(e)));s[t]!=l&&((l[b]||l).replaceWith(l=s[t]||r),O(l,e))}};var b=Symbol(":each");d.each=(e,t)=>{let r=function(e){let t=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,r=e.match(/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/);if(!r)return;let n=r[2].trim(),s=r[1].replace(/^\s*\(|\)\s*$/g,"").trim(),l=s.match(t);return l?[s.replace(t,"").trim(),l[1].trim(),n]:[s,"",n]}(t);if(!r)return E(new Error,e,t,":each");const n=e[b]=document.createTextNode("");e.replaceWith(n);const l=j(e,r[2],":each"),i=e.getAttribute(":key"),o=i?j(null,i,":each"):null;e.removeAttribute(":key");const a=e.getAttribute(":ref"),u=new s,c=new s;let f=[];return s=>{let i=l(s);i?"number"==typeof i?i=Array.from({length:i},((e,t)=>[t+1,t])):Array.isArray(i)?i=i.map(((e,t)=>[t+1,e])):"object"==typeof i?i=Object.entries(i):E(Error("Bad list value"),e,t,":each"):i=[];let y=[],h=[];for(let[t,n]of i){let l,i,f=o?.({[r[0]]:n,[r[1]]:t});null==f?l=e.cloneNode(!0):(l=c.get(f))||c.set(f,l=e.cloneNode(!0)),y.push(l),null!=f&&(i=u.get(f))?i[r[0]]=n:(i=p({[r[0]]:n,[a||""]:null,[r[1]]:t},s),null!=f&&u.set(f,i)),h.push(i)}!function(e,t,r,n){const s=new Map,l=new Map;let i,o;for(i=0;i<t.length;i++)s.set(t[i],i);for(i=0;i<r.length;i++)l.set(r[i],i);for(i=o=0;i!==t.length||o!==r.length;){var a=t[i],u=r[o];if(null===a)i++;else if(r.length<=o)e.removeChild(t[i]),i++;else if(t.length<=i)e.insertBefore(u,t[i]||n),o++;else if(a===u)i++,o++;else{var c=l.get(a),f=s.get(u);void 0===c?(e.removeChild(t[i]),i++):void 0===f?(e.insertBefore(u,t[i]||n),o++):(e.insertBefore(t[f],t[i]||n),t[f]=null,f>i+1&&i++,o++)}}}(n.parentNode,f,y,n),f=y;for(let e=0;e<y.length;e++)O(y[e],h[e])}},d.with=(e,t,r)=>{const n=j(e,t,":with")(r);O(e,p(n,r))},d.ref=(e,t,r)=>{r[t]=e},g.render=(e,t,r)=>{let n=j(e,t,":render")(r);n||E(new Error("Template not found"),e,t,":render");let s=n.content.cloneNode(!0);e.replaceChildren(s),O(e,r)},g.id=(e,t)=>{let r=j(e,t,":id");return t=>{return n=r(t),e.id=n||0===n?n:"";var n}},g.class=(e,t)=>{let r=j(e,t,":class"),n=e.getAttribute("class");return t=>{let s=r(t),l=[n];s&&("string"==typeof s?l.push(s):Array.isArray(s)?l.push(...s):l.push(...Object.entries(s).map((([e,t])=>t?e:"")))),(l=l.filter(Boolean).join(" "))?e.setAttribute("class",l):e.removeAttribute("class")}},g.style=(e,t)=>{let r=j(e,t,":style"),n=e.getAttribute("style")||"";return n.endsWith(";")||(n+="; "),t=>{let s=r(t);if("string"==typeof s)e.setAttribute("style",n+s);else{e.setAttribute("style",n);for(let t in s)e.style.setProperty(t,s[t])}}},g.text=(e,t)=>{let r=j(e,t,":text");return t=>{let n=r(t);e.textContent=null==n?"":n}},g[""]=(e,t)=>{let r=j(e,t,":");if(r)return t=>{let n=r(t);for(let t in n)x(e,t.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(e=>"-"+e.toLowerCase())),n[t])}},g.value=(e,t)=>{let r,n,s=j(e,t,":value"),l="text"===e.type||""===e.type?t=>e.setAttribute("value",e.value=null==t?"":t):"TEXTAREA"===e.tagName||"text"===e.type||""===e.type?t=>(r=e.selectionStart,n=e.selectionEnd,e.setAttribute("value",e.value=null==t?"":t),r&&e.setSelectionRange(r,n)):"checkbox"===e.type?t=>(e.value=t?"on":"",x(e,"checked",t)):"select-one"===e.type?t=>{for(let t in e.options)t.removeAttribute("selected");e.value=t,e.selectedOptions[0]?.setAttribute("selected","")}:t=>e.value=t;return e=>l(s(e))};var m=(e,t,r,n)=>{let s=n.startsWith("on")&&n.slice(2),l=j(e,t,":"+n);if(l)return s?t=>{let r=l(t)||(()=>{});return v(e,s,r)}:t=>x(e,n,l(t))},v=(e,t,r)=>{if(!r)return;const n={evt:"",target:e,test:()=>!0};n.evt=(t.startsWith("on")?t.slice(2):t).replace(/\.(\w+)?-?([-\w]+)?/g,((e,t,r="")=>(n.test=A[t]?.(n,...r.split("-"))||n.test,"")));const{evt:s,target:l,test:i,defer:o,stop:a,prevent:u,...c}=n;o&&(r=o(r));const f=e=>i(e)&&(a&&e.stopPropagation(),u&&e.preventDefault(),r.call(l,e));return l.addEventListener(s,f,c),()=>l.removeEventListener(s,f,c)},A={prevent(e){e.prevent=!0},stop(e){e.stop=!0},once(e){e.once=!0},passive(e){e.passive=!0},capture(e){e.capture=!0},window(e){e.target=window},document(e){e.target=document},throttle(e,t){e.defer=e=>k(e,t?Number(t)||0:108)},debounce(e,t){e.defer=e=>W(e,t?Number(t)||0:108)},outside:e=>t=>{let r=e.target;return!(r.contains(t.target)||!1===t.target.isConnected||r.offsetWidth<1&&r.offsetHeight<1)},self:e=>t=>t.target===e.target,ctrl:(e,...t)=>e=>w.ctrl(e)&&t.every((t=>w[t]?w[t](e):e.key===t)),shift:(e,...t)=>e=>w.shift(e)&&t.every((t=>w[t]?w[t](e):e.key===t)),alt:(e,...t)=>e=>w.alt(e)&&t.every((t=>w[t]?w[t](e):e.key===t)),meta:(e,...t)=>e=>w.meta(e)&&t.every((t=>w[t]?w[t](e):e.key===t)),arrow:e=>w.arrow,enter:e=>w.enter,escape:e=>w.escape,tab:e=>w.tab,space:e=>w.space,backspace:e=>w.backspace,delete:e=>w.delete,digit:e=>w.digit,letter:e=>w.letter,character:e=>w.character},w={ctrl:e=>e.ctrlKey||"Control"===e.key||"Ctrl"===e.key,shift:e=>e.shiftKey||"Shift"===e.key,alt:e=>e.altKey||"Alt"===e.key,meta:e=>e.metaKey||"Meta"===e.key||"Command"===e.key,arrow:e=>e.key.startsWith("Arrow"),enter:e=>"Enter"===e.key,escape:e=>e.key.startsWith("Esc"),tab:e=>"Tab"===e.key,space:e=>" "===e.key||"Space"===e.key||" "===e.key,backspace:e=>"Backspace"===e.key,delete:e=>"Delete"===e.key,digit:e=>/^\d$/.test(e.key),letter:e=>/^[a-zA-Z]$/.test(e.key),character:e=>/^\S$/.test(e.key)},k=(e,t)=>{let r,n,s=l=>{r=!0,setTimeout((()=>{if(r=!1,n)return n=!1,s(l),e(l)}),t)};return t=>r?n=!0:(s(t),e(t))},W=(e,t)=>{let r;return n=>{clearTimeout(r),r=setTimeout((()=>{r=null,e(n)}),t)}},x=(e,t,r)=>{null==r||!1===r?e.removeAttribute(t):e.setAttribute(t,!0===r?"":"number"==typeof r||"string"==typeof r?r:"")},S={};function j(e,t,r){let n=S[t];if(!n){let s=/^[\n\s]*if.*\(.*\)/.test(t)||/\b(let|const)\s/.test(t)&&!r.startsWith(":on")?`(() => {${t}})()`:t;try{n=S[t]=new Function("__scope",`with (__scope) { return ${s.trim()} };`)}catch(n){return E(n,e,t,r)}}return s=>{let l;try{l=n.call(e,s)}catch(n){return E(n,e,t,r)}return l}}function E(e,t,n,s){Object.assign(e,{element:t,expression:n}),console.warn(`∴ ${e.message}\n\n${s}=${n?`"${n}"\n\n`:""}`,t),r((()=>{throw e}),0)}O.globals=c;var N=new WeakMap;function O(e,t){if(!e.children)return;if(N.has(e))return Object.assign(N.get(e),t);const r=p(t||{}),n=[],s=(e,t=e.parentNode)=>{for(let s in d){let l=":"+s;if(e.hasAttribute?.(l)){let i=e.getAttribute(l);if(e.removeAttribute(l),n.push(d[s](e,i,r,s)),N.has(e))return;if(e.parentNode!==t)return!1}}if(e.attributes)for(let t=0;t<e.attributes.length;){let s=e.attributes[t],l=s.name[0];if(":"===l||"@"===l){e.removeAttribute(s.name);let t="@"===l?`event=>{${s.value}}`:s.value,i=s.name.slice(1).split(l);for(let s of i){"@"===l&&(s="on"+s);let i=g[s]||m;n.push(i(e,t,r,s))}}else t++}for(let t,r=0;t=e.children[r];r++)!1===s(t,e)&&r--};s(e);for(let e of n)if(e){let t;y((()=>{"function"==typeof t&&t(),t=e(r)}))}return N.set(e,r),r}document.currentScript&&O(document.documentElement)})();
|
package/sprae.js
CHANGED
|
@@ -375,19 +375,6 @@ secondary["value"] = (el, expr) => {
|
|
|
375
375
|
} : (value) => el.value = value;
|
|
376
376
|
return (state2) => update(evaluate(state2));
|
|
377
377
|
};
|
|
378
|
-
secondary["on"] = (el, expr) => {
|
|
379
|
-
let evaluate = parseExpr(el, expr, ":on");
|
|
380
|
-
return (state2) => {
|
|
381
|
-
let listeners = evaluate(state2);
|
|
382
|
-
let offs = [];
|
|
383
|
-
for (let evt in listeners)
|
|
384
|
-
offs.push(on(el, evt, listeners[evt]));
|
|
385
|
-
return () => {
|
|
386
|
-
for (let off of offs)
|
|
387
|
-
off();
|
|
388
|
-
};
|
|
389
|
-
};
|
|
390
|
-
};
|
|
391
378
|
var directives_default = (el, expr, state2, name) => {
|
|
392
379
|
let evt = name.startsWith("on") && name.slice(2);
|
|
393
380
|
let evaluate = parseExpr(el, expr, ":" + name);
|
|
@@ -401,43 +388,20 @@ var directives_default = (el, expr, state2, name) => {
|
|
|
401
388
|
};
|
|
402
389
|
return (state3) => attr(el, name, evaluate(state3));
|
|
403
390
|
};
|
|
404
|
-
var on = (
|
|
405
|
-
if (!
|
|
391
|
+
var on = (el, e, fn) => {
|
|
392
|
+
if (!fn)
|
|
406
393
|
return;
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
let off;
|
|
419
|
-
let curListener = (e) => {
|
|
420
|
-
if (cur)
|
|
421
|
-
off();
|
|
422
|
-
let nextFn = fn.call(target, e);
|
|
423
|
-
if (typeof nextFn !== "function")
|
|
424
|
-
nextFn = () => {
|
|
425
|
-
};
|
|
426
|
-
if (cur + 1 < ctxs.length)
|
|
427
|
-
onFn(nextFn, !cur ? 1 : cur + 1);
|
|
428
|
-
};
|
|
429
|
-
return off = addListenerWithMods(curListener, ctxs[cur]);
|
|
430
|
-
};
|
|
431
|
-
let rootOff = onFn(origFn);
|
|
432
|
-
return () => rootOff();
|
|
433
|
-
function addListenerWithMods(fn, { evt: evt2, target: target2, test, defer, stop, prevent, ...opts }) {
|
|
434
|
-
if (defer)
|
|
435
|
-
fn = defer(fn);
|
|
436
|
-
let cb = (e) => test(e) && (stop && e.stopPropagation(), prevent && e.preventDefault(), fn.call(target2, e));
|
|
437
|
-
target2.addEventListener(evt2, cb, opts);
|
|
438
|
-
return () => target2.removeEventListener(evt2, cb, opts);
|
|
439
|
-
}
|
|
440
|
-
;
|
|
394
|
+
const ctx = { evt: "", target: el, test: () => true };
|
|
395
|
+
ctx.evt = (e.startsWith("on") ? e.slice(2) : e).replace(
|
|
396
|
+
/\.(\w+)?-?([-\w]+)?/g,
|
|
397
|
+
(match, mod, param = "") => (ctx.test = mods[mod]?.(ctx, ...param.split("-")) || ctx.test, "")
|
|
398
|
+
);
|
|
399
|
+
const { evt, target, test, defer, stop, prevent, ...opts } = ctx;
|
|
400
|
+
if (defer)
|
|
401
|
+
fn = defer(fn);
|
|
402
|
+
const cb = (e2) => test(e2) && (stop && e2.stopPropagation(), prevent && e2.preventDefault(), fn.call(target, e2));
|
|
403
|
+
target.addEventListener(evt, cb, opts);
|
|
404
|
+
return () => target.removeEventListener(evt, cb, opts);
|
|
441
405
|
};
|
|
442
406
|
var mods = {
|
|
443
407
|
prevent(ctx) {
|
|
@@ -461,9 +425,6 @@ var mods = {
|
|
|
461
425
|
document(ctx) {
|
|
462
426
|
ctx.target = document;
|
|
463
427
|
},
|
|
464
|
-
toggle(ctx) {
|
|
465
|
-
ctx.defer = (fn, out) => (e) => out ? (out.call?.(ctx.target, e), out = null) : out = fn();
|
|
466
|
-
},
|
|
467
428
|
throttle(ctx, limit) {
|
|
468
429
|
ctx.defer = (fn) => throttle(fn, limit ? Number(limit) || 0 : 108);
|
|
469
430
|
},
|
|
@@ -605,18 +566,18 @@ function sprae(container, values) {
|
|
|
605
566
|
}
|
|
606
567
|
if (el.attributes) {
|
|
607
568
|
for (let i = 0; i < el.attributes.length; ) {
|
|
608
|
-
let attr2 = el.attributes[i];
|
|
609
|
-
if (
|
|
569
|
+
let attr2 = el.attributes[i], prefix = attr2.name[0];
|
|
570
|
+
if (prefix === ":" || prefix === "@") {
|
|
571
|
+
el.removeAttribute(attr2.name);
|
|
572
|
+
let expr = prefix === "@" ? `event=>{${attr2.value}}` : attr2.value, names = attr2.name.slice(1).split(prefix);
|
|
573
|
+
for (let name of names) {
|
|
574
|
+
if (prefix === "@")
|
|
575
|
+
name = `on` + name;
|
|
576
|
+
let dir = secondary[name] || directives_default;
|
|
577
|
+
updates.push(dir(el, expr, state2, name));
|
|
578
|
+
}
|
|
579
|
+
} else
|
|
610
580
|
i++;
|
|
611
|
-
continue;
|
|
612
|
-
}
|
|
613
|
-
el.removeAttribute(attr2.name);
|
|
614
|
-
let expr = attr2.value;
|
|
615
|
-
let attrNames = attr2.name.slice(1).split(":");
|
|
616
|
-
for (let attrName of attrNames) {
|
|
617
|
-
let dir = secondary[attrName] || directives_default;
|
|
618
|
-
updates.push(dir(el, expr, state2, attrName));
|
|
619
|
-
}
|
|
620
581
|
}
|
|
621
582
|
}
|
|
622
583
|
for (let i = 0, child; child = el.children[i]; i++) {
|