@oscarpalmer/abydon 0.13.0 → 0.15.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/dist/abydon.full.js +790 -763
- package/dist/constants.js +10 -0
- package/dist/fragment.js +38 -17
- package/dist/fragments.js +74 -0
- package/dist/helpers/dom.js +4 -4
- package/dist/helpers/index.js +4 -1
- package/dist/index.js +5 -1
- package/dist/node/attribute/index.js +19 -14
- package/dist/node/attribute/value.js +10 -12
- package/dist/node/event.js +7 -9
- package/dist/node/index.js +9 -4
- package/dist/node/value.js +84 -64
- package/dist/parse.js +7 -7
- package/package.json +14 -16
- package/src/constants.ts +20 -0
- package/src/fragment.ts +92 -29
- package/src/fragments.ts +134 -0
- package/src/helpers/dom.ts +3 -3
- package/src/helpers/index.ts +10 -0
- package/src/index.ts +16 -1
- package/src/models.ts +18 -4
- package/src/node/attribute/index.ts +24 -19
- package/src/node/attribute/value.ts +31 -28
- package/src/node/event.ts +11 -12
- package/src/node/index.ts +15 -6
- package/src/node/value.ts +186 -116
- package/src/parse.ts +10 -3
- package/types/constants.d.ts +9 -0
- package/types/fragment.d.ts +26 -8
- package/types/fragments.d.ts +13 -0
- package/types/helpers/index.d.ts +2 -0
- package/types/index.d.ts +5 -1
- package/types/models.d.ts +16 -4
- package/types/fragment.d.cts +0 -27
- package/types/helpers/dom.d.cts +0 -7
- package/types/helpers/index.d.cts +0 -29
- package/types/index.d.cts +0 -302
- package/types/models.d.cts +0 -107
- package/types/node/attribute/index.d.cts +0 -109
- package/types/node/attribute/value.d.cts +0 -109
- package/types/node/event.d.cts +0 -7
- package/types/node/index.d.cts +0 -108
- package/types/node/value.d.cts +0 -108
- package/types/parse.d.cts +0 -108
package/dist/abydon.full.js
CHANGED
|
@@ -1,594 +1,369 @@
|
|
|
1
|
+
const ACTIVE = {};
|
|
2
|
+
const BATCH = {
|
|
3
|
+
depth: 0,
|
|
4
|
+
handlers: /* @__PURE__ */ new Set()
|
|
5
|
+
};
|
|
6
|
+
const METHODS_AFFECTING_LENGTH = new Set([
|
|
7
|
+
"pop",
|
|
8
|
+
"push",
|
|
9
|
+
"shift",
|
|
10
|
+
"unshift"
|
|
11
|
+
]);
|
|
12
|
+
const METHODS_UPDATE = new Set([
|
|
13
|
+
...METHODS_AFFECTING_LENGTH,
|
|
14
|
+
"copyWithin",
|
|
15
|
+
"fill",
|
|
16
|
+
"reverse",
|
|
17
|
+
"sort",
|
|
18
|
+
"splice"
|
|
19
|
+
]);
|
|
20
|
+
const NAME_ARRAY = "array";
|
|
21
|
+
const NAME_COMPUTED = "computed";
|
|
22
|
+
const NAME_EFFECT = "effect";
|
|
23
|
+
const NAME_SIGNAL = "signal";
|
|
24
|
+
const NAME_STORE = "store";
|
|
25
|
+
const NAMES = new Set([
|
|
26
|
+
NAME_ARRAY,
|
|
27
|
+
NAME_COMPUTED,
|
|
28
|
+
NAME_SIGNAL,
|
|
29
|
+
NAME_STORE
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
var Effect = class {
|
|
33
|
+
constructor(callback) {
|
|
34
|
+
Object.defineProperty(this, "$mora", { value: NAME_EFFECT });
|
|
35
|
+
this.state = { callback };
|
|
36
|
+
runEffect(this);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
function runEffect(effect$1) {
|
|
40
|
+
const previousEffect = ACTIVE.effect;
|
|
41
|
+
ACTIVE.effect = effect$1;
|
|
42
|
+
try {
|
|
43
|
+
effect$1.state.callback();
|
|
44
|
+
} finally {
|
|
45
|
+
ACTIVE.effect = previousEffect;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function effect(callback) {
|
|
49
|
+
return typeof callback === "function" ? new Effect(callback) : void 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
1
52
|
function isArray(value) {
|
|
2
|
-
|
|
53
|
+
return isMora(value, NAME_ARRAY);
|
|
3
54
|
}
|
|
4
55
|
function isComputed(value) {
|
|
5
|
-
|
|
56
|
+
return isMora(value, NAME_COMPUTED);
|
|
6
57
|
}
|
|
7
58
|
function isEffect(value) {
|
|
8
|
-
|
|
59
|
+
return isMora(value, NAME_EFFECT);
|
|
9
60
|
}
|
|
10
61
|
function isMora(value, name) {
|
|
11
|
-
|
|
62
|
+
return typeof value === "object" && value != null && "$mora" in value && (typeof name === "string" ? value.$mora === name : name.has(value.$mora));
|
|
12
63
|
}
|
|
13
64
|
function isReactive(value) {
|
|
14
|
-
|
|
65
|
+
return isMora(value, NAMES);
|
|
15
66
|
}
|
|
16
67
|
function isSignal(value) {
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
const arrayName = "array";
|
|
20
|
-
const computedName = "computed";
|
|
21
|
-
const effectName = "effect";
|
|
22
|
-
const signalName = "signal";
|
|
23
|
-
const storeName = "store";
|
|
24
|
-
const reactiveNames = /* @__PURE__ */ new Set([arrayName, computedName, signalName, storeName]);
|
|
25
|
-
|
|
26
|
-
class Effect {
|
|
27
|
-
constructor(callback) {
|
|
28
|
-
Object.defineProperty(this, "$mora", {
|
|
29
|
-
value: effectName
|
|
30
|
-
});
|
|
31
|
-
this.state = {
|
|
32
|
-
callback
|
|
33
|
-
};
|
|
34
|
-
runEffect(this);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
function runEffect(effect2) {
|
|
38
|
-
const previousEffect = activeEffect;
|
|
39
|
-
activeEffect = effect2;
|
|
40
|
-
try {
|
|
41
|
-
effect2.state.callback();
|
|
42
|
-
} finally {
|
|
43
|
-
activeEffect = previousEffect;
|
|
44
|
-
}
|
|
68
|
+
return isMora(value, NAME_SIGNAL);
|
|
45
69
|
}
|
|
46
|
-
function effect(callback) {
|
|
47
|
-
return new Effect(callback);
|
|
48
|
-
}
|
|
49
|
-
let activeEffect;
|
|
50
70
|
|
|
51
71
|
function flushHandlers() {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
} else {
|
|
59
|
-
handler.callback(handler.state.value);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
72
|
+
while (BATCH.depth === 0 && BATCH.handlers.size > 0) {
|
|
73
|
+
const handlers = [...BATCH.handlers];
|
|
74
|
+
BATCH.handlers.clear();
|
|
75
|
+
for (const handler of handlers) if (isEffect(handler)) runEffect(handler);
|
|
76
|
+
else handler.callback(handler.state.value);
|
|
77
|
+
}
|
|
63
78
|
}
|
|
64
79
|
function startBatch() {
|
|
65
|
-
|
|
80
|
+
BATCH.depth += 1;
|
|
66
81
|
}
|
|
67
82
|
function stopBatch() {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
flushHandlers();
|
|
83
|
+
if (BATCH.depth > 0) BATCH.depth -= 1;
|
|
84
|
+
flushHandlers();
|
|
72
85
|
}
|
|
73
|
-
const batchedHandlers = /* @__PURE__ */ new Set();
|
|
74
|
-
let batchDepth = 0;
|
|
75
86
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
87
|
+
var Subscription = class {
|
|
88
|
+
callback;
|
|
89
|
+
state;
|
|
90
|
+
constructor(state, callback) {
|
|
91
|
+
this.state = state;
|
|
92
|
+
this.callback = callback;
|
|
93
|
+
callback(state.value);
|
|
94
|
+
}
|
|
95
|
+
destroy() {
|
|
96
|
+
this.callback = noop;
|
|
97
|
+
this.state = void 0;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
function noop() {}
|
|
85
101
|
function subscribe(state, callback) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
unsubscribe(state, callback);
|
|
92
|
-
};
|
|
102
|
+
if (typeof callback !== "function" || state.subscriptions.has(callback)) return noop;
|
|
103
|
+
state.subscriptions.set(callback, new Subscription(state, callback));
|
|
104
|
+
return () => {
|
|
105
|
+
unsubscribe(state, callback);
|
|
106
|
+
};
|
|
93
107
|
}
|
|
94
108
|
function unsubscribe(state, callback) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (subscription != null) {
|
|
98
|
-
subscription.callback = noop;
|
|
99
|
-
subscription.state = void 0;
|
|
100
|
-
}
|
|
109
|
+
state.subscriptions.get(callback)?.destroy();
|
|
110
|
+
state.subscriptions.delete(callback);
|
|
101
111
|
}
|
|
102
112
|
|
|
103
|
-
var
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
subscribe(callback) {
|
|
133
|
-
return subscribe(this.state, callback);
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* JSON representation of the value
|
|
137
|
-
*/
|
|
138
|
-
toJSON() {
|
|
139
|
-
return this.get();
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* String representation of the value
|
|
143
|
-
*/
|
|
144
|
-
toString() {
|
|
145
|
-
return String(this.get());
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Unsubscribe from changes
|
|
149
|
-
*/
|
|
150
|
-
unsubscribe(callback) {
|
|
151
|
-
unsubscribe(this.state, callback);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
113
|
+
var Reactive = class {
|
|
114
|
+
state = {
|
|
115
|
+
computeds: /* @__PURE__ */ new Set(),
|
|
116
|
+
effects: /* @__PURE__ */ new Set(),
|
|
117
|
+
equal: Object.is,
|
|
118
|
+
subscriptions: /* @__PURE__ */ new Map(),
|
|
119
|
+
value: void 0
|
|
120
|
+
};
|
|
121
|
+
constructor(name, value, options) {
|
|
122
|
+
this.state.value = value;
|
|
123
|
+
if (typeof options === "object" && typeof options.equal === "function") this.state.equal = options.equal;
|
|
124
|
+
Object.defineProperty(this, "$mora", { value: name });
|
|
125
|
+
}
|
|
126
|
+
peek() {
|
|
127
|
+
return this.state.value;
|
|
128
|
+
}
|
|
129
|
+
subscribe(callback) {
|
|
130
|
+
return subscribe(this.state, callback);
|
|
131
|
+
}
|
|
132
|
+
toJSON() {
|
|
133
|
+
return this.get();
|
|
134
|
+
}
|
|
135
|
+
toString() {
|
|
136
|
+
return String(this.get());
|
|
137
|
+
}
|
|
138
|
+
unsubscribe(callback) {
|
|
139
|
+
unsubscribe(this.state, callback);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
154
142
|
|
|
155
|
-
var
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
this.effect.dirty = false;
|
|
185
|
-
}
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* @inheritdoc
|
|
190
|
-
*/
|
|
191
|
-
get() {
|
|
192
|
-
if (activeComputed != null && this !== activeComputed) {
|
|
193
|
-
this.state.computeds.add(activeComputed);
|
|
194
|
-
}
|
|
195
|
-
if (activeEffect != null && activeEffect !== this.effect.instance) {
|
|
196
|
-
this.state.effects.add(activeEffect);
|
|
197
|
-
}
|
|
198
|
-
if (this.effect.dirty && batchDepth === 0) {
|
|
199
|
-
runEffect(this.effect.instance);
|
|
200
|
-
}
|
|
201
|
-
return this.state.value;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
143
|
+
var Computed = class extends Reactive {
|
|
144
|
+
effect = {
|
|
145
|
+
dirty: true,
|
|
146
|
+
instance: void 0
|
|
147
|
+
};
|
|
148
|
+
constructor(callback, options) {
|
|
149
|
+
super(NAME_COMPUTED, void 0, options);
|
|
150
|
+
this.effect.instance = effect(() => {
|
|
151
|
+
if (!this.effect.dirty) return;
|
|
152
|
+
const previousComputed = ACTIVE.computed;
|
|
153
|
+
ACTIVE.computed = this;
|
|
154
|
+
const value = callback();
|
|
155
|
+
ACTIVE.computed = previousComputed;
|
|
156
|
+
if (!this.state.equal(this.state.value, value)) {
|
|
157
|
+
this.state.value = value;
|
|
158
|
+
for (const computed$1 of this.state.computeds) computed$1.effect.dirty = true;
|
|
159
|
+
for (const effect$1 of this.state.effects) BATCH.handlers.add(effect$1);
|
|
160
|
+
for (const [, subscription] of this.state.subscriptions) subscription.callback(value);
|
|
161
|
+
}
|
|
162
|
+
this.effect.dirty = false;
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
get() {
|
|
166
|
+
if (ACTIVE.computed != null && this !== ACTIVE.computed) this.state.computeds.add(ACTIVE.computed);
|
|
167
|
+
if (ACTIVE.effect != null && ACTIVE.effect !== this.effect.instance) this.state.effects.add(ACTIVE.effect);
|
|
168
|
+
if (this.effect.dirty && BATCH.depth === 0) runEffect(this.effect.instance);
|
|
169
|
+
return this.state.value;
|
|
170
|
+
}
|
|
171
|
+
};
|
|
204
172
|
function computed(callback, options) {
|
|
205
|
-
|
|
173
|
+
return new Computed(callback, options);
|
|
206
174
|
}
|
|
207
175
|
|
|
208
176
|
function emitValue(state) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
batchedHandlers.add(effect);
|
|
214
|
-
}
|
|
215
|
-
for (const [, subscription] of state.subscriptions) {
|
|
216
|
-
batchedHandlers.add(subscription);
|
|
217
|
-
}
|
|
218
|
-
if (batchDepth === 0) {
|
|
219
|
-
flushHandlers();
|
|
220
|
-
}
|
|
177
|
+
for (const computed of state.computeds) computed.effect.dirty = true;
|
|
178
|
+
for (const effect of state.effects) BATCH.handlers.add(effect);
|
|
179
|
+
for (const [, subscription] of state.subscriptions) BATCH.handlers.add(subscription);
|
|
180
|
+
if (BATCH.depth === 0) flushHandlers();
|
|
221
181
|
}
|
|
222
182
|
function equalArrays(state, first, second) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
length -= offset;
|
|
238
|
-
for (let index = offset; index < length; index += 1) {
|
|
239
|
-
if (!state.equal(first[index], second[index])) {
|
|
240
|
-
return false;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
return true;
|
|
183
|
+
let { length } = first;
|
|
184
|
+
if (length !== second.length) return false;
|
|
185
|
+
let offset = 0;
|
|
186
|
+
if (length >= 100) {
|
|
187
|
+
offset = Math.round(length / 10);
|
|
188
|
+
offset = offset > 25 ? 25 : offset;
|
|
189
|
+
for (let index = 0; index < offset; index += 1) if (!state.equal(first[index], second[index])) return false;
|
|
190
|
+
}
|
|
191
|
+
length -= offset;
|
|
192
|
+
for (let index = offset; index < length; index += 1) if (!state.equal(first[index], second[index])) return false;
|
|
193
|
+
return true;
|
|
244
194
|
}
|
|
245
195
|
function getValue$1(state) {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
196
|
+
if (ACTIVE.computed != null) state.computeds.add(ACTIVE.computed);
|
|
197
|
+
if (ACTIVE.effect != null) state.effects.add(ACTIVE.effect);
|
|
198
|
+
return state.value;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
var Signal = class extends Reactive {
|
|
202
|
+
constructor(value, options) {
|
|
203
|
+
super(NAME_SIGNAL, value, options);
|
|
204
|
+
}
|
|
205
|
+
get() {
|
|
206
|
+
return getValue$1(this.state);
|
|
207
|
+
}
|
|
208
|
+
set(value) {
|
|
209
|
+
if (!this.state.equal(this.state.value, value)) {
|
|
210
|
+
this.state.value = value;
|
|
211
|
+
emitValue(this.state);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
update(callback) {
|
|
215
|
+
this.set(callback(this.state.value));
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
function signal(value, options) {
|
|
219
|
+
return new Signal(value, options);
|
|
253
220
|
}
|
|
254
221
|
|
|
255
222
|
function getReactiveValueInProxy(reactive, mapped, key, isArray) {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
223
|
+
let item = mapped.get(key);
|
|
224
|
+
if (item == null) {
|
|
225
|
+
item = computed(() => {
|
|
226
|
+
const value = reactive.get();
|
|
227
|
+
return isArray ? value.at(key) : value[key];
|
|
228
|
+
});
|
|
229
|
+
mapped.set(key, item);
|
|
230
|
+
}
|
|
231
|
+
return item;
|
|
265
232
|
}
|
|
266
233
|
function setProxyValue(proxy, value) {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
stopBatch();
|
|
284
|
-
}
|
|
285
|
-
function setValueInProxy(target, property, value, state, isArray, length) {
|
|
286
|
-
if (isArray) {
|
|
287
|
-
const isIndex = !Number.isNaN(Number(property));
|
|
288
|
-
const isLength = property === "length";
|
|
289
|
-
if (!isIndex && !isLength) {
|
|
290
|
-
return Reflect.set(target, property, value);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
const previous = Reflect.get(target, property);
|
|
294
|
-
if (!state.equal(previous, value)) {
|
|
295
|
-
Reflect.set(target, property, value);
|
|
296
|
-
emitValue(state);
|
|
297
|
-
if (isArray) {
|
|
298
|
-
length == null ? void 0 : length.set(target.length);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
return true;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
class Signal extends Reactive {
|
|
305
|
-
constructor(value, options) {
|
|
306
|
-
super(signalName, value, options);
|
|
307
|
-
}
|
|
308
|
-
/**
|
|
309
|
-
* @inheritdoc
|
|
310
|
-
*/
|
|
311
|
-
get() {
|
|
312
|
-
return getValue$1(this.state);
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* Set the value
|
|
316
|
-
*/
|
|
317
|
-
set(value) {
|
|
318
|
-
if (!this.state.equal(this.state.value, value)) {
|
|
319
|
-
this.state.value = value;
|
|
320
|
-
emitValue(this.state);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
/**
|
|
324
|
-
* Update the value _(based on the current value)_
|
|
325
|
-
*/
|
|
326
|
-
update(callback) {
|
|
327
|
-
this.set(callback(this.state.value));
|
|
328
|
-
}
|
|
234
|
+
startBatch();
|
|
235
|
+
const proxyKeys = Object.keys(proxy);
|
|
236
|
+
const valueKeys = Object.keys(value);
|
|
237
|
+
let { length } = proxyKeys;
|
|
238
|
+
for (let index = 0; index < length; index += 1) {
|
|
239
|
+
const key = proxyKeys[index];
|
|
240
|
+
proxy[key] = valueKeys.includes(key) ? value[key] : void 0;
|
|
241
|
+
}
|
|
242
|
+
length = valueKeys.length;
|
|
243
|
+
for (let index = 0; index < length; index += 1) {
|
|
244
|
+
const key = valueKeys[index];
|
|
245
|
+
if (!proxyKeys.includes(key)) proxy[key] = value[key];
|
|
246
|
+
}
|
|
247
|
+
stopBatch();
|
|
329
248
|
}
|
|
330
|
-
function
|
|
331
|
-
|
|
249
|
+
function setValueInProxy(parameters) {
|
|
250
|
+
const { isArray, length, property, state, target, value } = parameters;
|
|
251
|
+
if (isArray) {
|
|
252
|
+
if (!(!Number.isNaN(Number(property)) || property === "length")) return Reflect.set(target, property, value);
|
|
253
|
+
}
|
|
254
|
+
const previous = Reflect.get(target, property);
|
|
255
|
+
if (!state.equal(previous, value)) {
|
|
256
|
+
Reflect.set(target, property, value);
|
|
257
|
+
emitValue(state);
|
|
258
|
+
if (isArray) length?.set(target.length);
|
|
259
|
+
}
|
|
260
|
+
return true;
|
|
332
261
|
}
|
|
333
262
|
|
|
334
|
-
var
|
|
335
|
-
|
|
263
|
+
var ReactiveArray = class extends Reactive {
|
|
264
|
+
#indiced = /* @__PURE__ */ new Map();
|
|
265
|
+
#size = signal(0);
|
|
266
|
+
get length() {
|
|
267
|
+
return this.#size.get();
|
|
268
|
+
}
|
|
269
|
+
set length(value) {
|
|
270
|
+
if (typeof value === "number" && value >= 0 && value !== this.state.value.length) this.get().length = value;
|
|
271
|
+
}
|
|
272
|
+
constructor(value, options) {
|
|
273
|
+
super(NAME_ARRAY, new Proxy(value, {
|
|
274
|
+
get: (target, property) => METHODS_UPDATE.has(property) ? updateArray(property, target, this.state, this.#size) : Reflect.get(target, property),
|
|
275
|
+
set: (target, property, value$1) => setValueInProxy({
|
|
276
|
+
property,
|
|
277
|
+
target,
|
|
278
|
+
value: value$1,
|
|
279
|
+
isArray: true,
|
|
280
|
+
state: this.state,
|
|
281
|
+
length: this.#size
|
|
282
|
+
})
|
|
283
|
+
}), options);
|
|
284
|
+
this.#size.set(value.length);
|
|
285
|
+
}
|
|
286
|
+
clear() {
|
|
287
|
+
this.length = 0;
|
|
288
|
+
}
|
|
289
|
+
filter(callback) {
|
|
290
|
+
return computed(() => this.get().filter(callback));
|
|
291
|
+
}
|
|
292
|
+
get(first) {
|
|
293
|
+
if (typeof first === "number") return getReactiveValueInProxy(this, this.#indiced, first, true).get();
|
|
294
|
+
if (first === "length") return this.length;
|
|
295
|
+
return getValue$1(this.state);
|
|
296
|
+
}
|
|
297
|
+
map(callback) {
|
|
298
|
+
return computed(() => this.get().map(callback));
|
|
299
|
+
}
|
|
300
|
+
notify() {
|
|
301
|
+
emitValue(this.state);
|
|
302
|
+
}
|
|
303
|
+
peek(value) {
|
|
304
|
+
if (value === "length") return this.#size.peek();
|
|
305
|
+
if (typeof value === "number") return this.state.value.at(value);
|
|
306
|
+
return [...this.state.value];
|
|
307
|
+
}
|
|
308
|
+
pop() {
|
|
309
|
+
return this.state.value.pop();
|
|
310
|
+
}
|
|
311
|
+
push(...items) {
|
|
312
|
+
return this.state.value.push(...items);
|
|
313
|
+
}
|
|
314
|
+
set(first, second) {
|
|
315
|
+
if (first == null || Array.isArray(first)) this.state.value.splice(0, this.state.value.length, ...first ?? []);
|
|
316
|
+
else if (first === "length") this.length = second;
|
|
317
|
+
else if (typeof first === "number" && !Number.isNaN(first)) setAtIndex(this.state.value, first, second);
|
|
318
|
+
}
|
|
319
|
+
shift() {
|
|
320
|
+
return this.state.value.shift();
|
|
321
|
+
}
|
|
322
|
+
splice(from, to, ...items) {
|
|
323
|
+
return this.state.value.splice(from, to ?? this.state.value.length, ...items);
|
|
324
|
+
}
|
|
325
|
+
subscribe(first, second) {
|
|
326
|
+
if (typeof first === "number" && typeof second === "function") return getReactiveValueInProxy(this, this.#indiced, first, true).subscribe(second);
|
|
327
|
+
return typeof first === "function" ? subscribe(this.state, first) : noop;
|
|
328
|
+
}
|
|
329
|
+
unshift(...items) {
|
|
330
|
+
return this.state.value.unshift(...items);
|
|
331
|
+
}
|
|
332
|
+
update(callback) {
|
|
333
|
+
const updated = callback(this.state.value);
|
|
334
|
+
if (updated == null || Array.isArray(updated)) this.set(updated);
|
|
335
|
+
}
|
|
336
336
|
};
|
|
337
|
-
var __accessCheck$1 = (obj, member, msg) => member.has(obj) || __typeError$1("Cannot " + msg);
|
|
338
|
-
var __privateGet$1 = (obj, member, getter) => (__accessCheck$1(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
339
|
-
var __privateAdd$1 = (obj, member, value) => member.has(obj) ? __typeError$1("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
340
|
-
var _indiced, _size;
|
|
341
|
-
class ReactiveArray extends Reactive {
|
|
342
|
-
constructor(value, options) {
|
|
343
|
-
super(
|
|
344
|
-
arrayName,
|
|
345
|
-
new Proxy(value, {
|
|
346
|
-
get: (target, property) => updateMethods.has(property) ? updateArray(property, target, this.state, __privateGet$1(this, _size)) : Reflect.get(target, property),
|
|
347
|
-
set: (target, property, value2) => setValueInProxy(
|
|
348
|
-
target,
|
|
349
|
-
property,
|
|
350
|
-
value2,
|
|
351
|
-
this.state,
|
|
352
|
-
true,
|
|
353
|
-
__privateGet$1(this, _size)
|
|
354
|
-
)
|
|
355
|
-
}),
|
|
356
|
-
options
|
|
357
|
-
);
|
|
358
|
-
__privateAdd$1(this, _indiced, /* @__PURE__ */ new Map());
|
|
359
|
-
__privateAdd$1(this, _size, signal(0));
|
|
360
|
-
__privateGet$1(this, _size).set(value.length);
|
|
361
|
-
}
|
|
362
|
-
/**
|
|
363
|
-
* The length of the array
|
|
364
|
-
*/
|
|
365
|
-
get length() {
|
|
366
|
-
return __privateGet$1(this, _size).get();
|
|
367
|
-
}
|
|
368
|
-
/**
|
|
369
|
-
* Set the length of the array
|
|
370
|
-
*/
|
|
371
|
-
set length(value) {
|
|
372
|
-
if (typeof value === "number" && value >= 0 && value !== this.state.value.length) {
|
|
373
|
-
this.get().length = value;
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
/**
|
|
377
|
-
* Clear the array
|
|
378
|
-
*/
|
|
379
|
-
clear() {
|
|
380
|
-
this.length = 0;
|
|
381
|
-
}
|
|
382
|
-
get(first) {
|
|
383
|
-
if (typeof first === "number") {
|
|
384
|
-
return getReactiveValueInProxy(this, __privateGet$1(this, _indiced), first, true).get();
|
|
385
|
-
}
|
|
386
|
-
if (first === "length") {
|
|
387
|
-
return this.length;
|
|
388
|
-
}
|
|
389
|
-
return getValue$1(this.state);
|
|
390
|
-
}
|
|
391
|
-
/**
|
|
392
|
-
* Create a computed, filtered array
|
|
393
|
-
*/
|
|
394
|
-
filter(callback) {
|
|
395
|
-
return computed(() => this.get().filter(callback));
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* Create a computed, mapped array
|
|
399
|
-
*/
|
|
400
|
-
map(callback) {
|
|
401
|
-
return computed(() => this.get().map(callback));
|
|
402
|
-
}
|
|
403
|
-
peek(value) {
|
|
404
|
-
if (value === true) {
|
|
405
|
-
return __privateGet$1(this, _size).peek();
|
|
406
|
-
}
|
|
407
|
-
if (typeof value === "number") {
|
|
408
|
-
return this.state.value.at(value);
|
|
409
|
-
}
|
|
410
|
-
return [...this.state.value];
|
|
411
|
-
}
|
|
412
|
-
/**
|
|
413
|
-
* Remove and return the last item of the array
|
|
414
|
-
*/
|
|
415
|
-
pop() {
|
|
416
|
-
return this.state.value.pop();
|
|
417
|
-
}
|
|
418
|
-
/**
|
|
419
|
-
* Add items to the end of the array
|
|
420
|
-
*/
|
|
421
|
-
push(...items) {
|
|
422
|
-
return this.state.value.push(...items);
|
|
423
|
-
}
|
|
424
|
-
set(first, second) {
|
|
425
|
-
if (first == null || Array.isArray(first)) {
|
|
426
|
-
this.state.value.splice(0, this.state.value.length, ...first ?? []);
|
|
427
|
-
} else if (first === "length") {
|
|
428
|
-
this.length = second;
|
|
429
|
-
} else if (typeof first === "number") {
|
|
430
|
-
this.state.value[first] = second;
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
/**
|
|
434
|
-
* Remove and return the first item of the array
|
|
435
|
-
*/
|
|
436
|
-
shift() {
|
|
437
|
-
return this.state.value.shift();
|
|
438
|
-
}
|
|
439
|
-
/**
|
|
440
|
-
* Remove and return items from the array _(and optionally add new items)_
|
|
441
|
-
*/
|
|
442
|
-
splice(from, to, ...items) {
|
|
443
|
-
return this.state.value.splice(
|
|
444
|
-
from,
|
|
445
|
-
to ?? this.state.value.length,
|
|
446
|
-
...items
|
|
447
|
-
);
|
|
448
|
-
}
|
|
449
|
-
subscribe(first, second) {
|
|
450
|
-
if (typeof first === "number" && typeof second === "function") {
|
|
451
|
-
return getReactiveValueInProxy(
|
|
452
|
-
this,
|
|
453
|
-
__privateGet$1(this, _indiced),
|
|
454
|
-
first,
|
|
455
|
-
true
|
|
456
|
-
).subscribe(second);
|
|
457
|
-
}
|
|
458
|
-
return typeof first === "function" ? subscribe(this.state, first) : noop;
|
|
459
|
-
}
|
|
460
|
-
/**
|
|
461
|
-
* Add items to the beginning of the array
|
|
462
|
-
*/
|
|
463
|
-
unshift(...items) {
|
|
464
|
-
return this.state.value.unshift(...items);
|
|
465
|
-
}
|
|
466
|
-
/**
|
|
467
|
-
* Update the value _(based on the current value)_
|
|
468
|
-
*/
|
|
469
|
-
update(callback) {
|
|
470
|
-
const updated = callback(this.state.value);
|
|
471
|
-
if (updated == null || Array.isArray(updated)) {
|
|
472
|
-
this.set(updated);
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
_indiced = new WeakMap();
|
|
477
|
-
_size = new WeakMap();
|
|
478
337
|
function array(value, options) {
|
|
479
|
-
|
|
480
|
-
}
|
|
481
|
-
function updateArray(type,
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
return result;
|
|
494
|
-
};
|
|
495
|
-
}
|
|
496
|
-
const lengthAffectingMethods = /* @__PURE__ */ new Set([
|
|
497
|
-
"pop",
|
|
498
|
-
"push",
|
|
499
|
-
"shift",
|
|
500
|
-
"unshift"
|
|
501
|
-
]);
|
|
502
|
-
const updateMethods = /* @__PURE__ */ new Set([
|
|
503
|
-
...lengthAffectingMethods,
|
|
504
|
-
"copyWithin",
|
|
505
|
-
"fill",
|
|
506
|
-
"reverse",
|
|
507
|
-
"sort",
|
|
508
|
-
"splice"
|
|
509
|
-
]);
|
|
510
|
-
|
|
511
|
-
function isKey(value) {
|
|
512
|
-
return typeof value === "number" || typeof value === "string";
|
|
513
|
-
}
|
|
514
|
-
function isPlainObject$1(value) {
|
|
515
|
-
if (value === null || typeof value !== "object") {
|
|
516
|
-
return false;
|
|
517
|
-
}
|
|
518
|
-
if (Symbol.toStringTag in value || Symbol.iterator in value) {
|
|
519
|
-
return false;
|
|
520
|
-
}
|
|
521
|
-
const prototype = Object.getPrototypeOf(value);
|
|
522
|
-
return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
|
|
338
|
+
return new ReactiveArray(Array.isArray(value) ? value : [], options);
|
|
339
|
+
}
|
|
340
|
+
function updateArray(type, array$1, state, length) {
|
|
341
|
+
const affectsLength = METHODS_AFFECTING_LENGTH.has(type);
|
|
342
|
+
const previousArray = affectsLength ? [] : [...array$1];
|
|
343
|
+
const previousLength = array$1.length;
|
|
344
|
+
return (...args) => {
|
|
345
|
+
const result = array$1[type](...args);
|
|
346
|
+
if (affectsLength ? array$1.length !== previousLength : !equalArrays(state, previousArray, array$1)) {
|
|
347
|
+
emitValue(state);
|
|
348
|
+
length.set(array$1.length);
|
|
349
|
+
}
|
|
350
|
+
return result;
|
|
351
|
+
};
|
|
523
352
|
}
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
};
|
|
528
|
-
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
529
|
-
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
530
|
-
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
531
|
-
var _keyed;
|
|
532
|
-
class Store extends Reactive {
|
|
533
|
-
constructor(value, options) {
|
|
534
|
-
super(
|
|
535
|
-
storeName,
|
|
536
|
-
new Proxy(value, {
|
|
537
|
-
set: (target, property, value2) => setValueInProxy(target, property, value2, this.state, false)
|
|
538
|
-
}),
|
|
539
|
-
options
|
|
540
|
-
);
|
|
541
|
-
__privateAdd(this, _keyed, /* @__PURE__ */ new Map());
|
|
542
|
-
}
|
|
543
|
-
get(key) {
|
|
544
|
-
return isKey(key) ? getReactiveValueInProxy(this, __privateGet(this, _keyed), key, false).get() : getValue$1(this.state);
|
|
545
|
-
}
|
|
546
|
-
peek(key) {
|
|
547
|
-
return isKey(key) ? this.state.value[key] : { ...this.state.value };
|
|
548
|
-
}
|
|
549
|
-
set(first, second) {
|
|
550
|
-
if (isKey(first)) {
|
|
551
|
-
this.state.value[first] = second;
|
|
552
|
-
} else if (first == null || isPlainObject$1(first)) {
|
|
553
|
-
setProxyValue(this.state.value, first ?? {});
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
subscribe(first, second) {
|
|
557
|
-
if (isKey(first) && typeof second === "function") {
|
|
558
|
-
return getReactiveValueInProxy(this, __privateGet(this, _keyed), first, false).subscribe(
|
|
559
|
-
second
|
|
560
|
-
);
|
|
561
|
-
}
|
|
562
|
-
return typeof first === "function" ? subscribe(this.state, first) : noop;
|
|
563
|
-
}
|
|
564
|
-
/**
|
|
565
|
-
* Update the value _(based on the current value)_
|
|
566
|
-
*/
|
|
567
|
-
update(callback) {
|
|
568
|
-
const updated = callback({ ...this.state.value });
|
|
569
|
-
if (updated == null || isPlainObject$1(updated)) {
|
|
570
|
-
setProxyValue(this.state.value, updated ?? {});
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
_keyed = new WeakMap();
|
|
575
|
-
function store(value, options) {
|
|
576
|
-
return new Store(isPlainObject$1(value) ? value : {}, options);
|
|
353
|
+
function setAtIndex(array$1, index, value) {
|
|
354
|
+
const actual = index < 0 ? array$1.length + index : index;
|
|
355
|
+
if (actual > -1) array$1[actual] = value;
|
|
577
356
|
}
|
|
578
357
|
|
|
579
|
-
function
|
|
580
|
-
return value
|
|
358
|
+
function isKey(value) {
|
|
359
|
+
return typeof value === "number" || typeof value === "string";
|
|
581
360
|
}
|
|
582
|
-
function
|
|
583
|
-
|
|
361
|
+
function isPlainObject(value) {
|
|
362
|
+
if (value === null || typeof value !== "object") return false;
|
|
363
|
+
if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
|
|
364
|
+
const prototype = Object.getPrototypeOf(value);
|
|
365
|
+
return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
|
|
584
366
|
}
|
|
585
|
-
var childNodeTypes = new Set([
|
|
586
|
-
1,
|
|
587
|
-
3,
|
|
588
|
-
7,
|
|
589
|
-
8,
|
|
590
|
-
10
|
|
591
|
-
]);
|
|
592
367
|
|
|
593
368
|
function getString(value) {
|
|
594
369
|
if (typeof value === "string") return value;
|
|
@@ -598,23 +373,64 @@ function getString(value) {
|
|
|
598
373
|
return asString.startsWith("[object ") ? JSON.stringify(value) : asString;
|
|
599
374
|
}
|
|
600
375
|
|
|
601
|
-
function
|
|
602
|
-
|
|
603
|
-
if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
|
|
604
|
-
const prototype = Object.getPrototypeOf(value);
|
|
605
|
-
return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
|
|
376
|
+
function isNullableOrWhitespace(value) {
|
|
377
|
+
return value == null || EXPRESSION_WHITESPACE.test(getString(value));
|
|
606
378
|
}
|
|
379
|
+
var EXPRESSION_WHITESPACE = /^\s*$/;
|
|
607
380
|
|
|
608
|
-
|
|
609
|
-
|
|
381
|
+
var Store = class extends Reactive {
|
|
382
|
+
#keyed = /* @__PURE__ */ new Map();
|
|
383
|
+
constructor(value, options) {
|
|
384
|
+
super(NAME_STORE, new Proxy(value, { set: (target, property, value$1) => setValueInProxy({
|
|
385
|
+
target,
|
|
386
|
+
property,
|
|
387
|
+
value: value$1,
|
|
388
|
+
isArray: false,
|
|
389
|
+
state: this.state
|
|
390
|
+
}) }), options);
|
|
391
|
+
}
|
|
392
|
+
get(key) {
|
|
393
|
+
return isKey(key) ? getReactiveValueInProxy(this, this.#keyed, key, false).get() : getValue$1(this.state);
|
|
394
|
+
}
|
|
395
|
+
peek(key) {
|
|
396
|
+
return isKey(key) ? this.state.value[key] : { ...this.state.value };
|
|
397
|
+
}
|
|
398
|
+
set(first, second) {
|
|
399
|
+
if (isKey(first)) this.state.value[first] = second;
|
|
400
|
+
else if (first == null || isPlainObject(first)) setProxyValue(this.state.value, first ?? {});
|
|
401
|
+
}
|
|
402
|
+
subscribe(first, second) {
|
|
403
|
+
if (isKey(first) && typeof second === "function") return getReactiveValueInProxy(this, this.#keyed, first, false).subscribe(second);
|
|
404
|
+
return typeof first === "function" ? subscribe(this.state, first) : noop;
|
|
405
|
+
}
|
|
406
|
+
update(callback) {
|
|
407
|
+
const updated = callback({ ...this.state.value });
|
|
408
|
+
if (updated == null || isPlainObject(updated)) setProxyValue(this.state.value, updated ?? {});
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
function store(value, options) {
|
|
412
|
+
return new Store(isPlainObject(value) ? value : {}, options);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function isChildNode(value) {
|
|
416
|
+
return value instanceof Node && CHILD_NODE_TYPES.has(value.nodeType);
|
|
417
|
+
}
|
|
418
|
+
function isHTMLOrSVGElement(value) {
|
|
419
|
+
return value instanceof HTMLElement || value instanceof SVGElement;
|
|
610
420
|
}
|
|
611
|
-
var
|
|
421
|
+
var CHILD_NODE_TYPES = new Set([
|
|
422
|
+
Node.ELEMENT_NODE,
|
|
423
|
+
Node.TEXT_NODE,
|
|
424
|
+
Node.PROCESSING_INSTRUCTION_NODE,
|
|
425
|
+
Node.COMMENT_NODE,
|
|
426
|
+
Node.DOCUMENT_TYPE_NODE
|
|
427
|
+
]);
|
|
612
428
|
|
|
613
429
|
function isAttribute(value) {
|
|
614
430
|
return value instanceof Attr || isPlainObject(value) && typeof value.name === "string" && typeof value.value === "string";
|
|
615
431
|
}
|
|
616
432
|
function isBadAttribute(first, second) {
|
|
617
|
-
return validateAttribute((attribute) => attribute == null ||
|
|
433
|
+
return validateAttribute((attribute) => attribute == null || EXPRESSION_ON_PREFIX.test(attribute.name) || EXPRESSION_SOURCE_PREFIX.test(attribute.name) && EXPRESSION_VALUE_PREFIX.test(String(attribute.value)), first, second);
|
|
618
434
|
}
|
|
619
435
|
function isBooleanAttribute(value) {
|
|
620
436
|
return validateAttribute((attribute) => attribute != null && booleanAttributes.includes(attribute.name.toLowerCase()), value, "");
|
|
@@ -636,13 +452,16 @@ function isProperty(value) {
|
|
|
636
452
|
function setAttribute$1(element, first, second) {
|
|
637
453
|
updateValue(element, first, second, updateAttribute);
|
|
638
454
|
}
|
|
455
|
+
function setProperty(element, first, second) {
|
|
456
|
+
updateValue(element, first, second, updateProperty$1);
|
|
457
|
+
}
|
|
639
458
|
function updateAttribute(element, name, value) {
|
|
640
|
-
if (booleanAttributes.includes(name.toLowerCase())) updateProperty$1(element, name, value);
|
|
459
|
+
if (booleanAttributes.includes(name.toLowerCase())) updateProperty$1(element, name, value, false);
|
|
641
460
|
else if (value == null) element.removeAttribute(name);
|
|
642
461
|
else element.setAttribute(name, typeof value === "string" ? value : getString(value));
|
|
643
462
|
}
|
|
644
463
|
function updateProperty$1(element, name, value, validate) {
|
|
645
|
-
const actual = name;
|
|
464
|
+
const actual = validate ?? true ? name.toLowerCase() : name;
|
|
646
465
|
if (actual === "hidden") element.hidden = value === "" || value === true;
|
|
647
466
|
else element[actual] = value === "" || typeof value === "string" && value.toLowerCase() === actual || value === true;
|
|
648
467
|
}
|
|
@@ -660,6 +479,9 @@ function validateAttribute(callback, first, second) {
|
|
|
660
479
|
};
|
|
661
480
|
return callback(attribute);
|
|
662
481
|
}
|
|
482
|
+
var EXPRESSION_ON_PREFIX = /^on/i;
|
|
483
|
+
var EXPRESSION_SOURCE_PREFIX = /^(href|src|xlink:href)$/i;
|
|
484
|
+
var EXPRESSION_VALUE_PREFIX = /(data:text\/html|javascript:)/i;
|
|
663
485
|
const booleanAttributes = Object.freeze([
|
|
664
486
|
"async",
|
|
665
487
|
"autofocus",
|
|
@@ -686,18 +508,7 @@ const booleanAttributes = Object.freeze([
|
|
|
686
508
|
"reversed",
|
|
687
509
|
"selected"
|
|
688
510
|
]);
|
|
689
|
-
var onPrefix = /^on/i;
|
|
690
|
-
var sourcePrefix = /^(href|src|xlink:href)$/i;
|
|
691
|
-
var valuePrefix = /(data:text\/html|javascript:)/i;
|
|
692
511
|
|
|
693
|
-
function getOptions$1(input) {
|
|
694
|
-
const options = isPlainObject(input) ? input : {};
|
|
695
|
-
options.sanitizeBooleanAttributes = typeof options.sanitizeBooleanAttributes === "boolean" ? options.sanitizeBooleanAttributes : true;
|
|
696
|
-
return options;
|
|
697
|
-
}
|
|
698
|
-
function sanitize(value, options) {
|
|
699
|
-
return sanitizeNodes(Array.isArray(value) ? value : [value], getOptions$1(options));
|
|
700
|
-
}
|
|
701
512
|
function sanitizeAttributes(element, attributes, options) {
|
|
702
513
|
const { length } = attributes;
|
|
703
514
|
for (let index = 0; index < length; index += 1) {
|
|
@@ -706,54 +517,199 @@ function sanitizeAttributes(element, attributes, options) {
|
|
|
706
517
|
else if (options.sanitizeBooleanAttributes && isInvalidBooleanAttribute(attribute)) element.setAttribute(attribute.name, "");
|
|
707
518
|
}
|
|
708
519
|
}
|
|
709
|
-
function sanitizeNodes(nodes, options) {
|
|
520
|
+
function sanitizeNodes$1(nodes, options) {
|
|
710
521
|
const actual = nodes.filter((node) => node instanceof Node);
|
|
711
522
|
const { length } = nodes;
|
|
712
523
|
for (let index = 0; index < length; index += 1) {
|
|
713
524
|
const node = actual[index];
|
|
714
|
-
if (node instanceof Element)
|
|
715
|
-
|
|
525
|
+
if (node instanceof Element) {
|
|
526
|
+
const scripts = node.querySelectorAll("script");
|
|
527
|
+
for (const script of scripts) script.remove();
|
|
528
|
+
sanitizeAttributes(node, [...node.attributes], options);
|
|
529
|
+
}
|
|
530
|
+
if (node.hasChildNodes()) sanitizeNodes$1([...node.childNodes], options);
|
|
716
531
|
}
|
|
717
532
|
return nodes;
|
|
718
533
|
}
|
|
719
534
|
|
|
720
|
-
function createTemplate(html$1) {
|
|
535
|
+
function createTemplate(html$1, ignore) {
|
|
721
536
|
const template = document.createElement("template");
|
|
722
537
|
template.innerHTML = html$1;
|
|
723
|
-
templates[html$1] = template;
|
|
538
|
+
if (!ignore) templates[html$1] = template;
|
|
724
539
|
return template;
|
|
725
540
|
}
|
|
726
|
-
function
|
|
727
|
-
if (typeof value !== "string" || value.trim().length === 0) return;
|
|
728
|
-
if (value in templates) return templates[value];
|
|
729
|
-
let template;
|
|
730
|
-
if (idPattern.test(value)) template = document.querySelector(`#${value}`);
|
|
731
|
-
templates[value] = template instanceof HTMLTemplateElement ? template : createTemplate(value);
|
|
732
|
-
return templates[value];
|
|
733
|
-
}
|
|
734
|
-
function html$1(value, sanitization) {
|
|
541
|
+
function getHtml(value, options) {
|
|
735
542
|
if (typeof value !== "string" && !(value instanceof HTMLTemplateElement)) return [];
|
|
736
|
-
const
|
|
737
|
-
const template = value instanceof HTMLTemplateElement ? value : getTemplate(value);
|
|
543
|
+
const template = value instanceof HTMLTemplateElement ? value : getTemplate(value, options.ignoreCache);
|
|
738
544
|
if (template == null) return [];
|
|
739
545
|
const cloned = template.content.cloneNode(true);
|
|
740
546
|
const scripts = cloned.querySelectorAll("script");
|
|
741
|
-
const
|
|
742
|
-
for (let index = 0; index < length; index += 1) scripts[index].remove();
|
|
547
|
+
for (const script of scripts) script.remove();
|
|
743
548
|
cloned.normalize();
|
|
744
|
-
return
|
|
549
|
+
return sanitizeNodes$1([...cloned.childNodes], options);
|
|
550
|
+
}
|
|
551
|
+
function getOptions$1(input) {
|
|
552
|
+
const options = isPlainObject(input) ? input : {};
|
|
553
|
+
options.ignoreCache = typeof options.ignoreCache === "boolean" ? options.ignoreCache : false;
|
|
554
|
+
options.sanitizeBooleanAttributes = typeof options.sanitizeBooleanAttributes === "boolean" ? options.sanitizeBooleanAttributes : true;
|
|
555
|
+
return options;
|
|
556
|
+
}
|
|
557
|
+
function getTemplate(value, ignore) {
|
|
558
|
+
if (typeof value !== "string" || value.trim().length === 0) return;
|
|
559
|
+
let template = templates[value];
|
|
560
|
+
if (template != null) return template;
|
|
561
|
+
const element = EXPRESSION_ID.test(value) ? document.querySelector(`#${value}`) : null;
|
|
562
|
+
template = element instanceof HTMLTemplateElement ? element : createTemplate(value, ignore);
|
|
563
|
+
return template;
|
|
745
564
|
}
|
|
746
|
-
var
|
|
565
|
+
var html$1 = ((value, options) => {
|
|
566
|
+
return getHtml(value, getOptions$1(options));
|
|
567
|
+
});
|
|
568
|
+
html$1.clear = () => {
|
|
569
|
+
templates = {};
|
|
570
|
+
};
|
|
571
|
+
html$1.remove = (template) => {
|
|
572
|
+
if (typeof template !== "string" || templates[template] == null) return;
|
|
573
|
+
const keys = Object.keys(templates);
|
|
574
|
+
const { length } = keys;
|
|
575
|
+
const updated = {};
|
|
576
|
+
for (let index = 0; index < length; index += 1) {
|
|
577
|
+
const key = keys[index];
|
|
578
|
+
if (key !== template) updated[key] = templates[key];
|
|
579
|
+
}
|
|
580
|
+
templates = updated;
|
|
581
|
+
};
|
|
582
|
+
var EXPRESSION_ID = /^[a-z][\w-]*$/i;
|
|
747
583
|
var templates = {};
|
|
748
584
|
|
|
749
|
-
|
|
750
|
-
const
|
|
751
|
-
const
|
|
585
|
+
function compareArrays(first, second) {
|
|
586
|
+
const firstIsLarger = first.length > second.length;
|
|
587
|
+
const from = firstIsLarger ? first : second;
|
|
588
|
+
const to = firstIsLarger ? second : first;
|
|
589
|
+
if (!from
|
|
590
|
+
.filter(key => to.includes(key))
|
|
591
|
+
.every((key, index) => to[index] === key)) {
|
|
592
|
+
return 'dissimilar';
|
|
593
|
+
}
|
|
594
|
+
return firstIsLarger ? 'removed' : 'added';
|
|
595
|
+
}
|
|
596
|
+
function isFragment(value) {
|
|
597
|
+
return (typeof value === 'object' &&
|
|
598
|
+
value != null &&
|
|
599
|
+
'$fragment' in value &&
|
|
600
|
+
value.$fragment === true);
|
|
601
|
+
}
|
|
602
|
+
function isFragments(value) {
|
|
603
|
+
return (typeof value === 'object' &&
|
|
604
|
+
value != null &&
|
|
605
|
+
'$fragments' in value &&
|
|
606
|
+
value.$fragments === true);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
class Fragments {
|
|
610
|
+
#state;
|
|
611
|
+
/**
|
|
612
|
+
* Fragment items
|
|
613
|
+
*/
|
|
614
|
+
get items() {
|
|
615
|
+
return this.#state.mapped;
|
|
616
|
+
}
|
|
617
|
+
constructor(items, identify, fragment) {
|
|
618
|
+
Object.defineProperty(this, '$fragments', {
|
|
619
|
+
value: true,
|
|
620
|
+
});
|
|
621
|
+
this.#state = {
|
|
622
|
+
fragment,
|
|
623
|
+
identify,
|
|
624
|
+
array: items,
|
|
625
|
+
instances: {},
|
|
626
|
+
mapped: array([]),
|
|
627
|
+
subscriber: undefined,
|
|
628
|
+
};
|
|
629
|
+
states.set(this, this.#state);
|
|
630
|
+
initializeFragments(this.#state);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
function handleFragments(item, remove) {
|
|
634
|
+
const state = isFragments(item) ? states.get(item) : item;
|
|
635
|
+
if (state != null) {
|
|
636
|
+
(remove ? removeFragments$1 : initializeFragments)(state);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
function handleItems(state, items) {
|
|
640
|
+
const keys = new Set();
|
|
641
|
+
const mapped = [];
|
|
642
|
+
const { length } = items;
|
|
643
|
+
for (let index = 0; index < length; index += 1) {
|
|
644
|
+
const item = items[index];
|
|
645
|
+
const identifier = state.identify(item);
|
|
646
|
+
if (identifier == null) {
|
|
647
|
+
throw new Error('Identifier cannot be null or undefined');
|
|
648
|
+
}
|
|
649
|
+
const key = getString(identifier);
|
|
650
|
+
if (keys.has(key)) {
|
|
651
|
+
throw new Error(`Duplicate identifier found: "${key}"`);
|
|
652
|
+
}
|
|
653
|
+
let instance = state.instances[key];
|
|
654
|
+
if (instance == null) {
|
|
655
|
+
instance = state.fragment(item);
|
|
656
|
+
if (!isFragment(instance)) {
|
|
657
|
+
throw new Error('Fragment function must return a Fragment instance');
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
instance.identify(key);
|
|
661
|
+
state.instances[key] = instance;
|
|
662
|
+
keys.add(key);
|
|
663
|
+
mapped.push(instance);
|
|
664
|
+
}
|
|
665
|
+
state.mapped.set(mapped);
|
|
666
|
+
updateFragments(state, keys);
|
|
667
|
+
}
|
|
668
|
+
function initializeFragments(state) {
|
|
669
|
+
state.subscriber ??= state.array.subscribe(items => {
|
|
670
|
+
handleItems(state, items);
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
function removeFragments$1(state) {
|
|
674
|
+
state.subscriber?.();
|
|
675
|
+
updateFragments(state);
|
|
676
|
+
state.subscriber = undefined;
|
|
677
|
+
}
|
|
678
|
+
function updateFragments(state, active) {
|
|
679
|
+
const next = {};
|
|
680
|
+
const previous = { ...state.instances };
|
|
681
|
+
const keys = Object.keys(previous);
|
|
682
|
+
const { length } = keys;
|
|
683
|
+
for (let index = 0; index < length; index += 1) {
|
|
684
|
+
const key = keys[index];
|
|
685
|
+
if (active?.has(key)) {
|
|
686
|
+
next[key] = previous[key];
|
|
687
|
+
}
|
|
688
|
+
else {
|
|
689
|
+
previous[key].remove();
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
state.instances = next;
|
|
693
|
+
active?.clear();
|
|
694
|
+
}
|
|
695
|
+
//
|
|
696
|
+
const states = new WeakMap();
|
|
697
|
+
|
|
698
|
+
const ABORT_CONTROLLERS = new WeakMap();
|
|
699
|
+
const ATTRIBUTE_CLASS_PREFIX_LENGTH = 6;
|
|
700
|
+
const EXPRESSION_ATTRIBUTE_CLASS = /^class\./;
|
|
701
|
+
const EXPRESSION_ATTRIBUTE_STYLE_FULL = /^style\.([\w-]+)(?:\.([\w-]+))?$/;
|
|
702
|
+
const EXPRESSION_ATTRIBUTE_STYLE_PREFIX = /^style\./;
|
|
703
|
+
const EXPRESSION_COMMENT_FULL = /^<!--abydon\.(\d+)-->$/;
|
|
704
|
+
const EXPRESSION_COMMENT_CONTENT = /^abydon\.(\d+)$/;
|
|
705
|
+
const EXPRESSION_EVENT_NAME = /^@([\w-]+)(?::([a-z:]+))?$/i;
|
|
706
|
+
const REASON_EVENT_REMOVED = 'Event removed as element was removed from document by Abydon';
|
|
707
|
+
|
|
752
708
|
function getController(element) {
|
|
753
|
-
let controller =
|
|
709
|
+
let controller = ABORT_CONTROLLERS.get(element);
|
|
754
710
|
if (controller == null) {
|
|
755
711
|
controller = new AbortController();
|
|
756
|
-
|
|
712
|
+
ABORT_CONTROLLERS.set(element, controller);
|
|
757
713
|
}
|
|
758
714
|
return controller;
|
|
759
715
|
}
|
|
@@ -762,12 +718,12 @@ function getOptions(options) {
|
|
|
762
718
|
return {
|
|
763
719
|
capture: parts.includes('c') || parts.includes('capture'),
|
|
764
720
|
once: parts.includes('o') || parts.includes('once'),
|
|
765
|
-
passive: !parts.includes('a')
|
|
721
|
+
passive: !(parts.includes('a') || parts.includes('active')),
|
|
766
722
|
};
|
|
767
723
|
}
|
|
768
724
|
function mapEvent(element, name, value) {
|
|
769
725
|
element.removeAttribute(name);
|
|
770
|
-
const [, type, options] =
|
|
726
|
+
const [, type, options] = EXPRESSION_EVENT_NAME.exec(name) ?? [];
|
|
771
727
|
if (typeof value === 'function' && type != null) {
|
|
772
728
|
element.addEventListener(type, value, {
|
|
773
729
|
...getOptions(options ?? ''),
|
|
@@ -776,26 +732,8 @@ function mapEvent(element, name, value) {
|
|
|
776
732
|
}
|
|
777
733
|
}
|
|
778
734
|
function removeEvents(element) {
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
function compareArrays(first, second) {
|
|
784
|
-
const firstIsLarger = first.length > second.length;
|
|
785
|
-
const from = firstIsLarger ? first : second;
|
|
786
|
-
const to = firstIsLarger ? second : first;
|
|
787
|
-
if (!from
|
|
788
|
-
.filter(key => to.includes(key))
|
|
789
|
-
.every((key, index) => to[index] === key)) {
|
|
790
|
-
return 'dissimilar';
|
|
791
|
-
}
|
|
792
|
-
return firstIsLarger ? 'removed' : 'added';
|
|
793
|
-
}
|
|
794
|
-
function isFragment(value) {
|
|
795
|
-
return (typeof value === 'object' &&
|
|
796
|
-
value != null &&
|
|
797
|
-
'$fragment' in value &&
|
|
798
|
-
value.$fragment === true);
|
|
735
|
+
ABORT_CONTROLLERS.get(element)?.abort(REASON_EVENT_REMOVED);
|
|
736
|
+
ABORT_CONTROLLERS.delete(element);
|
|
799
737
|
}
|
|
800
738
|
|
|
801
739
|
function createNodes(value) {
|
|
@@ -808,7 +746,7 @@ function createNodes(value) {
|
|
|
808
746
|
return [new Text(getString(value))];
|
|
809
747
|
}
|
|
810
748
|
function removeNodes(nodes) {
|
|
811
|
-
|
|
749
|
+
sanitizeNodes(nodes);
|
|
812
750
|
const { length } = nodes;
|
|
813
751
|
for (let index = 0; index < length; index += 1) {
|
|
814
752
|
nodes[index].remove();
|
|
@@ -821,7 +759,7 @@ function replaceNodes(from, to) {
|
|
|
821
759
|
from[index].remove();
|
|
822
760
|
}
|
|
823
761
|
}
|
|
824
|
-
function
|
|
762
|
+
function sanitizeNodes(nodes) {
|
|
825
763
|
const { length } = nodes;
|
|
826
764
|
for (let index = 0; index < length; index += 1) {
|
|
827
765
|
const node = nodes[index];
|
|
@@ -829,21 +767,18 @@ function sanitiseNodes(nodes) {
|
|
|
829
767
|
removeEvents(node);
|
|
830
768
|
}
|
|
831
769
|
if (node.hasChildNodes()) {
|
|
832
|
-
|
|
770
|
+
sanitizeNodes([...node.childNodes]);
|
|
833
771
|
}
|
|
834
772
|
}
|
|
835
773
|
}
|
|
836
774
|
|
|
837
|
-
const classExpression = /^class\./;
|
|
838
|
-
const styleFullExpression = /^style\.([\w-]+)(?:\.([\w-]+))?$/;
|
|
839
|
-
const stylePrefixExpression = /^style\./;
|
|
840
775
|
function setAttribute(data, element, name, value) {
|
|
841
776
|
element.removeAttribute(name);
|
|
842
777
|
switch (true) {
|
|
843
|
-
case
|
|
778
|
+
case EXPRESSION_ATTRIBUTE_CLASS.test(name):
|
|
844
779
|
setClasses(data, element, name, value);
|
|
845
780
|
return;
|
|
846
|
-
case
|
|
781
|
+
case EXPRESSION_ATTRIBUTE_STYLE_PREFIX.test(name):
|
|
847
782
|
setStyle(data, element, name, value);
|
|
848
783
|
return;
|
|
849
784
|
default:
|
|
@@ -860,7 +795,7 @@ function setClasses(data, element, name, value) {
|
|
|
860
795
|
element.classList.remove(...classes);
|
|
861
796
|
}
|
|
862
797
|
}
|
|
863
|
-
const classes = name.slice(
|
|
798
|
+
const classes = name.slice(ATTRIBUTE_CLASS_PREFIX_LENGTH).split('.');
|
|
864
799
|
if (isReactive(value)) {
|
|
865
800
|
data.mora.subscribers.add(value.subscribe(update));
|
|
866
801
|
}
|
|
@@ -869,6 +804,10 @@ function setClasses(data, element, name, value) {
|
|
|
869
804
|
}
|
|
870
805
|
}
|
|
871
806
|
function setStyle(data, element, name, value) {
|
|
807
|
+
const [, property, unit] = EXPRESSION_ATTRIBUTE_STYLE_FULL.exec(name) ?? [];
|
|
808
|
+
if (property == null) {
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
872
811
|
function update(value) {
|
|
873
812
|
if (value == null || value === false || (value === true && unit == null)) {
|
|
874
813
|
element.style.removeProperty(property);
|
|
@@ -877,22 +816,21 @@ function setStyle(data, element, name, value) {
|
|
|
877
816
|
element.style.setProperty(property, value === true ? unit : getString(value));
|
|
878
817
|
}
|
|
879
818
|
}
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
else {
|
|
886
|
-
update(value);
|
|
887
|
-
}
|
|
819
|
+
if (isReactive(value)) {
|
|
820
|
+
data.mora.subscribers.add(value.subscribe(update));
|
|
821
|
+
}
|
|
822
|
+
else {
|
|
823
|
+
update(value);
|
|
888
824
|
}
|
|
889
825
|
}
|
|
890
826
|
function setValue(data, element, name, value) {
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
827
|
+
let callback;
|
|
828
|
+
if (isBooleanAttribute(name) && name in element) {
|
|
829
|
+
callback = name === 'selected' ? updateSelected : updateProperty;
|
|
830
|
+
}
|
|
831
|
+
else {
|
|
832
|
+
callback = setAttribute$1;
|
|
833
|
+
}
|
|
896
834
|
if (isReactive(value)) {
|
|
897
835
|
data.mora.subscribers.add(value.subscribe(next => {
|
|
898
836
|
callback(element, name, next);
|
|
@@ -902,11 +840,6 @@ function setValue(data, element, name, value) {
|
|
|
902
840
|
callback(element, name, value);
|
|
903
841
|
}
|
|
904
842
|
}
|
|
905
|
-
function triggerSelectChange(select) {
|
|
906
|
-
if (select != null) {
|
|
907
|
-
select.dispatchEvent(new Event('change', { bubbles: true }));
|
|
908
|
-
}
|
|
909
|
-
}
|
|
910
843
|
function updateProperty(element, name, value) {
|
|
911
844
|
element[name] = value === true;
|
|
912
845
|
}
|
|
@@ -914,14 +847,13 @@ function updateSelected(element, name, value) {
|
|
|
914
847
|
const select = element.closest('select');
|
|
915
848
|
const options = [...(select?.options ?? [])];
|
|
916
849
|
if (select != null && options.includes(element)) {
|
|
917
|
-
|
|
850
|
+
select.dispatchEvent(new Event('change', { bubbles: true }));
|
|
918
851
|
}
|
|
919
852
|
updateProperty(element, name, value);
|
|
920
853
|
}
|
|
921
854
|
|
|
922
|
-
const commentExpression$1 = /^<!--abydon\.(\d+)-->$/;
|
|
923
855
|
function getValue(data, original) {
|
|
924
|
-
const matches =
|
|
856
|
+
const matches = EXPRESSION_COMMENT_FULL.exec(original ?? '');
|
|
925
857
|
return matches == null ? original : data.values[+matches[1]];
|
|
926
858
|
}
|
|
927
859
|
function mapAttributes(data, element) {
|
|
@@ -930,24 +862,27 @@ function mapAttributes(data, element) {
|
|
|
930
862
|
for (let index = 0; index < length; index += 1) {
|
|
931
863
|
const { name, value } = attributes[index];
|
|
932
864
|
const actual = getValue(data, value);
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
865
|
+
switch (true) {
|
|
866
|
+
case name.startsWith('@'):
|
|
867
|
+
mapEvent(element, name, actual);
|
|
868
|
+
break;
|
|
869
|
+
case name.includes('.') ||
|
|
870
|
+
typeof actual === 'function' ||
|
|
871
|
+
isReactive(actual):
|
|
872
|
+
mapValue$1(data, element, name, actual);
|
|
873
|
+
break;
|
|
874
|
+
case isBooleanAttribute(name):
|
|
875
|
+
setProperty(element, name, value);
|
|
876
|
+
break;
|
|
940
877
|
}
|
|
941
878
|
}
|
|
942
879
|
}
|
|
943
880
|
function mapValue$1(data, element, name, value) {
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
setAttribute(data, element, name, value);
|
|
950
|
-
break;
|
|
881
|
+
if (typeof value === 'function') {
|
|
882
|
+
setComputedAttribute(data, element, name, value);
|
|
883
|
+
}
|
|
884
|
+
else {
|
|
885
|
+
setAttribute(data, element, name, value);
|
|
951
886
|
}
|
|
952
887
|
}
|
|
953
888
|
function setComputedAttribute(data, element, name, callback) {
|
|
@@ -956,6 +891,44 @@ function setComputedAttribute(data, element, name, callback) {
|
|
|
956
891
|
setAttribute(data, element, name, value);
|
|
957
892
|
}
|
|
958
893
|
|
|
894
|
+
//
|
|
895
|
+
function addToArray(identifiers, items, nodes, added) {
|
|
896
|
+
let position = nodes[0];
|
|
897
|
+
const before = added && !identifiers.previous.includes(items.templates[0].identifier);
|
|
898
|
+
const next = items.next.flatMap(fragment => fragment.get().flatMap(node => ({
|
|
899
|
+
identifier: fragment.identifier,
|
|
900
|
+
value: node,
|
|
901
|
+
})));
|
|
902
|
+
const { length } = next;
|
|
903
|
+
for (let index = 0; index < length; index += 1) {
|
|
904
|
+
const node = next[index];
|
|
905
|
+
if (!(added && identifiers.previous.includes(node.identifier))) {
|
|
906
|
+
if (index === 0 && before) {
|
|
907
|
+
position.before(node.value);
|
|
908
|
+
}
|
|
909
|
+
else {
|
|
910
|
+
position.after(node.value);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
position = node.value;
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
function handleArray(identifiers, items, nodes) {
|
|
917
|
+
const next = items.templates.map(template => items.fragments?.find(fragment => fragment.identifier === template.identifier) ?? template);
|
|
918
|
+
const comparison = compareArrays(items.fragments ?? [], items.templates);
|
|
919
|
+
if (comparison !== 'removed') {
|
|
920
|
+
addToArray(identifiers, { ...items, next }, nodes, comparison === 'added');
|
|
921
|
+
}
|
|
922
|
+
const toRemove = items.fragments?.filter(fragment => !identifiers.next.includes(fragment.identifier)) ?? [];
|
|
923
|
+
const { length } = toRemove;
|
|
924
|
+
for (let index = 0; index < length; index += 1) {
|
|
925
|
+
toRemove[index].remove();
|
|
926
|
+
}
|
|
927
|
+
return {
|
|
928
|
+
fragments: next,
|
|
929
|
+
nodes: next.flatMap(fragment => fragment.get()),
|
|
930
|
+
};
|
|
931
|
+
}
|
|
959
932
|
function removeFragments(fragments) {
|
|
960
933
|
if (fragments != null) {
|
|
961
934
|
const { length } = fragments;
|
|
@@ -964,133 +937,128 @@ function removeFragments(fragments) {
|
|
|
964
937
|
}
|
|
965
938
|
}
|
|
966
939
|
}
|
|
967
|
-
function
|
|
940
|
+
function replaceText(item, comment, isNullable) {
|
|
941
|
+
let to;
|
|
942
|
+
if (isNullable) {
|
|
943
|
+
to = [comment];
|
|
944
|
+
}
|
|
945
|
+
else {
|
|
946
|
+
to = item.text == null ? [] : [item.text];
|
|
947
|
+
}
|
|
948
|
+
replaceNodes(item.nodes ?? [], to);
|
|
949
|
+
}
|
|
950
|
+
function setArray(item, comment, value) {
|
|
968
951
|
if (value.length === 0) {
|
|
969
952
|
return {
|
|
970
|
-
nodes: setText(
|
|
953
|
+
nodes: setText(item, comment, value),
|
|
971
954
|
};
|
|
972
955
|
}
|
|
973
956
|
let templates = value.filter(item => isFragment(item) && item.identifier != null);
|
|
974
|
-
const
|
|
975
|
-
const
|
|
976
|
-
if (new Set(
|
|
957
|
+
const next = templates.map(fragment => fragment.identifier);
|
|
958
|
+
const previous = item.fragments?.map(fragment => fragment.identifier) ?? [];
|
|
959
|
+
if (new Set(next).size !== templates.length) {
|
|
977
960
|
templates = [];
|
|
978
961
|
}
|
|
979
962
|
const noTemplates = templates.length === 0;
|
|
980
963
|
if (noTemplates ||
|
|
981
|
-
nodes == null ||
|
|
982
|
-
|
|
964
|
+
item.nodes == null ||
|
|
965
|
+
previous.some(identifier => identifier == null)) {
|
|
983
966
|
return {
|
|
984
967
|
fragments: noTemplates ? undefined : templates,
|
|
985
|
-
nodes: setNodes(
|
|
968
|
+
nodes: setNodes(item, comment, noTemplates
|
|
986
969
|
? value.flatMap(item => createNodes(item))
|
|
987
970
|
: templates.flatMap(template => template.get())),
|
|
988
971
|
};
|
|
989
972
|
}
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
identifier: fragment.identifier,
|
|
998
|
-
value: node,
|
|
999
|
-
})));
|
|
1000
|
-
const { length } = items;
|
|
1001
|
-
for (let index = 0; index < length; index += 1) {
|
|
1002
|
-
const item = items[index];
|
|
1003
|
-
if (comparison === 'dissimilar' ||
|
|
1004
|
-
!oldIdentifiers.includes(item.identifier)) {
|
|
1005
|
-
if (index === 0 && before) {
|
|
1006
|
-
position.before(item.value);
|
|
1007
|
-
}
|
|
1008
|
-
else {
|
|
1009
|
-
position.after(item.value);
|
|
1010
|
-
}
|
|
1011
|
-
}
|
|
1012
|
-
position = item.value;
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
const toRemove = fragments?.filter(fragment => !identifiers.includes(fragment.identifier)) ?? [];
|
|
1016
|
-
const { length } = toRemove;
|
|
1017
|
-
for (let index = 0; index < length; index += 1) {
|
|
1018
|
-
toRemove[index].remove();
|
|
1019
|
-
}
|
|
1020
|
-
return {
|
|
1021
|
-
fragments: next,
|
|
1022
|
-
nodes: next.flatMap(fragment => fragment.get()),
|
|
1023
|
-
};
|
|
973
|
+
return handleArray({
|
|
974
|
+
next,
|
|
975
|
+
previous,
|
|
976
|
+
}, {
|
|
977
|
+
templates,
|
|
978
|
+
fragments: item.fragments ?? [],
|
|
979
|
+
}, item.nodes);
|
|
1024
980
|
}
|
|
1025
|
-
function setNodes(
|
|
1026
|
-
if (nodes == null) {
|
|
981
|
+
function setNodes(item, comment, next) {
|
|
982
|
+
if (item.nodes == null) {
|
|
1027
983
|
if (comment.parentNode != null) {
|
|
1028
984
|
replaceNodes([comment], next);
|
|
1029
985
|
}
|
|
1030
|
-
else if (text
|
|
1031
|
-
replaceNodes([text], next);
|
|
986
|
+
else if (item.text?.parentNode != null) {
|
|
987
|
+
replaceNodes([item.text], next);
|
|
1032
988
|
}
|
|
1033
989
|
}
|
|
1034
990
|
else {
|
|
1035
|
-
replaceNodes(nodes, next);
|
|
991
|
+
replaceNodes(item.nodes, next);
|
|
1036
992
|
}
|
|
1037
|
-
removeFragments(fragments);
|
|
993
|
+
removeFragments(item.fragments);
|
|
1038
994
|
return next;
|
|
1039
995
|
}
|
|
1040
996
|
function setReactiveValue(data, comment, reactive) {
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
let nodes;
|
|
997
|
+
let item = data.items.find(item => item.nodes?.includes(comment));
|
|
998
|
+
item ??= {};
|
|
999
|
+
item.text = new Text();
|
|
1045
1000
|
data.mora.subscribers.add(reactive.subscribe(value => {
|
|
1046
1001
|
if (Array.isArray(value)) {
|
|
1047
|
-
|
|
1048
|
-
fragments = typeof result === 'boolean' ? undefined : result?.fragments;
|
|
1049
|
-
nodes =
|
|
1050
|
-
typeof result === 'boolean'
|
|
1051
|
-
? result
|
|
1052
|
-
? [text]
|
|
1053
|
-
: undefined
|
|
1054
|
-
: result?.nodes;
|
|
1002
|
+
setReactiveValueForArray(item, comment, value);
|
|
1055
1003
|
}
|
|
1056
1004
|
else {
|
|
1057
|
-
|
|
1058
|
-
fragments = valueIsFragment ? [value] : undefined;
|
|
1059
|
-
if (valueIsFragment || isChildNode(value)) {
|
|
1060
|
-
nodes = setNodes(fragments, nodes, comment, text, createNodes(value));
|
|
1061
|
-
}
|
|
1062
|
-
else {
|
|
1063
|
-
nodes = setText(fragments, nodes, comment, text, value);
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
if (item != null) {
|
|
1067
|
-
item.fragments = fragments;
|
|
1068
|
-
item.nodes = [...(nodes ?? [comment])];
|
|
1005
|
+
setReactiveValueForSingle(item, comment, value);
|
|
1069
1006
|
}
|
|
1007
|
+
item.nodes = [...(item.nodes ?? [comment])];
|
|
1070
1008
|
}));
|
|
1071
1009
|
}
|
|
1072
|
-
function
|
|
1010
|
+
function setReactiveValueForArray(item, comment, value) {
|
|
1011
|
+
const result = setArray(item, comment, value);
|
|
1012
|
+
item.fragments = typeof result === 'boolean' ? undefined : result?.fragments;
|
|
1013
|
+
if (typeof result === 'boolean') {
|
|
1014
|
+
if (result) {
|
|
1015
|
+
item.nodes = item.text == null ? [] : [item.text];
|
|
1016
|
+
}
|
|
1017
|
+
else {
|
|
1018
|
+
item.nodes = undefined;
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
else {
|
|
1022
|
+
item.nodes = result?.nodes;
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
function setReactiveValueForSingle(item, comment, value) {
|
|
1026
|
+
const valueIsFragment = isFragment(value);
|
|
1027
|
+
item.fragments = valueIsFragment ? [value] : undefined;
|
|
1028
|
+
if (valueIsFragment || isChildNode(value)) {
|
|
1029
|
+
item.nodes = setNodes(item, comment, createNodes(value));
|
|
1030
|
+
}
|
|
1031
|
+
else {
|
|
1032
|
+
item.nodes = setText(item, comment, value);
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
function setText(item, comment, value) {
|
|
1073
1036
|
const isNullable = isNullableOrWhitespace(value);
|
|
1074
|
-
text
|
|
1037
|
+
if (item.text != null) {
|
|
1038
|
+
item.text.textContent = isNullable ? '' : getString(value);
|
|
1039
|
+
}
|
|
1075
1040
|
let result = false;
|
|
1076
|
-
if (nodes != null) {
|
|
1077
|
-
|
|
1041
|
+
if (item.nodes != null) {
|
|
1042
|
+
replaceText(item, comment, isNullable);
|
|
1078
1043
|
result = !isNullable;
|
|
1079
1044
|
}
|
|
1080
1045
|
else if (isNullable && comment.parentNode == null) {
|
|
1081
|
-
text
|
|
1046
|
+
item.text?.replaceWith(comment);
|
|
1082
1047
|
}
|
|
1083
|
-
else if (!isNullable && text
|
|
1084
|
-
|
|
1048
|
+
else if (!isNullable && item?.text?.parentNode == null) {
|
|
1049
|
+
if (item.text != null) {
|
|
1050
|
+
comment.replaceWith(item.text);
|
|
1051
|
+
}
|
|
1085
1052
|
result = true;
|
|
1086
1053
|
}
|
|
1087
|
-
removeFragments(fragments);
|
|
1088
|
-
|
|
1054
|
+
removeFragments(item.fragments);
|
|
1055
|
+
if (result) {
|
|
1056
|
+
return item.text == null ? [] : [item.text];
|
|
1057
|
+
}
|
|
1089
1058
|
}
|
|
1090
1059
|
|
|
1091
|
-
const commentExpression = /^abydon\.(\d+)$/;
|
|
1092
1060
|
function mapNode(data, comment) {
|
|
1093
|
-
const matches =
|
|
1061
|
+
const matches = EXPRESSION_COMMENT_CONTENT.exec(comment.textContent ?? '');
|
|
1094
1062
|
const value = matches == null ? null : data.values[+matches[1]];
|
|
1095
1063
|
if (value != null) {
|
|
1096
1064
|
mapValue(data, comment, value);
|
|
@@ -1117,6 +1085,10 @@ function mapValue(data, comment, value) {
|
|
|
1117
1085
|
case typeof value === 'function':
|
|
1118
1086
|
setComputedValue(data, comment, value);
|
|
1119
1087
|
break;
|
|
1088
|
+
case isFragments(value):
|
|
1089
|
+
handleFragments(value, false);
|
|
1090
|
+
setReactiveValue(data, comment, value.items);
|
|
1091
|
+
break;
|
|
1120
1092
|
case isReactive(value):
|
|
1121
1093
|
setReactiveValue(data, comment, value);
|
|
1122
1094
|
break;
|
|
@@ -1126,7 +1098,7 @@ function mapValue(data, comment, value) {
|
|
|
1126
1098
|
}
|
|
1127
1099
|
}
|
|
1128
1100
|
function replaceComment(data, comment, value) {
|
|
1129
|
-
const item = data.items.find(item => item.nodes
|
|
1101
|
+
const item = data.items.find(item => item.nodes?.includes(comment));
|
|
1130
1102
|
const nodes = createNodes(value);
|
|
1131
1103
|
if (item != null) {
|
|
1132
1104
|
item.fragments = isFragment(value) ? [value] : undefined;
|
|
@@ -1157,22 +1129,36 @@ function handleExpression(data, prefix, expression) {
|
|
|
1157
1129
|
return isNullableOrWhitespace(expression) ? prefix : `${prefix}${expression}`;
|
|
1158
1130
|
}
|
|
1159
1131
|
function parse(data) {
|
|
1132
|
+
if (data.template != null) {
|
|
1133
|
+
return data.template;
|
|
1134
|
+
}
|
|
1160
1135
|
const { length } = data.strings;
|
|
1161
|
-
|
|
1136
|
+
data.template = '';
|
|
1162
1137
|
for (let index = 0; index < length; index += 1) {
|
|
1163
|
-
template += handleExpression(data, data.strings[index], data.expressions[index]);
|
|
1138
|
+
data.template += handleExpression(data, data.strings[index], data.expressions[index]);
|
|
1164
1139
|
}
|
|
1165
|
-
|
|
1140
|
+
data.expressions = [];
|
|
1141
|
+
data.strings = [];
|
|
1142
|
+
return data.template;
|
|
1166
1143
|
}
|
|
1167
1144
|
|
|
1168
1145
|
class Fragment {
|
|
1169
|
-
|
|
1170
|
-
|
|
1146
|
+
#data;
|
|
1147
|
+
#configuration = {
|
|
1148
|
+
identifier: undefined,
|
|
1149
|
+
ignoreCache: false,
|
|
1150
|
+
};
|
|
1151
|
+
/**
|
|
1152
|
+
* Fragment identifier
|
|
1153
|
+
*/
|
|
1171
1154
|
get identifier() {
|
|
1172
|
-
return this.
|
|
1155
|
+
return this.#configuration.identifier;
|
|
1173
1156
|
}
|
|
1174
1157
|
constructor(strings, expressions) {
|
|
1175
|
-
this
|
|
1158
|
+
Object.defineProperty(this, '$fragment', {
|
|
1159
|
+
value: true,
|
|
1160
|
+
});
|
|
1161
|
+
this.#data = {
|
|
1176
1162
|
expressions,
|
|
1177
1163
|
strings,
|
|
1178
1164
|
items: [],
|
|
@@ -1184,52 +1170,90 @@ class Fragment {
|
|
|
1184
1170
|
};
|
|
1185
1171
|
}
|
|
1186
1172
|
/**
|
|
1187
|
-
*
|
|
1173
|
+
* Append the fragment to the given element
|
|
1174
|
+
* @param element Element to append to
|
|
1188
1175
|
*/
|
|
1189
1176
|
appendTo(element) {
|
|
1190
1177
|
element.append(...this.get());
|
|
1191
1178
|
}
|
|
1192
1179
|
/**
|
|
1193
|
-
*
|
|
1180
|
+
* Configure the fragment
|
|
1181
|
+
* @param configuration Configuration options
|
|
1182
|
+
* @returns Fragment
|
|
1183
|
+
*/
|
|
1184
|
+
configure(configuration) {
|
|
1185
|
+
const actual = isPlainObject(configuration) ? configuration : {};
|
|
1186
|
+
if (actual.identifier !== undefined) {
|
|
1187
|
+
this.#configuration.identifier = actual.identifier;
|
|
1188
|
+
}
|
|
1189
|
+
if (typeof actual.ignoreCache === 'boolean') {
|
|
1190
|
+
this.#configuration.ignoreCache = actual.ignoreCache;
|
|
1191
|
+
}
|
|
1192
|
+
return this;
|
|
1193
|
+
}
|
|
1194
|
+
/**
|
|
1195
|
+
* Get a list of the fragment's nodes
|
|
1196
|
+
* @returns List of nodes
|
|
1194
1197
|
*/
|
|
1195
1198
|
get() {
|
|
1196
|
-
|
|
1197
|
-
|
|
1199
|
+
const data = this.#data;
|
|
1200
|
+
if (data.items.length === 0) {
|
|
1201
|
+
const parsed = parse(data);
|
|
1198
1202
|
const templated = html$1(parsed, {
|
|
1203
|
+
ignoreCache: this.#configuration.ignoreCache,
|
|
1199
1204
|
sanitizeBooleanAttributes: false,
|
|
1200
1205
|
});
|
|
1201
|
-
|
|
1206
|
+
data.items.splice(0, data.items.length, ...templated.map(node => ({
|
|
1202
1207
|
nodes: [node],
|
|
1203
1208
|
})));
|
|
1204
|
-
mapNodes(
|
|
1209
|
+
mapNodes(data, data.items.flatMap(item => item.fragments?.flatMap(fragment => fragment.get()) ??
|
|
1210
|
+
item.nodes ??
|
|
1211
|
+
[]));
|
|
1205
1212
|
}
|
|
1206
1213
|
return [
|
|
1207
|
-
...
|
|
1214
|
+
...data.items.flatMap(item => item.fragments?.flatMap(fragment => fragment.get()) ??
|
|
1215
|
+
item.nodes ??
|
|
1216
|
+
[]),
|
|
1208
1217
|
];
|
|
1209
1218
|
}
|
|
1219
|
+
/**
|
|
1220
|
+
* Set an identifier for the fragment
|
|
1221
|
+
*
|
|
1222
|
+
* _An identifier can be used to uniquely identify a fragment,
|
|
1223
|
+
* which helps prevent re-rendering in certain scenarios._
|
|
1224
|
+
* @param identifier Identifier
|
|
1225
|
+
* @returns Fragment
|
|
1226
|
+
*/
|
|
1210
1227
|
identify(identifier) {
|
|
1211
|
-
this.
|
|
1228
|
+
this.#configuration.identifier = identifier;
|
|
1212
1229
|
return this;
|
|
1213
1230
|
}
|
|
1214
1231
|
/**
|
|
1215
|
-
*
|
|
1232
|
+
* Remove the fragment from the DOM
|
|
1216
1233
|
*/
|
|
1217
1234
|
remove() {
|
|
1218
|
-
removeFragment(this
|
|
1235
|
+
removeFragment(this.#data);
|
|
1219
1236
|
}
|
|
1220
1237
|
}
|
|
1221
1238
|
function removeFragment(data) {
|
|
1222
1239
|
removeMora(data);
|
|
1223
|
-
|
|
1240
|
+
let { length } = data.items;
|
|
1224
1241
|
for (let index = 0; index < length; index += 1) {
|
|
1225
1242
|
const { fragments, nodes } = data.items[index];
|
|
1226
|
-
const
|
|
1227
|
-
for (let
|
|
1228
|
-
fragments?.[
|
|
1243
|
+
const fragmentsLength = fragments?.length ?? 0;
|
|
1244
|
+
for (let fragmentIndex = 0; fragmentIndex < fragmentsLength; fragmentIndex += 1) {
|
|
1245
|
+
fragments?.[fragmentIndex]?.remove();
|
|
1246
|
+
}
|
|
1247
|
+
removeNodes(nodes ?? []);
|
|
1248
|
+
}
|
|
1249
|
+
data.items.length = 0;
|
|
1250
|
+
length = data.values.length;
|
|
1251
|
+
for (let index = 0; index < length; index += 1) {
|
|
1252
|
+
const value = data.values[index];
|
|
1253
|
+
if (isFragments(value)) {
|
|
1254
|
+
handleFragments(value, true);
|
|
1229
1255
|
}
|
|
1230
|
-
removeNodes(nodes);
|
|
1231
1256
|
}
|
|
1232
|
-
data.items.splice(0, length);
|
|
1233
1257
|
}
|
|
1234
1258
|
function removeMora(data) {
|
|
1235
1259
|
const unsubscribers = [...data.mora.subscribers];
|
|
@@ -1240,8 +1264,11 @@ function removeMora(data) {
|
|
|
1240
1264
|
}
|
|
1241
1265
|
}
|
|
1242
1266
|
|
|
1267
|
+
function fragments(array, identify, fragment) {
|
|
1268
|
+
return new Fragments(array, identify, fragment);
|
|
1269
|
+
}
|
|
1243
1270
|
function html(strings, ...values) {
|
|
1244
1271
|
return new Fragment(strings, values);
|
|
1245
1272
|
}
|
|
1246
1273
|
|
|
1247
|
-
export { array, computed, effect, html, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch, store };
|
|
1274
|
+
export { array, computed, effect, fragments, html, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch, store };
|