olova 1.0.1 → 1.0.3
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/olova.js +1 -1000
- package/package.json +3 -13
package/dist/olova.js
CHANGED
|
@@ -1,1000 +1 @@
|
|
|
1
|
-
class
|
|
2
|
-
constructor() {
|
|
3
|
-
this.$elements = {};
|
|
4
|
-
this.listeners = {};
|
|
5
|
-
this.components = {};
|
|
6
|
-
this.plugins = {};
|
|
7
|
-
this.refs = {};
|
|
8
|
-
this.$refs = new Proxy(
|
|
9
|
-
{},
|
|
10
|
-
{
|
|
11
|
-
get: (target, key) => {
|
|
12
|
-
return this.refs[key];
|
|
13
|
-
},
|
|
14
|
-
}
|
|
15
|
-
);
|
|
16
|
-
this.data = {};
|
|
17
|
-
this.dependencies = new Map();
|
|
18
|
-
this.subscribers = new Map();
|
|
19
|
-
this.effects = [];
|
|
20
|
-
this.cleanupEffects = [];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
registerPlugin(name, handler) {
|
|
24
|
-
this.plugins[name] = handler;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
registerComponent(name, componentFunction) {
|
|
28
|
-
this.components[name] = componentFunction;
|
|
29
|
-
this.defineCustomElement(name);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
defineCustomElement(name) {
|
|
33
|
-
const deshi = this;
|
|
34
|
-
class CustomElement extends HTMLElement {
|
|
35
|
-
connectedCallback() {
|
|
36
|
-
this.render();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
render() {
|
|
40
|
-
const props = this.getProps();
|
|
41
|
-
const componentFunction = deshi.components[name];
|
|
42
|
-
const renderedContent = componentFunction(props);
|
|
43
|
-
|
|
44
|
-
const tempContainer = document.createElement("div");
|
|
45
|
-
tempContainer.innerHTML = renderedContent.trim();
|
|
46
|
-
|
|
47
|
-
const parent = this.parentNode;
|
|
48
|
-
const renderedElement = tempContainer.firstChild;
|
|
49
|
-
|
|
50
|
-
if (renderedElement) {
|
|
51
|
-
parent.replaceChild(renderedElement, this);
|
|
52
|
-
deshi.applyDirectivesToElement(renderedElement);
|
|
53
|
-
deshi.initReactiveSystem();
|
|
54
|
-
deshi.runEffects();
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
getProps() {
|
|
59
|
-
const props = {};
|
|
60
|
-
for (const attr of this.attributes) {
|
|
61
|
-
props[attr.name] = attr.value;
|
|
62
|
-
}
|
|
63
|
-
return props;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
static get observedAttributes() {
|
|
67
|
-
return Object.keys(deshi.components[name]({}) || {});
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
attributeChangedCallback(name, oldValue, newValue) {
|
|
71
|
-
this.render();
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
customElements.define(name, CustomElement);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
applyDirectivesToElement(element) {
|
|
79
|
-
this.applyShowDirective(element);
|
|
80
|
-
this.applyIfDirective(element);
|
|
81
|
-
this.applyForDirective(element);
|
|
82
|
-
this.applyModelDirective(element);
|
|
83
|
-
this.applyAttrDirective(element);
|
|
84
|
-
this.applyClassDirective(element);
|
|
85
|
-
this.applyStyleDirective(element);
|
|
86
|
-
this.applyBindDirective(element);
|
|
87
|
-
this.applyRefDirective(element);
|
|
88
|
-
|
|
89
|
-
element.querySelectorAll("*").forEach((el) => {
|
|
90
|
-
this.applyShowDirective(el);
|
|
91
|
-
this.applyIfDirective(el);
|
|
92
|
-
this.applyForDirective(el);
|
|
93
|
-
this.applyModelDirective(el);
|
|
94
|
-
this.applyAttrDirective(el);
|
|
95
|
-
this.applyClassDirective(el);
|
|
96
|
-
this.applyStyleDirective(el);
|
|
97
|
-
this.applyBindDirective(el);
|
|
98
|
-
this.applyRefDirective(el);
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
applyShowDirective(el) {
|
|
103
|
-
if (!(el instanceof HTMLElement)) return;
|
|
104
|
-
const showExpression = el.getAttribute("$show");
|
|
105
|
-
if (!showExpression) return;
|
|
106
|
-
|
|
107
|
-
this.effect(() => {
|
|
108
|
-
const shouldShow = this.evaluateExpression(showExpression);
|
|
109
|
-
el.style.display = shouldShow ? "" : "none";
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
applyIfDirective(el) {
|
|
114
|
-
if (!(el instanceof HTMLElement)) return;
|
|
115
|
-
const key = el.getAttribute("$if");
|
|
116
|
-
if (!key) return;
|
|
117
|
-
|
|
118
|
-
const parent = el.parentNode;
|
|
119
|
-
const comment = document.createComment("$if placeholder");
|
|
120
|
-
parent?.insertBefore(comment, el);
|
|
121
|
-
|
|
122
|
-
let elseElement = el.nextElementSibling;
|
|
123
|
-
while (elseElement && !elseElement.hasAttribute("$else")) {
|
|
124
|
-
elseElement = elseElement.nextElementSibling;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (elseElement) {
|
|
128
|
-
parent?.removeChild(elseElement);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
this.effect(() => {
|
|
132
|
-
if (this.evaluateExpression(key)) {
|
|
133
|
-
el.style.display = "";
|
|
134
|
-
if (el.parentNode !== parent) {
|
|
135
|
-
parent?.insertBefore(el, comment.nextSibling);
|
|
136
|
-
}
|
|
137
|
-
if (elseElement) {
|
|
138
|
-
elseElement.style.display = "none";
|
|
139
|
-
if (elseElement.parentNode === parent) {
|
|
140
|
-
parent?.removeChild(elseElement);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
} else {
|
|
144
|
-
el.style.display = "none";
|
|
145
|
-
if (el.parentNode === parent) {
|
|
146
|
-
parent?.removeChild(el);
|
|
147
|
-
}
|
|
148
|
-
if (elseElement) {
|
|
149
|
-
elseElement.style.display = "";
|
|
150
|
-
if (elseElement.parentNode !== parent) {
|
|
151
|
-
parent?.insertBefore(elseElement, comment.nextSibling);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
applyForDirective(el) {
|
|
159
|
-
if (!(el instanceof HTMLElement)) return;
|
|
160
|
-
const expression = el.getAttribute("$for");
|
|
161
|
-
if (!expression) return;
|
|
162
|
-
|
|
163
|
-
const [item, arr] = expression.split(" in ");
|
|
164
|
-
const parent = el.parentNode;
|
|
165
|
-
const comment = document.createComment("$for placeholder");
|
|
166
|
-
parent?.insertBefore(comment, el);
|
|
167
|
-
el.remove();
|
|
168
|
-
|
|
169
|
-
this.effect(() => {
|
|
170
|
-
const items = this.evaluateExpression(arr);
|
|
171
|
-
const existingElements = new Set();
|
|
172
|
-
let currentElement = comment.nextSibling;
|
|
173
|
-
while (currentElement && currentElement.nodeType === Node.ELEMENT_NODE) {
|
|
174
|
-
existingElements.add(currentElement);
|
|
175
|
-
currentElement = currentElement.nextSibling;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
items.forEach((value, index) => {
|
|
179
|
-
let element = Array.from(existingElements).find(
|
|
180
|
-
(el) => el.getAttribute("key") === String(index)
|
|
181
|
-
);
|
|
182
|
-
if (!element) {
|
|
183
|
-
element = el.cloneNode(true);
|
|
184
|
-
element.setAttribute("key", String(index));
|
|
185
|
-
parent?.insertBefore(element, comment.nextSibling);
|
|
186
|
-
} else {
|
|
187
|
-
existingElements.delete(element);
|
|
188
|
-
}
|
|
189
|
-
this.interpolateElement(element, { [item]: value, index });
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
existingElements.forEach((el) => el.remove());
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
applyModelDirective(el) {
|
|
197
|
-
if (!(el instanceof HTMLInputElement)) return;
|
|
198
|
-
const key = el.getAttribute("$model");
|
|
199
|
-
if (!key) return;
|
|
200
|
-
|
|
201
|
-
el.addEventListener("input", (e) => {
|
|
202
|
-
this.setExpressionValue(key, e.target.value);
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
this.effect(() => {
|
|
206
|
-
el.value = this.evaluateExpression(key);
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
applyAttrDirective(el) {
|
|
211
|
-
if (!(el instanceof HTMLElement)) return;
|
|
212
|
-
const bindings = el.getAttribute("$attr")?.split(",");
|
|
213
|
-
if (!bindings) return;
|
|
214
|
-
|
|
215
|
-
bindings.forEach((binding) => {
|
|
216
|
-
const [attr, expression] = binding.split(":");
|
|
217
|
-
this.effect(() => {
|
|
218
|
-
el.setAttribute(attr, this.evaluateExpression(expression));
|
|
219
|
-
});
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
applyClassDirective(el) {
|
|
224
|
-
if (!(el instanceof HTMLElement)) return;
|
|
225
|
-
const classBinding = el.getAttribute("$class");
|
|
226
|
-
if (!classBinding) return;
|
|
227
|
-
|
|
228
|
-
this.effect(() => {
|
|
229
|
-
const classObj = this.evaluateExpression(classBinding);
|
|
230
|
-
if (typeof classObj === "object" && classObj !== null) {
|
|
231
|
-
Object.entries(classObj).forEach(([className, condition]) => {
|
|
232
|
-
if (condition) {
|
|
233
|
-
el.classList.add(className);
|
|
234
|
-
} else {
|
|
235
|
-
el.classList.remove(className);
|
|
236
|
-
}
|
|
237
|
-
});
|
|
238
|
-
} else if (typeof classObj === "string") {
|
|
239
|
-
el.className = classObj;
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
applyStyleDirective(el) {
|
|
245
|
-
if (!(el instanceof HTMLElement)) return;
|
|
246
|
-
const styleBinding = el.getAttribute("$style");
|
|
247
|
-
if (!styleBinding) return;
|
|
248
|
-
|
|
249
|
-
this.effect(() => {
|
|
250
|
-
const styleObj = this.evaluateExpression(styleBinding);
|
|
251
|
-
if (typeof styleObj === "object" && styleObj !== null) {
|
|
252
|
-
Object.keys(styleObj).forEach((prop) => {
|
|
253
|
-
el.style[prop] = styleObj[prop];
|
|
254
|
-
});
|
|
255
|
-
} else if (typeof styleObj === "string") {
|
|
256
|
-
el.setAttribute("style", styleObj);
|
|
257
|
-
}
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
applyBindDirective(el) {
|
|
262
|
-
if (!(el instanceof HTMLElement)) return;
|
|
263
|
-
const bindExpression = el.getAttribute("$bind");
|
|
264
|
-
if (!bindExpression) return;
|
|
265
|
-
|
|
266
|
-
this.effect(() => {
|
|
267
|
-
const value = this.evaluateExpression(bindExpression);
|
|
268
|
-
this.setElementValue(el, value);
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
el.addEventListener("input", (event) => {
|
|
272
|
-
const value = this.getElementValue(event.target);
|
|
273
|
-
this.setExpressionValue(bindExpression, value);
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
if (el.type === "checkbox" || el.type === "radio") {
|
|
277
|
-
el.addEventListener("change", (event) => {
|
|
278
|
-
const value = this.getElementValue(event.target);
|
|
279
|
-
this.setExpressionValue(bindExpression, value);
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
applyRefDirective(el) {
|
|
285
|
-
if (!(el instanceof HTMLElement)) return;
|
|
286
|
-
const key = el.getAttribute("$ref");
|
|
287
|
-
if (key) {
|
|
288
|
-
this.registerRef(key, el);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
setElementValue(el, value) {
|
|
293
|
-
if (el instanceof HTMLInputElement) {
|
|
294
|
-
if (el.type === "checkbox") {
|
|
295
|
-
el.checked = !!value;
|
|
296
|
-
} else if (el.type === "radio") {
|
|
297
|
-
el.checked = el.value === value;
|
|
298
|
-
} else {
|
|
299
|
-
el.value = value;
|
|
300
|
-
}
|
|
301
|
-
} else if (
|
|
302
|
-
el instanceof HTMLTextAreaElement ||
|
|
303
|
-
el instanceof HTMLSelectElement
|
|
304
|
-
) {
|
|
305
|
-
el.value = value;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
getElementValue(el) {
|
|
310
|
-
if (el instanceof HTMLInputElement) {
|
|
311
|
-
if (el.type === "checkbox") {
|
|
312
|
-
return el.checked;
|
|
313
|
-
} else if (el.type === "radio") {
|
|
314
|
-
return el.checked ? el.value : null;
|
|
315
|
-
} else {
|
|
316
|
-
return el.value;
|
|
317
|
-
}
|
|
318
|
-
} else if (
|
|
319
|
-
el instanceof HTMLTextAreaElement ||
|
|
320
|
-
el instanceof HTMLSelectElement
|
|
321
|
-
) {
|
|
322
|
-
return el.value;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
useEffect(callback) {
|
|
327
|
-
this.effects.push(callback);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
runEffects() {
|
|
331
|
-
this.effects.forEach((effect) => {
|
|
332
|
-
const cleanup = effect();
|
|
333
|
-
if (typeof cleanup === "function") {
|
|
334
|
-
this.cleanupEffects.push(cleanup);
|
|
335
|
-
}
|
|
336
|
-
});
|
|
337
|
-
this.effects = [];
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
cleanup() {
|
|
341
|
-
this.cleanupEffects.forEach((cleanup) => cleanup());
|
|
342
|
-
this.cleanupEffects = [];
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
getRef(key) {
|
|
346
|
-
if (this.refs[key] !== undefined) {
|
|
347
|
-
return this.refs[key];
|
|
348
|
-
} else {
|
|
349
|
-
console.warn(`Ref '${key}' not found.`);
|
|
350
|
-
return null;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
registerRef(key, ref) {
|
|
355
|
-
this.refs[key] = ref;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
defineReactive(obj, key, val) {
|
|
359
|
-
this.listeners[key] = [];
|
|
360
|
-
Object.defineProperty(obj, key, {
|
|
361
|
-
get: () => {
|
|
362
|
-
this.track(key);
|
|
363
|
-
return val;
|
|
364
|
-
},
|
|
365
|
-
set: (newVal) => {
|
|
366
|
-
if (val !== newVal) {
|
|
367
|
-
val = newVal;
|
|
368
|
-
this.notify(key);
|
|
369
|
-
}
|
|
370
|
-
},
|
|
371
|
-
});
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
watch(key, listener) {
|
|
375
|
-
if (!this.listeners[key]) {
|
|
376
|
-
this.listeners[key] = [];
|
|
377
|
-
}
|
|
378
|
-
this.listeners[key].push(listener);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
track(key) {
|
|
382
|
-
if (olova.activeEffect) {
|
|
383
|
-
if (!this.dependencies.has(key)) {
|
|
384
|
-
this.dependencies.set(key, new Set());
|
|
385
|
-
}
|
|
386
|
-
this.dependencies.get(key).add(olova.activeEffect);
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
notify(key) {
|
|
391
|
-
if (this.dependencies.has(key)) {
|
|
392
|
-
this.dependencies.get(key).forEach((effect) => effect());
|
|
393
|
-
}
|
|
394
|
-
if (this.listeners[key]) {
|
|
395
|
-
this.listeners[key].forEach((listener) => listener());
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
effect(fn) {
|
|
400
|
-
olova.activeEffect = fn;
|
|
401
|
-
fn();
|
|
402
|
-
olova.activeEffect = null;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
makeReactive(obj) {
|
|
406
|
-
for (const key in obj) {
|
|
407
|
-
if (obj.hasOwnProperty(key)) {
|
|
408
|
-
this.defineReactive(obj, key, obj[key]);
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
initReactiveSystem() {
|
|
414
|
-
this.makeReactive(window.useSignal);
|
|
415
|
-
this.initDirectives();
|
|
416
|
-
this.initEvents();
|
|
417
|
-
this.initDataBinding();
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
initDirectives() {
|
|
421
|
-
this.initIfDirective();
|
|
422
|
-
this.initRefDirective();
|
|
423
|
-
this.initShowDirective();
|
|
424
|
-
this.initForDirective();
|
|
425
|
-
this.initModelDirective();
|
|
426
|
-
this.initAttrDirective();
|
|
427
|
-
this.initClassDirective();
|
|
428
|
-
this.initStyleDirective();
|
|
429
|
-
this.initBindDirective();
|
|
430
|
-
this.initHtmlDirective();
|
|
431
|
-
Object.keys(this.plugins).forEach((pluginName) => {
|
|
432
|
-
document.querySelectorAll(`[\\$${pluginName}]`).forEach((el) => {
|
|
433
|
-
const value = el.getAttribute(`$${pluginName}`);
|
|
434
|
-
this.effect(() => {
|
|
435
|
-
const result = this.evaluateExpression(value);
|
|
436
|
-
this.plugins[pluginName](el, result, this);
|
|
437
|
-
});
|
|
438
|
-
});
|
|
439
|
-
});
|
|
440
|
-
}
|
|
441
|
-
initHtmlDirective() {
|
|
442
|
-
document.querySelectorAll("[\\$html]").forEach((el) => {
|
|
443
|
-
if (!(el instanceof HTMLElement)) return;
|
|
444
|
-
const htmlExpression = el.getAttribute("$html");
|
|
445
|
-
if (!htmlExpression) return;
|
|
446
|
-
|
|
447
|
-
this.effect(() => {
|
|
448
|
-
const htmlContent = this.evaluateExpression(htmlExpression);
|
|
449
|
-
el.innerHTML = htmlContent;
|
|
450
|
-
el.removeAttribute("$html");
|
|
451
|
-
});
|
|
452
|
-
});
|
|
453
|
-
}
|
|
454
|
-
initClassDirective() {
|
|
455
|
-
document.querySelectorAll("[\\$class]").forEach((el) => {
|
|
456
|
-
if (!(el instanceof HTMLElement)) return;
|
|
457
|
-
const classBinding = el.getAttribute("$class");
|
|
458
|
-
if (!classBinding) return;
|
|
459
|
-
|
|
460
|
-
this.effect(() => {
|
|
461
|
-
const classObj = this.evaluateExpression(classBinding);
|
|
462
|
-
if (typeof classObj === "object" && classObj !== null) {
|
|
463
|
-
Object.entries(classObj).forEach(([className, condition]) => {
|
|
464
|
-
if (condition) {
|
|
465
|
-
el.classList.add(className);
|
|
466
|
-
} else {
|
|
467
|
-
el.classList.remove(className);
|
|
468
|
-
}
|
|
469
|
-
});
|
|
470
|
-
} else if (typeof classObj === "string") {
|
|
471
|
-
el.className = classObj;
|
|
472
|
-
}
|
|
473
|
-
});
|
|
474
|
-
});
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
initShowDirective() {
|
|
478
|
-
document.querySelectorAll("[\\$show]").forEach((el) => {
|
|
479
|
-
if (!(el instanceof HTMLElement)) return;
|
|
480
|
-
const showExpression = el.getAttribute("$show");
|
|
481
|
-
if (!showExpression) return;
|
|
482
|
-
|
|
483
|
-
this.effect(() => {
|
|
484
|
-
const shouldShow = this.evaluateExpression(showExpression);
|
|
485
|
-
el.style.display = shouldShow ? "" : "none";
|
|
486
|
-
});
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
|
-
initBindDirective() {
|
|
490
|
-
document.querySelectorAll("[\\$bind]").forEach((el) => {
|
|
491
|
-
if (!(el instanceof HTMLElement)) return;
|
|
492
|
-
const bindExpression = el.getAttribute("$bind");
|
|
493
|
-
if (!bindExpression) return;
|
|
494
|
-
|
|
495
|
-
this.effect(() => {
|
|
496
|
-
const value = this.evaluateExpression(bindExpression);
|
|
497
|
-
this.setElementValue(el, value);
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
el.addEventListener("input", (event) => {
|
|
501
|
-
const value = this.getElementValue(event.target);
|
|
502
|
-
this.setExpressionValue(bindExpression, value);
|
|
503
|
-
});
|
|
504
|
-
|
|
505
|
-
if (el.type === "checkbox" || el.type === "radio") {
|
|
506
|
-
el.addEventListener("change", (event) => {
|
|
507
|
-
const value = this.getElementValue(event.target);
|
|
508
|
-
this.setExpressionValue(bindExpression, value);
|
|
509
|
-
});
|
|
510
|
-
}
|
|
511
|
-
});
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
setElementValue(el, value) {
|
|
515
|
-
if (el instanceof HTMLInputElement) {
|
|
516
|
-
if (el.type === "checkbox") {
|
|
517
|
-
el.checked = !!value;
|
|
518
|
-
} else if (el.type === "radio") {
|
|
519
|
-
el.checked = el.value === value;
|
|
520
|
-
} else {
|
|
521
|
-
el.value = value;
|
|
522
|
-
}
|
|
523
|
-
} else if (
|
|
524
|
-
el instanceof HTMLTextAreaElement ||
|
|
525
|
-
el instanceof HTMLSelectElement
|
|
526
|
-
) {
|
|
527
|
-
el.value = value;
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
getElementValue(el) {
|
|
532
|
-
if (el instanceof HTMLInputElement) {
|
|
533
|
-
if (el.type === "checkbox") {
|
|
534
|
-
return el.checked;
|
|
535
|
-
} else if (el.type === "radio") {
|
|
536
|
-
return el.checked ? el.value : null;
|
|
537
|
-
} else {
|
|
538
|
-
return el.value;
|
|
539
|
-
}
|
|
540
|
-
} else if (
|
|
541
|
-
el instanceof HTMLTextAreaElement ||
|
|
542
|
-
el instanceof HTMLSelectElement
|
|
543
|
-
) {
|
|
544
|
-
return el.value;
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
initStyleDirective() {
|
|
548
|
-
document.querySelectorAll("[\\$style]").forEach((el) => {
|
|
549
|
-
if (!(el instanceof HTMLElement)) return;
|
|
550
|
-
const styleBinding = el.getAttribute("$style");
|
|
551
|
-
if (!styleBinding) return;
|
|
552
|
-
|
|
553
|
-
this.effect(() => {
|
|
554
|
-
const styleObj = this.evaluateExpression(styleBinding);
|
|
555
|
-
if (typeof styleObj === "object" && styleObj !== null) {
|
|
556
|
-
Object.keys(styleObj).forEach((prop) => {
|
|
557
|
-
el.style[prop] = styleObj[prop];
|
|
558
|
-
});
|
|
559
|
-
} else if (typeof styleObj === "string") {
|
|
560
|
-
el.setAttribute("style", styleObj);
|
|
561
|
-
}
|
|
562
|
-
});
|
|
563
|
-
});
|
|
564
|
-
}
|
|
565
|
-
initIfDirective() {
|
|
566
|
-
document.querySelectorAll("[\\$if]").forEach((el) => {
|
|
567
|
-
if (!(el instanceof HTMLElement)) return;
|
|
568
|
-
const key = el.getAttribute("$if");
|
|
569
|
-
if (!key) return;
|
|
570
|
-
const parent = el.parentNode;
|
|
571
|
-
const comment = document.createComment("$if placeholder");
|
|
572
|
-
parent?.insertBefore(comment, el);
|
|
573
|
-
|
|
574
|
-
let elseElement = el.nextElementSibling;
|
|
575
|
-
while (elseElement && !elseElement.hasAttribute("$else")) {
|
|
576
|
-
elseElement = elseElement.nextElementSibling;
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
if (elseElement) {
|
|
580
|
-
parent?.removeChild(elseElement);
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
this.effect(() => {
|
|
584
|
-
if (this.evaluateExpression(key)) {
|
|
585
|
-
el.style.display = "";
|
|
586
|
-
if (el.parentNode !== parent) {
|
|
587
|
-
parent?.insertBefore(el, comment.nextSibling);
|
|
588
|
-
}
|
|
589
|
-
if (elseElement) {
|
|
590
|
-
elseElement.style.display = "none";
|
|
591
|
-
if (elseElement.parentNode === parent) {
|
|
592
|
-
parent?.removeChild(elseElement);
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
} else {
|
|
596
|
-
el.style.display = "none";
|
|
597
|
-
if (el.parentNode === parent) {
|
|
598
|
-
parent?.removeChild(el);
|
|
599
|
-
}
|
|
600
|
-
if (elseElement) {
|
|
601
|
-
elseElement.style.display = "";
|
|
602
|
-
if (elseElement.parentNode !== parent) {
|
|
603
|
-
parent?.insertBefore(elseElement, comment.nextSibling);
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
});
|
|
608
|
-
});
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
initRefDirective() {
|
|
612
|
-
document.querySelectorAll("[\\$ref]").forEach((el) => {
|
|
613
|
-
if (!(el instanceof HTMLElement)) return;
|
|
614
|
-
const key = el.getAttribute("$ref");
|
|
615
|
-
if (key) {
|
|
616
|
-
this.registerRef(key, el);
|
|
617
|
-
}
|
|
618
|
-
el.removeAttribute("$ref");
|
|
619
|
-
});
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
initForDirective() {
|
|
623
|
-
document.querySelectorAll("[\\$for]").forEach((el) => {
|
|
624
|
-
if (!(el instanceof HTMLElement)) return;
|
|
625
|
-
const expression = el.getAttribute("$for");
|
|
626
|
-
if (!expression) return;
|
|
627
|
-
const [item, arr] = expression.split(" in ");
|
|
628
|
-
const parent = el.parentNode;
|
|
629
|
-
const comment = document.createComment("$for placeholder");
|
|
630
|
-
parent?.insertBefore(comment, el);
|
|
631
|
-
|
|
632
|
-
// Remove the $for attribute
|
|
633
|
-
el.removeAttribute("$for");
|
|
634
|
-
|
|
635
|
-
const template = el.cloneNode(true);
|
|
636
|
-
el.remove();
|
|
637
|
-
|
|
638
|
-
this.effect(() => {
|
|
639
|
-
const items = this.evaluateExpression(arr);
|
|
640
|
-
const existingElements = new Set();
|
|
641
|
-
let currentElement = comment.nextSibling;
|
|
642
|
-
while (
|
|
643
|
-
currentElement &&
|
|
644
|
-
currentElement.nodeType === Node.ELEMENT_NODE
|
|
645
|
-
) {
|
|
646
|
-
existingElements.add(currentElement);
|
|
647
|
-
currentElement = currentElement.nextSibling;
|
|
648
|
-
}
|
|
649
|
-
items.forEach((value, index) => {
|
|
650
|
-
let element = Array.from(existingElements).find(
|
|
651
|
-
(el) => el.getAttribute("key") === String(index)
|
|
652
|
-
);
|
|
653
|
-
if (!element) {
|
|
654
|
-
element = template.cloneNode(true);
|
|
655
|
-
element.setAttribute("key", String(index));
|
|
656
|
-
parent?.insertBefore(element, comment.nextSibling);
|
|
657
|
-
} else {
|
|
658
|
-
existingElements.delete(element);
|
|
659
|
-
}
|
|
660
|
-
this.interpolateElement(element, { [item]: value, index });
|
|
661
|
-
});
|
|
662
|
-
existingElements.forEach((el) => el.remove());
|
|
663
|
-
});
|
|
664
|
-
});
|
|
665
|
-
}
|
|
666
|
-
initModelDirective() {
|
|
667
|
-
document.querySelectorAll("[\\$model]").forEach((el) => {
|
|
668
|
-
if (!(el instanceof HTMLInputElement)) return;
|
|
669
|
-
const key = el.getAttribute("$model");
|
|
670
|
-
if (!key) return;
|
|
671
|
-
el.addEventListener("input", (e) => {
|
|
672
|
-
this.setExpressionValue(key, e.target.value);
|
|
673
|
-
});
|
|
674
|
-
this.effect(() => {
|
|
675
|
-
el.value = this.evaluateExpression(key);
|
|
676
|
-
});
|
|
677
|
-
});
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
initAttrDirective() {
|
|
681
|
-
document.querySelectorAll("[\\$attr]").forEach((el) => {
|
|
682
|
-
if (!(el instanceof HTMLElement)) return;
|
|
683
|
-
const bindings = el.getAttribute("$attr")?.split(",");
|
|
684
|
-
if (!bindings) return;
|
|
685
|
-
bindings.forEach((binding) => {
|
|
686
|
-
const [attr, expression] = binding.split(":");
|
|
687
|
-
this.effect(() => {
|
|
688
|
-
el.setAttribute(attr, this.evaluateExpression(expression));
|
|
689
|
-
});
|
|
690
|
-
});
|
|
691
|
-
});
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
initEvents() {
|
|
695
|
-
const eventTypes = [
|
|
696
|
-
"click",
|
|
697
|
-
"input",
|
|
698
|
-
"change",
|
|
699
|
-
"mouseover",
|
|
700
|
-
"mousemove",
|
|
701
|
-
"mouseout",
|
|
702
|
-
"keydown",
|
|
703
|
-
"keyup",
|
|
704
|
-
"mousedown",
|
|
705
|
-
"mouseup",
|
|
706
|
-
"dblclick",
|
|
707
|
-
"focus",
|
|
708
|
-
"blur",
|
|
709
|
-
"contextmenu",
|
|
710
|
-
"drag",
|
|
711
|
-
"drop",
|
|
712
|
-
"scroll",
|
|
713
|
-
"resize",
|
|
714
|
-
"touchstart",
|
|
715
|
-
"touchmove",
|
|
716
|
-
"touchend",
|
|
717
|
-
"paste",
|
|
718
|
-
"copy",
|
|
719
|
-
"cut",
|
|
720
|
-
"error",
|
|
721
|
-
"load",
|
|
722
|
-
"submit",
|
|
723
|
-
"animationstart",
|
|
724
|
-
"animationend",
|
|
725
|
-
"animationiteration",
|
|
726
|
-
"transitionend",
|
|
727
|
-
"hashchange",
|
|
728
|
-
"beforeunload",
|
|
729
|
-
"fullscreenchange",
|
|
730
|
-
"message",
|
|
731
|
-
"canplay",
|
|
732
|
-
"canplaythrough",
|
|
733
|
-
"durationchange",
|
|
734
|
-
"emptied",
|
|
735
|
-
"ended",
|
|
736
|
-
"invalid",
|
|
737
|
-
"progress",
|
|
738
|
-
"ratechange",
|
|
739
|
-
"waiting",
|
|
740
|
-
"volumechange",
|
|
741
|
-
"wheel",
|
|
742
|
-
"focusin",
|
|
743
|
-
"focusout",
|
|
744
|
-
"pointerenter",
|
|
745
|
-
"pointerleave",
|
|
746
|
-
"touchcancel",
|
|
747
|
-
];
|
|
748
|
-
|
|
749
|
-
eventTypes.forEach((eventType) => {
|
|
750
|
-
document.querySelectorAll(`[\\@${eventType}]`).forEach((el) => {
|
|
751
|
-
if (!(el instanceof HTMLElement)) return;
|
|
752
|
-
|
|
753
|
-
const handlerExpression = el.getAttribute(`@${eventType}`);
|
|
754
|
-
if (handlerExpression) {
|
|
755
|
-
el.addEventListener(eventType, (event) => {
|
|
756
|
-
try {
|
|
757
|
-
let cleanedExpression = handlerExpression.trim();
|
|
758
|
-
|
|
759
|
-
// If the expression is a function reference, invoke it
|
|
760
|
-
if (
|
|
761
|
-
cleanedExpression in window.useSignal &&
|
|
762
|
-
typeof window.useSignal[cleanedExpression] === "function"
|
|
763
|
-
) {
|
|
764
|
-
window.useSignal[cleanedExpression](event);
|
|
765
|
-
} else {
|
|
766
|
-
// If it's not a direct function reference, treat it as inline JS
|
|
767
|
-
const func = new Function(
|
|
768
|
-
"event, $",
|
|
769
|
-
`with($) { ${cleanedExpression} }`
|
|
770
|
-
);
|
|
771
|
-
func(event, window.useSignal);
|
|
772
|
-
}
|
|
773
|
-
} catch (error) {
|
|
774
|
-
console.error(
|
|
775
|
-
`Error executing handler '${handlerExpression}' for event '${eventType}':`,
|
|
776
|
-
error
|
|
777
|
-
);
|
|
778
|
-
}
|
|
779
|
-
});
|
|
780
|
-
}
|
|
781
|
-
});
|
|
782
|
-
});
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
initDataBinding() {
|
|
786
|
-
this.compileTextNodes(document.body);
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
compileTextNodes(el) {
|
|
790
|
-
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
|
|
791
|
-
let node;
|
|
792
|
-
const nodesToReplace = [];
|
|
793
|
-
|
|
794
|
-
while ((node = walker.nextNode())) {
|
|
795
|
-
if (node.textContent.includes("{") && node.textContent.includes("}")) {
|
|
796
|
-
nodesToReplace.push(node);
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
nodesToReplace.forEach((node) => {
|
|
801
|
-
const parts = node.textContent.split(/(\{.*?\})/);
|
|
802
|
-
const fragment = document.createDocumentFragment();
|
|
803
|
-
|
|
804
|
-
parts.forEach((part) => {
|
|
805
|
-
if (part.startsWith("{") && part.endsWith("}")) {
|
|
806
|
-
const textNode = document.createTextNode("");
|
|
807
|
-
const expression = part.slice(2, -2).trim();
|
|
808
|
-
this.effect(() => {
|
|
809
|
-
textNode.textContent = this.evaluateExpression(expression);
|
|
810
|
-
});
|
|
811
|
-
fragment.appendChild(textNode);
|
|
812
|
-
} else {
|
|
813
|
-
fragment.appendChild(document.createTextNode(part));
|
|
814
|
-
}
|
|
815
|
-
});
|
|
816
|
-
|
|
817
|
-
node.parentNode.replaceChild(fragment, node);
|
|
818
|
-
});
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
interpolateTextNodes(el, context) {
|
|
822
|
-
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
|
|
823
|
-
let node;
|
|
824
|
-
const nodesToReplace = [];
|
|
825
|
-
|
|
826
|
-
while ((node = walker.nextNode())) {
|
|
827
|
-
if (node.textContent.includes("{") && node.textContent.includes("}")) {
|
|
828
|
-
nodesToReplace.push(node);
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
nodesToReplace.forEach((node) => {
|
|
833
|
-
const parts = node.textContent.split(/(\{.*?\})/);
|
|
834
|
-
const fragment = document.createDocumentFragment();
|
|
835
|
-
|
|
836
|
-
parts.forEach((part) => {
|
|
837
|
-
if (part.startsWith("{") && part.endsWith("}")) {
|
|
838
|
-
const textNode = document.createTextNode("");
|
|
839
|
-
const expression = part.slice(2, -2).trim();
|
|
840
|
-
this.effect(() => {
|
|
841
|
-
textNode.textContent = this.evaluateExpression(expression, context);
|
|
842
|
-
});
|
|
843
|
-
fragment.appendChild(textNode);
|
|
844
|
-
} else {
|
|
845
|
-
fragment.appendChild(document.createTextNode(part));
|
|
846
|
-
}
|
|
847
|
-
});
|
|
848
|
-
|
|
849
|
-
node.parentNode.replaceChild(fragment, node);
|
|
850
|
-
});
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
evaluateExpression(expression, context = {}) {
|
|
854
|
-
try {
|
|
855
|
-
const func = new Function(
|
|
856
|
-
"useSignal",
|
|
857
|
-
"with(useSignal) { return " + expression + " }"
|
|
858
|
-
);
|
|
859
|
-
return func({ ...window.useSignal, ...context });
|
|
860
|
-
} catch (error) {
|
|
861
|
-
console.error(`Error evaluating expression: ${expression}`, error);
|
|
862
|
-
return "";
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
setExpressionValue(expression, value) {
|
|
867
|
-
try {
|
|
868
|
-
const func = new Function(
|
|
869
|
-
"useSignal",
|
|
870
|
-
"value",
|
|
871
|
-
`with(useSignal) { ${expression} = value }`
|
|
872
|
-
);
|
|
873
|
-
func(window.useSignal, value);
|
|
874
|
-
} catch (error) {
|
|
875
|
-
console.error(`Error setting value for expression: ${expression}`, error);
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
|
|
879
|
-
interpolateElement(el, context) {
|
|
880
|
-
this.interpolateAttributes(el, context);
|
|
881
|
-
this.interpolateTextNodes(el, context);
|
|
882
|
-
Array.from(el.children).forEach((child) =>
|
|
883
|
-
this.interpolateElement(child, context)
|
|
884
|
-
);
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
interpolateAttributes(el, context) {
|
|
888
|
-
Array.from(el.attributes).forEach((attr) => {
|
|
889
|
-
if (attr.value.includes("{") && attr.value.includes("}")) {
|
|
890
|
-
this.effect(() => {
|
|
891
|
-
attr.value = this.interpolate(attr.value, context);
|
|
892
|
-
});
|
|
893
|
-
}
|
|
894
|
-
});
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
interpolateTextNodes(el, context) {
|
|
898
|
-
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
|
|
899
|
-
let node;
|
|
900
|
-
const nodesToReplace = [];
|
|
901
|
-
|
|
902
|
-
while ((node = walker.nextNode())) {
|
|
903
|
-
if (node.textContent.includes("{") && node.textContent.includes("}")) {
|
|
904
|
-
nodesToReplace.push(node);
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
nodesToReplace.forEach((node) => {
|
|
909
|
-
const fragment = document.createDocumentFragment();
|
|
910
|
-
const parts = node.textContent.split(/(\{.*?\})/);
|
|
911
|
-
|
|
912
|
-
parts.forEach((part) => {
|
|
913
|
-
if (part.startsWith("{") && part.endsWith("}")) {
|
|
914
|
-
const span = document.createElement("span");
|
|
915
|
-
const expression = part.slice(2, -2).trim();
|
|
916
|
-
this.effect(() => {
|
|
917
|
-
span.textContent = this.evaluateExpression(expression, context);
|
|
918
|
-
});
|
|
919
|
-
fragment.appendChild(span);
|
|
920
|
-
} else {
|
|
921
|
-
fragment.appendChild(document.createTextNode(part));
|
|
922
|
-
}
|
|
923
|
-
});
|
|
924
|
-
|
|
925
|
-
node.parentNode.replaceChild(fragment, node);
|
|
926
|
-
});
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
interpolate(template, context) {
|
|
930
|
-
return template.replace(/\{\{(.*?)\}\}/g, (match, expression) => {
|
|
931
|
-
return this.evaluateExpression(expression, context);
|
|
932
|
-
});
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
static init() {
|
|
936
|
-
const deshi = new olova();
|
|
937
|
-
window.$refs = deshi.$refs;
|
|
938
|
-
window.$ = (selector) => deshi.$(selector);
|
|
939
|
-
// Create the useSignal function
|
|
940
|
-
const useSignalFunction = (obj = {}) => {
|
|
941
|
-
Object.assign(window.useSignal, obj);
|
|
942
|
-
};
|
|
943
|
-
// Create the useSignal object with the function
|
|
944
|
-
window.useSignal = new Proxy(useSignalFunction, {
|
|
945
|
-
get(target, key) {
|
|
946
|
-
if (key === "call" || key === "apply") {
|
|
947
|
-
return Reflect.get(target, key);
|
|
948
|
-
}
|
|
949
|
-
deshi.track(key);
|
|
950
|
-
return Reflect.get(target, key);
|
|
951
|
-
},
|
|
952
|
-
set(target, key, value) {
|
|
953
|
-
if (Reflect.get(target, key) !== value) {
|
|
954
|
-
Reflect.set(target, key, value);
|
|
955
|
-
deshi.notify(key);
|
|
956
|
-
deshi.runEffects();
|
|
957
|
-
}
|
|
958
|
-
return true;
|
|
959
|
-
},
|
|
960
|
-
});
|
|
961
|
-
|
|
962
|
-
document.addEventListener("DOMContentLoaded", () => {
|
|
963
|
-
deshi.renderTemplate();
|
|
964
|
-
});
|
|
965
|
-
|
|
966
|
-
window.addEventListener("beforeunload", () => {
|
|
967
|
-
deshi.cleanup();
|
|
968
|
-
});
|
|
969
|
-
|
|
970
|
-
window.useEffect = (callback) => {
|
|
971
|
-
deshi.useEffect(callback);
|
|
972
|
-
};
|
|
973
|
-
window.component = (name, componentFunction) => {
|
|
974
|
-
deshi.registerComponent(name, componentFunction);
|
|
975
|
-
};
|
|
976
|
-
|
|
977
|
-
window.plugin = (name, handler) => deshi.registerPlugin(name, handler);
|
|
978
|
-
|
|
979
|
-
return deshi;
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
renderTemplate() {
|
|
983
|
-
const root = document.getElementById("root");
|
|
984
|
-
const template = document.querySelector("template");
|
|
985
|
-
if (root && template) {
|
|
986
|
-
let content = template.innerHTML;
|
|
987
|
-
content = content.replace(/<([a-z-]+)><\/\1>/g, "");
|
|
988
|
-
root.innerHTML = content;
|
|
989
|
-
template.remove();
|
|
990
|
-
this.initReactiveSystem();
|
|
991
|
-
this.runEffects();
|
|
992
|
-
} else {
|
|
993
|
-
console.error("Root element or app template not found");
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
olova.activeEffect = null;
|
|
999
|
-
|
|
1000
|
-
export default olova;
|
|
1
|
+
let createApp=({data:e,computed:t,methods:r,watch:o,mounted:n,beforeMount:a,beforeUpdate:l,template:c,plugins:i=[],components:s={}})=>{let u,d={},f={},m={},h={},p={},E=new Map,y=new Map,b=(e,t)=>{y.set(e,t)},g=(e,t)=>{p[e]=t},A=e=>new Proxy(e,{get:(e,t)=>"object"==typeof e[t]&&null!==e[t]?A(e[t]):e[t],set:(e,t,r)=>(e[t]!==r&&(e[t]=r,N(t)),!0)});Error;class $ extends Error{constructor(e){super(e),this.name="StateError"}}let w=(e,t,r=Error)=>function(...o){try{return e.apply(this,o)}catch(e){throw new r(`${t}: ${e.message}`)}};a&&w(a,"Error in beforeMount hook",$).call(M);let v=new Set,T=e=>{d[e]&&(v.add(e),requestAnimationFrame((()=>{v.forEach((e=>{d[e].forEach(w((t=>{t.node?t.node.textContent=t.originalText.replace(/\{(.*?)\}/g,((e,t)=>Function("state",`with(state) { return ${t} }`)(M))):t.element&&t.attrName?(t.element.setAttribute(t.attrName,M[e]),t.element.removeAttribute(`:${t.attrName}`)):t.update&&t.update()}),"Error updating bindings"))})),v.clear()})))},N=e=>{l&&w(l,"Error in beforeUpdate hook").call(M,e),T(e),x(),_(e),m.__updated__&&m.__updated__.forEach((e=>e.callback.call(M)))},x=()=>{Object.keys(f).forEach((e=>delete f[e]))},_=e=>{m[e]&&m[e].forEach((t=>{t.debounce?(clearTimeout(t.timeout),t.timeout=setTimeout((()=>t.callback.call(M,M[e])),t.debounce)):t.throttle?(!t.lastCalled||Date.now()-t.lastCalled>t.throttle)&&(t.callback.call(M,M[e]),t.lastCalled=Date.now()):t.callback.call(M,M[e])}))};o&&Object.keys(o).forEach((e=>{"function"==typeof o[e]?m[e]=[{callback:o[e]}]:"object"==typeof o[e]?m[e]=[{...o[e]}]:m[e]=Array.isArray(o[e])?o[e].map((e=>({callback:e}))):[{callback:o[e]}]}));let M=A({...e,$refs:new Proxy(h,{get:(e,t)=>e[t],set(){throw Error("$refs is read-only")}})}),L={},C={};t&&Object.keys(t).forEach((e=>{let r=t[e];L[e]=[],Object.defineProperty(M,e,{get:()=>"function"==typeof r&&"AsyncFunction"===r.constructor.name?(C[e]||(f[e]=new Proxy(M,{get:(t,r)=>(L[e].includes(r)||L[e].push(r),t[r])}),C[e]=r.call(M).then((t=>(f[e]=t,delete C[e],T(e),t))).catch((t=>{console.error(`Error in async computed property "${e}":`,t)}))),C[e]):(f.hasOwnProperty(e)||(f[e]=new Proxy(M,{get:(t,r)=>(L[e].includes(r)||L[e].push(r),t[r])}),f[e]=r.call(M)),f[e]),enumerable:!0})}));let O=()=>{let e=document.createElement("div");e.innerHTML=c.trim(),u.appendChild(e);let t=e=>{e.nodeType===Node.ELEMENT_NODE&&Array.from((e=(e=>{if(e.nodeType===Node.ELEMENT_NODE){let t=e.tagName.toLowerCase();if(y.has(t)){let r=y.get(t),o=Array.from(e.attributes).reduce(((e,t)=>(e[t.name]=t.value,e)),{}),n=r(o),a=document.createElement("div");a.innerHTML=n;let l=a.firstElementChild;return e.parentNode.replaceChild(l,e),l}}return e})(e)).childNodes).forEach(t)};Array.from(u.childNodes).forEach(t),u.querySelectorAll("*").forEach((e=>{if(e instanceof HTMLElement){(e=>{Array.from(e.attributes).forEach((t=>{let r=t.name.startsWith("$")?t.name.slice(1):null;if(r&&p[r]){let o=t.value;p[r](e,o,M),e.removeAttribute(t.name)}}))})(e),[...e.childNodes].filter((e=>e.nodeType===Node.TEXT_NODE&&/\{.*?\}/.test(e.textContent||""))).forEach((e=>{let t=e.textContent||"",r=t.match(/\{(.*?)\}/g);r&&r.forEach((r=>{let o=r.replace(/\{|\}/g,"").trim();d[o]||(d[o]=[]),d[o].push({node:e,originalText:t})}))})),Array.from(e.attributes).forEach((t=>{if(t.name.startsWith("$")){let r=t.value.trim(),o=t.name.slice(1);d[r]||(d[r]=[]),d[r].push({element:e,attrName:o})}}))}}))};Object.entries(s).forEach((([e,t])=>{b(e,t)}));let S={beforeCreate:[],created:[],beforeMount:[],mounted:[],beforeUpdate:[],updated:[],beforeUnmount:[],unmounted:[]},k=(e,t)=>{S[e]&&S[e].push(t)},j=e=>{S[e]&&S[e].forEach((e=>e.call(M)))};return window.addEventListener("error",(e=>{console.error("Global error:",e)})),{mount:w((function(e){if(!(u=document.querySelector(e)))throw Error(`Element with selector "${e}" not found.`);j("beforeCreate"),j("created"),a&&a.call(M),j("beforeMount"),i.forEach((e=>{"function"==typeof e&&e({createPlugin:g,state:M,bindings:d})})),O(),u.querySelectorAll("*").forEach((e=>{Array.from(e.attributes).forEach((t=>{if(t.name.startsWith("@")){let o=t.name.slice(1),n=t.value.trim();e.addEventListener(o,(e=>{if(r&&r[n])r[n].call(M,e);else try{Function("state","event",`with(state) { ${n} }`).call(M,M,e),N()}catch(e){console.error(`Error executing inline event expression: ${n}`,e)}}))}}))})),u.querySelectorAll("[\\$style]").forEach((e=>{if(!(e instanceof HTMLElement))return;let t=e.getAttribute("$style");t&&((()=>{try{let r=Function("state",`with(state) { return ${t} }`)(M);"object"==typeof r&&null!==r?Object.entries(r).forEach((([t,r])=>{e.style[t]=r})):"string"==typeof r&&e.setAttribute("style",r)}catch(e){console.error("Error applying style directive:",e)}})(),T(t))})),u.querySelectorAll("[\\$if]").forEach((e=>{if(!(e instanceof HTMLElement))return;let t=e.getAttribute("$if");if(!t)return;let r=e.parentNode,o=document.createComment("$if placeholder");r?.insertBefore(o,e);let n=e.nextElementSibling;for(;n&&!n.hasAttribute("$else");)n=n.nextElementSibling;(()=>{try{Function("state",`with(state) { return ${t} }`)(M)?(e.style.display="",e.parentNode!==r&&r?.insertBefore(e,o.nextSibling),n&&(n.style.display="none")):(e.style.display="none",n&&(n.style.display=""))}catch(e){console.error("Error evaluating :if directive:",e)}})(),T(t)})),u.querySelectorAll("[\\$for]").forEach((e=>{if(!(e instanceof HTMLElement))return;let t=e.getAttribute("$for");if(!t)return;let r=t.match(/^\s*(\w+)\s+(?:of|in)\s+(\w+)\s*$/);if(!r)return void console.error("Invalid :for expression:",t);let[,o,n]=r,a=e.parentNode,l=document.createComment("$for placeholder");a?.insertBefore(l,e),e.removeAttribute("$for");let c=e.cloneNode(!0);a?.removeChild(e);let i=()=>{let e=document.createDocumentFragment(),t=M[n];for((Array.isArray(t)&&t.forEach(((t,r)=>{let n=c.cloneNode(!0),a=new Proxy({[o]:t,index:r},{get:(e,t)=>t in e?e[t]:M[t]}),l=e=>{if(e.nodeType===Node.TEXT_NODE){let t=e.textContent;t.includes("{")&&t.includes("}")&&(e.textContent=t.replace(/\{(.*?)\}/g,((e,t)=>Function("state",`with(state) { return ${t} }`)(a))))}else e.nodeType===Node.ELEMENT_NODE&&Array.from(e.childNodes).forEach(l)};l(n),n.querySelectorAll("*").forEach((e=>{Array.from(e.attributes).forEach((t=>{if(t.value.includes("{")&&t.value.includes("}")){let r=t.value.replace(/\{(.*?)\}/g,((e,t)=>Function("state",`with(state) { return ${t} }`)(a)));e.setAttribute(t.name,r)}}))})),e.appendChild(n)})));l.nextSibling;)a?.removeChild(l.nextSibling);a?.insertBefore(e,l.nextSibling)};i(),d[n]||(d[n]=[]),d[n].push({updateFor:i})})),u.querySelectorAll("[\\$ref]").forEach((e=>{if(!(e instanceof HTMLElement))return;let t=e.getAttribute("$ref");t&&(h[t]=e,e.removeAttribute("$ref"))})),u.querySelectorAll("[\\$model]").forEach((e=>{if(!(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement))return;let t=e.getAttribute("$model");t&&(e.value=M[t]||"",e.addEventListener("input",(e=>{M[t]=e.target.value})),d[t]||(d[t]=[]),d[t].push({element:e,updateModel(){e.value=M[t]||""}}),e.removeAttribute("$model"))})),u.querySelectorAll("[\\$class]").forEach((e=>{if(!(e instanceof HTMLElement))return;let t=e.getAttribute("$class");if(!t)return;let r=()=>{try{let r=Function("state",`with(state) { return ${t} }`)(M);"object"==typeof r&&null!==r?Object.entries(r).forEach((([t,r])=>{r?e.classList.add(t):e.classList.remove(t)})):"string"==typeof r&&(e.className=r)}catch(e){console.error("Error applying class directive:",e)}e.removeAttribute("$class")};r(),d[t]||(d[t]=[]),d[t].push({updateClass:r})})),(e=>{Object.keys(L).forEach((t=>{L[t].includes(e)&&(delete f[t],T(t))}))})(),u.querySelectorAll("[\\$show]").forEach((e=>{e instanceof HTMLElement&&(e=>{if(!(e instanceof HTMLElement))return;let t=e.getAttribute("$show");if(!t)return;let r=()=>{try{let r=Function("state",`with(state) { return ${t} }`)(M);e.style.display=r?"":"none"}catch(e){console.error("Error evaluating $show directive:",e)}};r(),d[t]||(d[t]=[]),d[t].push({element:e,update:r})})(e)})),n&&n.call(M),j("mounted"),Object.keys(M).forEach((e=>T(e)))}),"Error mounting application"),onUpdated:e=>{if("function"==typeof e){let t=w(e,"Error in onUpdated callback");m.__updated__||(m.__updated__=[]),m.__updated__.push({callback:t})}},createPlugin:g,emit:(e,t)=>{E.has(e)||E.set(e,[]),E.get(e).forEach((e=>e(t)))},on:(e,t)=>(E.has(e)||E.set(e,[]),E.get(e).push(t),()=>{let r=E.get(e),o=r.indexOf(t);-1!==o&&r.splice(o,1)}),addLifecycleHook:k,applyMixin:e=>{e.data&&Object.assign(M,e.data()),e.methods&&Object.assign(r,e.methods),e.computed&&Object.assign(t,e.computed),e.watch&&Object.keys(e.watch).forEach((t=>{o[t]||(o[t]=[]),o[t].push(e.watch[t])})),e.mounted&&k("mounted",e.mounted)},component:b}};export{createApp};
|
package/package.json
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "olova",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "A lightweight JavaScript framework for building reactive applications.",
|
|
5
|
-
"main": "
|
|
6
|
-
"scripts": {
|
|
7
|
-
"dev": "vite",
|
|
8
|
-
"build": "vite build",
|
|
9
|
-
"preview": "vite preview",
|
|
10
|
-
"test": "jest"
|
|
11
|
-
},
|
|
5
|
+
"main": "olova.js",
|
|
12
6
|
"keywords": [
|
|
13
7
|
"javascript",
|
|
14
8
|
"framework",
|
|
@@ -17,9 +11,5 @@
|
|
|
17
11
|
],
|
|
18
12
|
"author": "Nazmul Hossain",
|
|
19
13
|
"license": "MIT",
|
|
20
|
-
"dependencies": {}
|
|
21
|
-
"devDependencies": {
|
|
22
|
-
"vite": "^4.0.0",
|
|
23
|
-
"jest": "^30.1.0"
|
|
24
|
-
}
|
|
14
|
+
"dependencies": {}
|
|
25
15
|
}
|