lightview 2.2.2 → 2.3.4
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/cDOMIntro.md +279 -0
- package/docs/about.html +15 -12
- package/docs/api/computed.html +1 -1
- package/docs/api/effects.html +1 -1
- package/docs/api/elements.html +56 -25
- package/docs/api/enhance.html +1 -1
- package/docs/api/hypermedia.html +1 -1
- package/docs/api/index.html +1 -1
- package/docs/api/nav.html +28 -3
- package/docs/api/signals.html +1 -1
- package/docs/api/state.html +283 -85
- package/docs/assets/js/examplify.js +2 -1
- package/docs/cdom-nav.html +3 -2
- package/docs/cdom.html +383 -114
- package/jprx/README.md +112 -71
- package/jprx/helpers/state.js +21 -0
- package/jprx/package.json +1 -1
- package/jprx/parser.js +136 -86
- package/jprx/specs/expressions.json +71 -0
- package/jprx/specs/helpers.json +150 -0
- package/lightview-all.js +618 -431
- package/lightview-cdom.js +311 -605
- package/lightview-router.js +6 -0
- package/lightview-x.js +226 -54
- package/lightview.js +351 -42
- package/package.json +2 -1
- package/src/lightview-cdom.js +211 -315
- package/src/lightview-router.js +10 -0
- package/src/lightview-x.js +121 -1
- package/src/lightview.js +88 -16
- package/src/reactivity/signal.js +73 -29
- package/src/reactivity/state.js +84 -21
- package/tests/cdom/fixtures/helpers.cdomc +24 -24
- package/tests/cdom/helpers.test.js +28 -28
- package/tests/cdom/parser.test.js +39 -114
- package/tests/cdom/reactivity.test.js +32 -29
- package/tests/jprx/spec.test.js +99 -0
- package/tests/cdom/loader.test.js +0 -125
package/lightview-all.js
CHANGED
|
@@ -1,29 +1,48 @@
|
|
|
1
1
|
(function() {
|
|
2
2
|
"use strict";
|
|
3
|
+
var _a, _b;
|
|
3
4
|
const _LV = globalThis.__LIGHTVIEW_INTERNALS__ || (globalThis.__LIGHTVIEW_INTERNALS__ = {
|
|
4
5
|
currentEffect: null,
|
|
5
6
|
registry: /* @__PURE__ */ new Map(),
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
// Global name -> Signal/Proxy
|
|
8
|
+
localRegistries: /* @__PURE__ */ new WeakMap(),
|
|
9
|
+
// Object/Element -> Map(name -> Signal/Proxy)
|
|
10
|
+
futureSignals: /* @__PURE__ */ new Map(),
|
|
11
|
+
// name -> Set of (signal) => void
|
|
12
|
+
schemas: /* @__PURE__ */ new Map(),
|
|
13
|
+
// name -> Schema (Draft 7+ or Shorthand)
|
|
14
|
+
parents: /* @__PURE__ */ new WeakMap(),
|
|
15
|
+
// Proxy -> Parent (Proxy/Element)
|
|
16
|
+
helpers: /* @__PURE__ */ new Map(),
|
|
17
|
+
// name -> function (used for transforms and expressions)
|
|
18
|
+
hooks: {
|
|
19
|
+
validate: (value, schema) => true
|
|
20
|
+
// Hook for extensions (like JPRX) to provide full validation
|
|
21
|
+
}
|
|
8
22
|
});
|
|
9
|
-
const
|
|
10
|
-
let
|
|
23
|
+
const lookup$1 = (name, scope) => {
|
|
24
|
+
let current = scope;
|
|
25
|
+
while (current && typeof current === "object") {
|
|
26
|
+
const registry2 = _LV.localRegistries.get(current);
|
|
27
|
+
if (registry2 && registry2.has(name)) return registry2.get(name);
|
|
28
|
+
current = current.parentElement || _LV.parents.get(current);
|
|
29
|
+
}
|
|
30
|
+
return _LV.registry.get(name);
|
|
31
|
+
};
|
|
32
|
+
const signal$1 = (initialValue, optionsOrName) => {
|
|
33
|
+
const name = typeof optionsOrName === "string" ? optionsOrName : optionsOrName == null ? void 0 : optionsOrName.name;
|
|
11
34
|
const storage = optionsOrName == null ? void 0 : optionsOrName.storage;
|
|
35
|
+
const scope = optionsOrName == null ? void 0 : optionsOrName.scope;
|
|
12
36
|
if (name && storage) {
|
|
13
37
|
try {
|
|
14
38
|
const stored = storage.getItem(name);
|
|
15
|
-
if (stored !== null)
|
|
16
|
-
initialValue = JSON.parse(stored);
|
|
17
|
-
}
|
|
39
|
+
if (stored !== null) initialValue = JSON.parse(stored);
|
|
18
40
|
} catch (e) {
|
|
19
41
|
}
|
|
20
42
|
}
|
|
21
43
|
let value = initialValue;
|
|
22
44
|
const subscribers = /* @__PURE__ */ new Set();
|
|
23
|
-
const f = (...args) =>
|
|
24
|
-
if (args.length === 0) return f.value;
|
|
25
|
-
f.value = args[0];
|
|
26
|
-
};
|
|
45
|
+
const f = (...args) => args.length === 0 ? f.value : f.value = args[0];
|
|
27
46
|
Object.defineProperty(f, "value", {
|
|
28
47
|
get() {
|
|
29
48
|
if (_LV.currentEffect) {
|
|
@@ -46,23 +65,41 @@
|
|
|
46
65
|
}
|
|
47
66
|
});
|
|
48
67
|
if (name) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
68
|
+
const registry2 = scope && typeof scope === "object" ? _LV.localRegistries.get(scope) || _LV.localRegistries.set(scope, /* @__PURE__ */ new Map()).get(scope) : _LV.registry;
|
|
69
|
+
if (registry2 && registry2.has(name) && registry2.get(name) !== f) {
|
|
70
|
+
throw new Error(`Lightview: A signal or state with the name "${name}" is already registered.`);
|
|
71
|
+
}
|
|
72
|
+
if (registry2) registry2.set(name, f);
|
|
73
|
+
const futures = _LV.futureSignals.get(name);
|
|
74
|
+
if (futures) {
|
|
75
|
+
futures.forEach((resolve) => resolve(f));
|
|
55
76
|
}
|
|
56
77
|
}
|
|
57
78
|
return f;
|
|
58
79
|
};
|
|
59
|
-
const getSignal = (name,
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
80
|
+
const getSignal = (name, defaultValueOrOptions) => {
|
|
81
|
+
const options = typeof defaultValueOrOptions === "object" && defaultValueOrOptions !== null ? defaultValueOrOptions : { defaultValue: defaultValueOrOptions };
|
|
82
|
+
const { scope, defaultValue } = options;
|
|
83
|
+
const existing = lookup$1(name, scope);
|
|
84
|
+
if (existing) return existing;
|
|
85
|
+
if (defaultValue !== void 0) return signal$1(defaultValue, { name, scope });
|
|
86
|
+
const future = signal$1(void 0);
|
|
87
|
+
const handler = (realSignal) => {
|
|
88
|
+
const hasValue = realSignal && (typeof realSignal === "object" || typeof realSignal === "function") && "value" in realSignal;
|
|
89
|
+
if (hasValue) {
|
|
90
|
+
future.value = realSignal.value;
|
|
91
|
+
effect(() => {
|
|
92
|
+
future.value = realSignal.value;
|
|
93
|
+
});
|
|
94
|
+
} else {
|
|
95
|
+
future.value = realSignal;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
if (!_LV.futureSignals.has(name)) _LV.futureSignals.set(name, /* @__PURE__ */ new Set());
|
|
99
|
+
_LV.futureSignals.get(name).add(handler);
|
|
100
|
+
return future;
|
|
64
101
|
};
|
|
65
|
-
signal.get = getSignal;
|
|
102
|
+
signal$1.get = getSignal;
|
|
66
103
|
const effect = (fn) => {
|
|
67
104
|
const execute = () => {
|
|
68
105
|
if (!execute.active || execute.running) return;
|
|
@@ -89,16 +126,45 @@
|
|
|
89
126
|
return execute;
|
|
90
127
|
};
|
|
91
128
|
const computed = (fn) => {
|
|
92
|
-
const sig = signal(void 0);
|
|
129
|
+
const sig = signal$1(void 0);
|
|
93
130
|
effect(() => {
|
|
94
131
|
sig.value = fn();
|
|
95
132
|
});
|
|
96
133
|
return sig;
|
|
97
134
|
};
|
|
98
135
|
const getRegistry$1 = () => _LV.registry;
|
|
136
|
+
const internals = _LV;
|
|
99
137
|
const stateCache = /* @__PURE__ */ new WeakMap();
|
|
100
138
|
const stateSignals = /* @__PURE__ */ new WeakMap();
|
|
101
|
-
const
|
|
139
|
+
const stateSchemas = /* @__PURE__ */ new WeakMap();
|
|
140
|
+
const { parents, schemas, hooks } = internals;
|
|
141
|
+
const validate = (target, prop, value, schema) => {
|
|
142
|
+
var _a2, _b2;
|
|
143
|
+
const current = target[prop];
|
|
144
|
+
const type = typeof current;
|
|
145
|
+
const isNew = !(prop in target);
|
|
146
|
+
let behavior = schema;
|
|
147
|
+
if (typeof schema === "object" && schema !== null) behavior = schema.type;
|
|
148
|
+
if (behavior === "auto" && isNew) throw new Error(`Lightview: Cannot add new property "${prop}" to fixed 'auto' state.`);
|
|
149
|
+
if (behavior === "polymorphic" || typeof behavior === "object" && (behavior == null ? void 0 : behavior.coerce)) {
|
|
150
|
+
if (type === "number") return Number(value);
|
|
151
|
+
if (type === "boolean") return Boolean(value);
|
|
152
|
+
if (type === "string") return String(value);
|
|
153
|
+
} else if (behavior === "auto" || behavior === "dynamic") {
|
|
154
|
+
if (!isNew && typeof value !== type) {
|
|
155
|
+
throw new Error(`Lightview: Type mismatch for "${prop}". Expected ${type}, got ${typeof value}.`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (typeof schema === "object" && schema !== null && schema.transform) {
|
|
159
|
+
const trans = schema.transform;
|
|
160
|
+
const transformFn = typeof trans === "function" ? trans : internals.helpers.get(trans) || ((_b2 = (_a2 = globalThis.Lightview) == null ? void 0 : _a2.helpers) == null ? void 0 : _b2[trans]);
|
|
161
|
+
if (transformFn) value = transformFn(value);
|
|
162
|
+
}
|
|
163
|
+
if (hooks.validate(value, schema) === false) {
|
|
164
|
+
throw new Error(`Lightview: Validation failed for "${prop}".`);
|
|
165
|
+
}
|
|
166
|
+
return value;
|
|
167
|
+
};
|
|
102
168
|
const protoMethods = (proto, test) => Object.getOwnPropertyNames(proto).filter((k) => typeof proto[k] === "function" && test(k));
|
|
103
169
|
const DATE_TRACKING = protoMethods(Date.prototype, (k) => /^(to|get|valueOf)/.test(k));
|
|
104
170
|
const DATE_MUTATING = protoMethods(Date.prototype, (k) => /^set/.test(k));
|
|
@@ -138,31 +204,33 @@
|
|
|
138
204
|
const proxyGet = (target, prop, receiver, signals) => {
|
|
139
205
|
if (prop === "__parent__") return parents.get(receiver);
|
|
140
206
|
if (!signals.has(prop)) {
|
|
141
|
-
signals.set(prop, signal(Reflect.get(target, prop, receiver)));
|
|
207
|
+
signals.set(prop, signal$1(Reflect.get(target, prop, receiver)));
|
|
142
208
|
}
|
|
143
|
-
const
|
|
144
|
-
const val =
|
|
209
|
+
const signal2 = signals.get(prop);
|
|
210
|
+
const val = signal2.value;
|
|
145
211
|
if (typeof val === "object" && val !== null) {
|
|
146
|
-
const childProxy = state(val);
|
|
212
|
+
const childProxy = state$1(val);
|
|
147
213
|
parents.set(childProxy, receiver);
|
|
148
214
|
return childProxy;
|
|
149
215
|
}
|
|
150
216
|
return val;
|
|
151
217
|
};
|
|
152
218
|
const proxySet = (target, prop, value, receiver, signals) => {
|
|
219
|
+
const schema = stateSchemas.get(receiver);
|
|
220
|
+
const validatedValue = schema ? validate(target, prop, value, schema) : value;
|
|
153
221
|
if (!signals.has(prop)) {
|
|
154
|
-
signals.set(prop, signal(Reflect.get(target, prop, receiver)));
|
|
222
|
+
signals.set(prop, signal$1(Reflect.get(target, prop, receiver)));
|
|
155
223
|
}
|
|
156
|
-
const success = Reflect.set(target, prop,
|
|
157
|
-
const
|
|
158
|
-
if (success &&
|
|
224
|
+
const success = Reflect.set(target, prop, validatedValue, receiver);
|
|
225
|
+
const signal2 = signals.get(prop);
|
|
226
|
+
if (success && signal2) signal2.value = validatedValue;
|
|
159
227
|
return success;
|
|
160
228
|
};
|
|
161
229
|
const createSpecialProxy = (obj, monitor, trackingProps = []) => {
|
|
162
230
|
const signals = getOrSet(stateSignals, obj, () => /* @__PURE__ */ new Map());
|
|
163
231
|
if (!signals.has(monitor)) {
|
|
164
232
|
const initialValue = typeof obj[monitor] === "function" ? obj[monitor].call(obj) : obj[monitor];
|
|
165
|
-
signals.set(monitor, signal(initialValue));
|
|
233
|
+
signals.set(monitor, signal$1(initialValue));
|
|
166
234
|
}
|
|
167
235
|
const isDate = obj instanceof Date;
|
|
168
236
|
const isArray = Array.isArray(obj);
|
|
@@ -184,7 +252,7 @@
|
|
|
184
252
|
if (isArray && ARRAY_ITERATION.includes(prop) && typeof args[0] === "function") {
|
|
185
253
|
const originalCallback = args[0];
|
|
186
254
|
args[0] = function(element2, index2, array) {
|
|
187
|
-
const wrappedElement = typeof element2 === "object" && element2 !== null ? state(element2) : element2;
|
|
255
|
+
const wrappedElement = typeof element2 === "object" && element2 !== null ? state$1(element2) : element2;
|
|
188
256
|
if (wrappedElement && typeof wrappedElement === "object") {
|
|
189
257
|
parents.set(wrappedElement, receiver);
|
|
190
258
|
}
|
|
@@ -225,10 +293,12 @@
|
|
|
225
293
|
}
|
|
226
294
|
});
|
|
227
295
|
};
|
|
228
|
-
const state = (obj, optionsOrName) => {
|
|
296
|
+
const state$1 = (obj, optionsOrName) => {
|
|
229
297
|
if (typeof obj !== "object" || obj === null) return obj;
|
|
230
298
|
const name = typeof optionsOrName === "string" ? optionsOrName : optionsOrName == null ? void 0 : optionsOrName.name;
|
|
231
299
|
const storage = optionsOrName == null ? void 0 : optionsOrName.storage;
|
|
300
|
+
const scope = optionsOrName == null ? void 0 : optionsOrName.scope;
|
|
301
|
+
const schema = optionsOrName == null ? void 0 : optionsOrName.schema;
|
|
232
302
|
if (name && storage) {
|
|
233
303
|
try {
|
|
234
304
|
const item = storage.getItem(name);
|
|
@@ -257,6 +327,7 @@
|
|
|
257
327
|
stateCache.set(obj, proxy);
|
|
258
328
|
} else return obj;
|
|
259
329
|
}
|
|
330
|
+
if (schema) stateSchemas.set(proxy, schema);
|
|
260
331
|
if (name && storage) {
|
|
261
332
|
effect(() => {
|
|
262
333
|
try {
|
|
@@ -266,25 +337,33 @@
|
|
|
266
337
|
});
|
|
267
338
|
}
|
|
268
339
|
if (name) {
|
|
269
|
-
const registry2 = getRegistry$1();
|
|
270
|
-
if (registry2.has(name)) {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
340
|
+
const registry2 = scope && typeof scope === "object" ? internals.localRegistries.get(scope) || internals.localRegistries.set(scope, /* @__PURE__ */ new Map()).get(scope) : getRegistry$1();
|
|
341
|
+
if (registry2 && registry2.has(name) && registry2.get(name) !== proxy) {
|
|
342
|
+
throw new Error(`Lightview: A signal or state with the name "${name}" is already registered.`);
|
|
343
|
+
}
|
|
344
|
+
if (registry2) registry2.set(name, proxy);
|
|
345
|
+
const futures = internals.futureSignals.get(name);
|
|
346
|
+
if (futures) {
|
|
347
|
+
futures.forEach((resolve) => resolve(proxy));
|
|
276
348
|
}
|
|
277
349
|
}
|
|
278
350
|
return proxy;
|
|
279
351
|
};
|
|
280
|
-
const getState = (name,
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
return
|
|
352
|
+
const getState = (name, defaultValueOrOptions) => {
|
|
353
|
+
const options = typeof defaultValueOrOptions === "object" && defaultValueOrOptions !== null ? defaultValueOrOptions : { defaultValue: defaultValueOrOptions };
|
|
354
|
+
const { scope, defaultValue } = options;
|
|
355
|
+
const existing = lookup$1(name, scope);
|
|
356
|
+
if (existing) return existing;
|
|
357
|
+
if (defaultValue !== void 0) return state$1(defaultValue, { name, scope });
|
|
358
|
+
const future = signal$1(void 0);
|
|
359
|
+
const handler = (realState) => {
|
|
360
|
+
future.value = realState;
|
|
361
|
+
};
|
|
362
|
+
if (!internals.futureSignals.has(name)) internals.futureSignals.set(name, /* @__PURE__ */ new Set());
|
|
363
|
+
internals.futureSignals.get(name).add(handler);
|
|
364
|
+
return future;
|
|
286
365
|
};
|
|
287
|
-
state.get = getState;
|
|
366
|
+
state$1.get = getState;
|
|
288
367
|
const core = {
|
|
289
368
|
get currentEffect() {
|
|
290
369
|
return (globalThis.__LIGHTVIEW_INTERNALS__ || (globalThis.__LIGHTVIEW_INTERNALS__ = {})).currentEffect;
|
|
@@ -293,6 +372,38 @@
|
|
|
293
372
|
const nodeState = /* @__PURE__ */ new WeakMap();
|
|
294
373
|
const nodeStateFactory = () => ({ effects: [], onmount: null, onunmount: null });
|
|
295
374
|
const registry = getRegistry$1();
|
|
375
|
+
const scrollMemory = /* @__PURE__ */ new Map();
|
|
376
|
+
const initScrollMemory = () => {
|
|
377
|
+
if (typeof document === "undefined") return;
|
|
378
|
+
document.addEventListener("scroll", (e) => {
|
|
379
|
+
const el = e.target;
|
|
380
|
+
if (el === document || el === document.documentElement) return;
|
|
381
|
+
const key = el.id || el.getAttribute && el.getAttribute("data-preserve-scroll");
|
|
382
|
+
if (key) {
|
|
383
|
+
scrollMemory.set(key, { top: el.scrollTop, left: el.scrollLeft });
|
|
384
|
+
}
|
|
385
|
+
}, true);
|
|
386
|
+
};
|
|
387
|
+
if (typeof document !== "undefined") {
|
|
388
|
+
if (document.readyState === "loading") {
|
|
389
|
+
document.addEventListener("DOMContentLoaded", initScrollMemory);
|
|
390
|
+
} else {
|
|
391
|
+
initScrollMemory();
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
const saveScrolls = () => new Map(scrollMemory);
|
|
395
|
+
const restoreScrolls = (map2, root = document) => {
|
|
396
|
+
if (!map2 || map2.size === 0) return;
|
|
397
|
+
requestAnimationFrame(() => {
|
|
398
|
+
map2.forEach((pos, key) => {
|
|
399
|
+
const node = document.getElementById(key) || document.querySelector(`[data-preserve-scroll="${key}"]`);
|
|
400
|
+
if (node) {
|
|
401
|
+
node.scrollTop = pos.top;
|
|
402
|
+
node.scrollLeft = pos.left;
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
});
|
|
406
|
+
};
|
|
296
407
|
const trackEffect = (node, effectFn) => {
|
|
297
408
|
const state2 = getOrSet(nodeState, node, nodeStateFactory);
|
|
298
409
|
if (!state2.effects) state2.effects = [];
|
|
@@ -490,6 +601,26 @@
|
|
|
490
601
|
domNode.setAttribute(key, value);
|
|
491
602
|
}
|
|
492
603
|
reactiveAttrs[key] = value;
|
|
604
|
+
} else if (typeof value === "object" && value !== null && Lightview.hooks.processAttribute) {
|
|
605
|
+
const processed = Lightview.hooks.processAttribute(domNode, key, value);
|
|
606
|
+
if (processed !== void 0) {
|
|
607
|
+
reactiveAttrs[key] = processed;
|
|
608
|
+
} else if (key === "style") {
|
|
609
|
+
Object.entries(value).forEach(([styleKey, styleValue]) => {
|
|
610
|
+
if (typeof styleValue === "function") {
|
|
611
|
+
const runner = effect(() => {
|
|
612
|
+
domNode.style[styleKey] = styleValue();
|
|
613
|
+
});
|
|
614
|
+
trackEffect(domNode, runner);
|
|
615
|
+
} else {
|
|
616
|
+
domNode.style[styleKey] = styleValue;
|
|
617
|
+
}
|
|
618
|
+
});
|
|
619
|
+
reactiveAttrs[key] = value;
|
|
620
|
+
} else {
|
|
621
|
+
setAttributeValue(domNode, key, value);
|
|
622
|
+
reactiveAttrs[key] = value;
|
|
623
|
+
}
|
|
493
624
|
} else if (typeof value === "function") {
|
|
494
625
|
const runner = effect(() => {
|
|
495
626
|
const result = value();
|
|
@@ -501,18 +632,6 @@
|
|
|
501
632
|
});
|
|
502
633
|
trackEffect(domNode, runner);
|
|
503
634
|
reactiveAttrs[key] = value;
|
|
504
|
-
} else if (key === "style" && typeof value === "object") {
|
|
505
|
-
Object.entries(value).forEach(([styleKey, styleValue]) => {
|
|
506
|
-
if (typeof styleValue === "function") {
|
|
507
|
-
const runner = effect(() => {
|
|
508
|
-
domNode.style[styleKey] = styleValue();
|
|
509
|
-
});
|
|
510
|
-
trackEffect(domNode, runner);
|
|
511
|
-
} else {
|
|
512
|
-
domNode.style[styleKey] = styleValue;
|
|
513
|
-
}
|
|
514
|
-
});
|
|
515
|
-
reactiveAttrs[key] = value;
|
|
516
635
|
} else {
|
|
517
636
|
setAttributeValue(domNode, key, value);
|
|
518
637
|
reactiveAttrs[key] = value;
|
|
@@ -691,8 +810,11 @@
|
|
|
691
810
|
}
|
|
692
811
|
});
|
|
693
812
|
const Lightview = {
|
|
694
|
-
|
|
695
|
-
|
|
813
|
+
state: state$1,
|
|
814
|
+
getState,
|
|
815
|
+
registerSchema: (name, definition) => internals.schemas.set(name, definition),
|
|
816
|
+
signal: signal$1,
|
|
817
|
+
get: signal$1.get,
|
|
696
818
|
computed,
|
|
697
819
|
effect,
|
|
698
820
|
registry,
|
|
@@ -705,14 +827,24 @@
|
|
|
705
827
|
hooks: {
|
|
706
828
|
onNonStandardHref: null,
|
|
707
829
|
processChild: null,
|
|
708
|
-
|
|
830
|
+
processAttribute: null,
|
|
831
|
+
validateUrl: null,
|
|
832
|
+
validate: (value, schema) => internals.hooks.validate(value, schema)
|
|
709
833
|
},
|
|
710
834
|
// Internals exposed for extensions
|
|
711
835
|
internals: {
|
|
712
836
|
core,
|
|
713
837
|
domToElement,
|
|
714
838
|
wrapDomElement,
|
|
715
|
-
setupChildren
|
|
839
|
+
setupChildren,
|
|
840
|
+
trackEffect,
|
|
841
|
+
saveScrolls,
|
|
842
|
+
restoreScrolls,
|
|
843
|
+
localRegistries: internals.localRegistries,
|
|
844
|
+
futureSignals: internals.futureSignals,
|
|
845
|
+
schemas: internals.schemas,
|
|
846
|
+
parents: internals.parents,
|
|
847
|
+
hooks: internals.hooks
|
|
716
848
|
}
|
|
717
849
|
};
|
|
718
850
|
if (typeof module !== "undefined" && module.exports) {
|
|
@@ -723,8 +855,8 @@
|
|
|
723
855
|
globalThis.addEventListener("click", (e) => {
|
|
724
856
|
const path = e.composedPath();
|
|
725
857
|
const link = path.find((el) => {
|
|
726
|
-
var
|
|
727
|
-
return el.tagName === "A" && ((
|
|
858
|
+
var _a2, _b2;
|
|
859
|
+
return el.tagName === "A" && ((_b2 = (_a2 = el.getAttribute) == null ? void 0 : _a2.call(el, "href")) == null ? void 0 : _b2.startsWith("#"));
|
|
728
860
|
});
|
|
729
861
|
if (link && !e.defaultPrevented) {
|
|
730
862
|
const href = link.getAttribute("href");
|
|
@@ -749,23 +881,23 @@
|
|
|
749
881
|
});
|
|
750
882
|
if (typeof MutationObserver !== "undefined") {
|
|
751
883
|
const walkNodes = (node, fn) => {
|
|
752
|
-
var
|
|
884
|
+
var _a2;
|
|
753
885
|
fn(node);
|
|
754
|
-
(
|
|
886
|
+
(_a2 = node.childNodes) == null ? void 0 : _a2.forEach((n) => walkNodes(n, fn));
|
|
755
887
|
if (node.shadowRoot) walkNodes(node.shadowRoot, fn);
|
|
756
888
|
};
|
|
757
889
|
const cleanupNode = (node) => walkNodes(node, (n) => {
|
|
758
|
-
var
|
|
890
|
+
var _a2, _b2;
|
|
759
891
|
const s = nodeState.get(n);
|
|
760
892
|
if (s) {
|
|
761
|
-
(
|
|
762
|
-
(
|
|
893
|
+
(_a2 = s.effects) == null ? void 0 : _a2.forEach((e) => e.stop());
|
|
894
|
+
(_b2 = s.onunmount) == null ? void 0 : _b2.call(s, n);
|
|
763
895
|
nodeState.delete(n);
|
|
764
896
|
}
|
|
765
897
|
});
|
|
766
898
|
const mountNode = (node) => walkNodes(node, (n) => {
|
|
767
|
-
var
|
|
768
|
-
(
|
|
899
|
+
var _a2, _b2;
|
|
900
|
+
(_b2 = (_a2 = nodeState.get(n)) == null ? void 0 : _a2.onmount) == null ? void 0 : _b2.call(_a2, n);
|
|
769
901
|
});
|
|
770
902
|
const observer = new MutationObserver((mutations) => {
|
|
771
903
|
mutations.forEach((mutation) => {
|
|
@@ -819,7 +951,7 @@
|
|
|
819
951
|
return keys.length === 1 && isValidTagName(keys[0]) && typeof obj[keys[0]] === "object";
|
|
820
952
|
};
|
|
821
953
|
const convertObjectDOM = (obj) => {
|
|
822
|
-
var
|
|
954
|
+
var _a2, _b2;
|
|
823
955
|
if (typeof obj !== "object" || obj === null) return obj;
|
|
824
956
|
if (Array.isArray(obj)) return obj.map(convertObjectDOM);
|
|
825
957
|
if (obj.tag) return { ...obj, children: obj.children ? convertObjectDOM(obj.children) : [] };
|
|
@@ -827,7 +959,7 @@
|
|
|
827
959
|
const tagKey = Object.keys(obj)[0];
|
|
828
960
|
const content = obj[tagKey];
|
|
829
961
|
const LV = typeof window !== "undefined" ? globalThis.Lightview : typeof globalThis !== "undefined" ? globalThis.Lightview : null;
|
|
830
|
-
const tag = ((
|
|
962
|
+
const tag = ((_b2 = (_a2 = LV == null ? void 0 : LV.tags) == null ? void 0 : _a2._customTags) == null ? void 0 : _b2[tagKey]) || tagKey;
|
|
831
963
|
const { children, ...attributes } = content;
|
|
832
964
|
return { tag, attributes, children: children ? convertObjectDOM(children) : [] };
|
|
833
965
|
};
|
|
@@ -889,7 +1021,7 @@
|
|
|
889
1021
|
return null;
|
|
890
1022
|
}
|
|
891
1023
|
};
|
|
892
|
-
const themeSignal = signal(
|
|
1024
|
+
const themeSignal = signal$1(
|
|
893
1025
|
typeof document !== "undefined" && document.documentElement.getAttribute("data-theme") || getSavedTheme() || "light"
|
|
894
1026
|
);
|
|
895
1027
|
const setTheme = (themeName) => {
|
|
@@ -1115,12 +1247,12 @@
|
|
|
1115
1247
|
const frag = document.createDocumentFragment();
|
|
1116
1248
|
frag.appendChild(createMarker(markerId, false));
|
|
1117
1249
|
elements.forEach((c) => {
|
|
1118
|
-
var
|
|
1250
|
+
var _a2, _b2, _c;
|
|
1119
1251
|
if (typeof c === "string") frag.appendChild(document.createTextNode(c));
|
|
1120
1252
|
else if (c.domEl) frag.appendChild(c.domEl);
|
|
1121
1253
|
else if (c instanceof Node) frag.appendChild(c);
|
|
1122
1254
|
else {
|
|
1123
|
-
const v = ((_c = (
|
|
1255
|
+
const v = ((_c = (_a2 = globalThis.Lightview) == null ? void 0 : (_b2 = _a2.hooks).processChild) == null ? void 0 : _c.call(_b2, c)) || c;
|
|
1124
1256
|
if (v.tag) {
|
|
1125
1257
|
const n = element2(v.tag, v.attributes || {}, v.children || []);
|
|
1126
1258
|
if (n == null ? void 0 : n.domEl) frag.appendChild(n.domEl);
|
|
@@ -1137,10 +1269,10 @@
|
|
|
1137
1269
|
};
|
|
1138
1270
|
const isPath = (s) => typeof s === "string" && !isDangerousProtocol(s) && /^(https?:|\.|\/|[\w])|(\.(html|json|[vo]dom|cdomc?))$/i.test(s);
|
|
1139
1271
|
const fetchContent = async (src) => {
|
|
1140
|
-
var
|
|
1272
|
+
var _a2;
|
|
1141
1273
|
try {
|
|
1142
1274
|
const LV = globalThis.Lightview;
|
|
1143
|
-
if (((
|
|
1275
|
+
if (((_a2 = LV == null ? void 0 : LV.hooks) == null ? void 0 : _a2.validateUrl) && !LV.hooks.validateUrl(src)) {
|
|
1144
1276
|
console.warn(`[LightviewX] Fetch blocked by validateUrl hook: ${src}`);
|
|
1145
1277
|
return null;
|
|
1146
1278
|
}
|
|
@@ -1165,10 +1297,10 @@
|
|
|
1165
1297
|
}
|
|
1166
1298
|
};
|
|
1167
1299
|
const parseElements = (content, isJson, isHtml, el, element2, isCdom = false, ext = "") => {
|
|
1168
|
-
var
|
|
1300
|
+
var _a2;
|
|
1169
1301
|
if (isJson) return Array.isArray(content) ? content : [content];
|
|
1170
1302
|
if (isCdom && ext === "cdomc") {
|
|
1171
|
-
const parser = (
|
|
1303
|
+
const parser = (_a2 = globalThis.LightviewCDOM) == null ? void 0 : _a2.parseCDOMC;
|
|
1172
1304
|
if (parser) {
|
|
1173
1305
|
try {
|
|
1174
1306
|
const obj = parser(content);
|
|
@@ -1201,11 +1333,14 @@
|
|
|
1201
1333
|
return null;
|
|
1202
1334
|
}
|
|
1203
1335
|
};
|
|
1204
|
-
const updateTargetContent = (el, elements, raw, loc, contentHash,
|
|
1336
|
+
const updateTargetContent = (el, elements, raw, loc, contentHash, options, targetHash = null) => {
|
|
1337
|
+
var _a2;
|
|
1338
|
+
const { element: element2, setupChildren: setupChildren2, saveScrolls: saveScrolls2, restoreScrolls: restoreScrolls2 } = { ...options, ...(_a2 = globalThis.Lightview) == null ? void 0 : _a2.internals };
|
|
1205
1339
|
const markerId = `${loc}-${contentHash.slice(0, 8)}`;
|
|
1206
1340
|
let track = getOrSet(insertedContentMap, el.domEl, () => ({}));
|
|
1207
1341
|
if (track[loc]) removeInsertedContent(el.domEl, `${loc}-${track[loc].slice(0, 8)}`);
|
|
1208
1342
|
track[loc] = contentHash;
|
|
1343
|
+
const scrollMap = saveScrolls2 ? saveScrolls2() : null;
|
|
1209
1344
|
const performScroll = (root) => {
|
|
1210
1345
|
if (!targetHash) return;
|
|
1211
1346
|
requestAnimationFrame(() => {
|
|
@@ -1219,18 +1354,24 @@
|
|
|
1219
1354
|
});
|
|
1220
1355
|
});
|
|
1221
1356
|
};
|
|
1357
|
+
const runRestore = (root) => {
|
|
1358
|
+
if (restoreScrolls2 && scrollMap) restoreScrolls2(scrollMap, root);
|
|
1359
|
+
};
|
|
1222
1360
|
if (loc === "shadow") {
|
|
1223
1361
|
if (!el.domEl.shadowRoot) el.domEl.attachShadow({ mode: "open" });
|
|
1224
1362
|
setupChildren2(elements, el.domEl.shadowRoot);
|
|
1225
1363
|
executeScripts(el.domEl.shadowRoot);
|
|
1226
1364
|
performScroll(el.domEl.shadowRoot);
|
|
1365
|
+
runRestore(el.domEl.shadowRoot);
|
|
1227
1366
|
} else if (loc === "innerhtml") {
|
|
1228
1367
|
el.children = elements;
|
|
1229
1368
|
executeScripts(el.domEl);
|
|
1230
1369
|
performScroll(document);
|
|
1370
|
+
runRestore(el.domEl);
|
|
1231
1371
|
} else {
|
|
1232
1372
|
insert(elements, el.domEl, loc, markerId, { element: element2, setupChildren: setupChildren2 });
|
|
1233
1373
|
performScroll(document);
|
|
1374
|
+
runRestore(el.domEl);
|
|
1234
1375
|
}
|
|
1235
1376
|
};
|
|
1236
1377
|
const handleSrcAttribute = async (el, src, tagName, { element: element2, setupChildren: setupChildren2 }) => {
|
|
@@ -1263,9 +1404,9 @@
|
|
|
1263
1404
|
if (root) {
|
|
1264
1405
|
requestAnimationFrame(() => {
|
|
1265
1406
|
requestAnimationFrame(() => {
|
|
1266
|
-
var
|
|
1407
|
+
var _a2;
|
|
1267
1408
|
const id = targetHash.startsWith("#") ? targetHash.slice(1) : targetHash;
|
|
1268
|
-
const target = root.getElementById ? root.getElementById(id) : (
|
|
1409
|
+
const target = root.getElementById ? root.getElementById(id) : (_a2 = root.querySelector) == null ? void 0 : _a2.call(root, `#${id}`);
|
|
1269
1410
|
if (target) {
|
|
1270
1411
|
target.style.scrollMarginTop = "calc(var(--site-nav-height, 0px) + 2rem)";
|
|
1271
1412
|
target.scrollIntoView({ behavior: "smooth", block: "start", inline: "start" });
|
|
@@ -1292,7 +1433,7 @@
|
|
|
1292
1433
|
return { selector: targetStr, location: null };
|
|
1293
1434
|
};
|
|
1294
1435
|
const handleNonStandardHref = (e, { domToElement: domToElement2, wrapDomElement: wrapDomElement2 }) => {
|
|
1295
|
-
var
|
|
1436
|
+
var _a2;
|
|
1296
1437
|
const clickedEl = e.target.closest("[href]");
|
|
1297
1438
|
if (!clickedEl) return;
|
|
1298
1439
|
const tagName = clickedEl.tagName.toLowerCase();
|
|
@@ -1300,7 +1441,7 @@
|
|
|
1300
1441
|
e.preventDefault();
|
|
1301
1442
|
const href = clickedEl.getAttribute("href");
|
|
1302
1443
|
const LV = globalThis.Lightview;
|
|
1303
|
-
if (href && (isDangerousProtocol(href) || ((
|
|
1444
|
+
if (href && (isDangerousProtocol(href) || ((_a2 = LV == null ? void 0 : LV.hooks) == null ? void 0 : _a2.validateUrl) && !LV.hooks.validateUrl(href))) {
|
|
1304
1445
|
console.warn(`[LightviewX] Navigation or fetch blocked by security policy: ${href}`);
|
|
1305
1446
|
return;
|
|
1306
1447
|
}
|
|
@@ -1460,9 +1601,9 @@
|
|
|
1460
1601
|
return { events, exclusions, calls };
|
|
1461
1602
|
};
|
|
1462
1603
|
const globalBeforeInterceptor = async (e) => {
|
|
1463
|
-
var
|
|
1604
|
+
var _a2, _b2;
|
|
1464
1605
|
if (e[BYPASS_FLAG]) return;
|
|
1465
|
-
const target = (
|
|
1606
|
+
const target = (_b2 = (_a2 = e.target).closest) == null ? void 0 : _b2.call(_a2, "[lv-before]");
|
|
1466
1607
|
if (!target) return;
|
|
1467
1608
|
const { events, exclusions, calls } = parseBeforeAttribute(target.getAttribute("lv-before"));
|
|
1468
1609
|
const isExcluded = exclusions.includes(e.type);
|
|
@@ -1677,7 +1818,7 @@
|
|
|
1677
1818
|
}
|
|
1678
1819
|
}
|
|
1679
1820
|
return processTemplateChild(child, {
|
|
1680
|
-
state,
|
|
1821
|
+
state: state$1,
|
|
1681
1822
|
signal: LV.signal
|
|
1682
1823
|
});
|
|
1683
1824
|
};
|
|
@@ -1858,7 +1999,7 @@
|
|
|
1858
1999
|
}).filter(Boolean);
|
|
1859
2000
|
}
|
|
1860
2001
|
render() {
|
|
1861
|
-
var
|
|
2002
|
+
var _a2, _b2;
|
|
1862
2003
|
const props = { useShadow: false };
|
|
1863
2004
|
for (const attr of this.attributes) {
|
|
1864
2005
|
const name = attr.name.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
|
|
@@ -1882,7 +2023,7 @@
|
|
|
1882
2023
|
const vdomChildren = this.parseChildrenToVDOM();
|
|
1883
2024
|
const children = Object.keys(childElements).length > 0 ? vdomChildren : [{ tag: globalThis.Lightview.tags.slot }];
|
|
1884
2025
|
const result = Component(props, ...children);
|
|
1885
|
-
if (((
|
|
2026
|
+
if (((_b2 = (_a2 = globalThis.Lightview) == null ? void 0 : _a2.internals) == null ? void 0 : _b2.setupChildren) && this.themeWrapper) {
|
|
1886
2027
|
this.themeWrapper.innerHTML = "";
|
|
1887
2028
|
globalThis.Lightview.internals.setupChildren([result], this.themeWrapper);
|
|
1888
2029
|
}
|
|
@@ -1895,8 +2036,91 @@
|
|
|
1895
2036
|
}
|
|
1896
2037
|
};
|
|
1897
2038
|
};
|
|
2039
|
+
const validateJSONSchema = (value, schema) => {
|
|
2040
|
+
var _a2;
|
|
2041
|
+
if (!schema) return true;
|
|
2042
|
+
const errors = [];
|
|
2043
|
+
const internals2 = (_a2 = globalThis.Lightview) == null ? void 0 : _a2.internals;
|
|
2044
|
+
const check = (val, sch, path = "") => {
|
|
2045
|
+
var _a3;
|
|
2046
|
+
if (!sch) return true;
|
|
2047
|
+
if (typeof sch === "string") {
|
|
2048
|
+
const registered = (_a3 = internals2 == null ? void 0 : internals2.schemas) == null ? void 0 : _a3.get(sch);
|
|
2049
|
+
if (registered) return check(val, registered, path);
|
|
2050
|
+
return true;
|
|
2051
|
+
}
|
|
2052
|
+
const type = sch.type;
|
|
2053
|
+
const getType = (v) => {
|
|
2054
|
+
if (v === null) return "null";
|
|
2055
|
+
if (Array.isArray(v)) return "array";
|
|
2056
|
+
return typeof v;
|
|
2057
|
+
};
|
|
2058
|
+
const currentType = getType(val);
|
|
2059
|
+
if (type && type !== currentType) {
|
|
2060
|
+
if (type === "integer" && Number.isInteger(val)) ;
|
|
2061
|
+
else if (!(type === "number" && typeof val === "number")) {
|
|
2062
|
+
errors.push({ path, message: `Expected type ${type}, got ${currentType}`, keyword: "type" });
|
|
2063
|
+
return false;
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
if (currentType === "string") {
|
|
2067
|
+
if (sch.minLength !== void 0 && val.length < sch.minLength) errors.push({ path, keyword: "minLength" });
|
|
2068
|
+
if (sch.maxLength !== void 0 && val.length > sch.maxLength) errors.push({ path, keyword: "maxLength" });
|
|
2069
|
+
if (sch.pattern !== void 0 && !new RegExp(sch.pattern).test(val)) errors.push({ path, keyword: "pattern" });
|
|
2070
|
+
if (sch.format === "email" && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val)) errors.push({ path, keyword: "format" });
|
|
2071
|
+
}
|
|
2072
|
+
if (currentType === "number") {
|
|
2073
|
+
if (sch.minimum !== void 0 && val < sch.minimum) errors.push({ path, keyword: "minimum" });
|
|
2074
|
+
if (sch.maximum !== void 0 && val > sch.maximum) errors.push({ path, keyword: "maximum" });
|
|
2075
|
+
if (sch.multipleOf !== void 0 && val % sch.multipleOf !== 0) errors.push({ path, keyword: "multipleOf" });
|
|
2076
|
+
}
|
|
2077
|
+
if (currentType === "object") {
|
|
2078
|
+
if (sch.required && Array.isArray(sch.required)) {
|
|
2079
|
+
for (const key of sch.required) {
|
|
2080
|
+
if (!(key in val)) errors.push({ path: path ? `${path}.${key}` : key, keyword: "required" });
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
if (sch.properties) {
|
|
2084
|
+
for (const key in sch.properties) {
|
|
2085
|
+
if (key in val) check(val[key], sch.properties[key], path ? `${path}.${key}` : key);
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
if (sch.additionalProperties === false) {
|
|
2089
|
+
for (const key in val) {
|
|
2090
|
+
if (!sch.properties || !(key in sch.properties)) errors.push({ path: path ? `${path}.${key}` : key, keyword: "additionalProperties" });
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
}
|
|
2094
|
+
if (currentType === "array") {
|
|
2095
|
+
if (sch.minItems !== void 0 && val.length < sch.minItems) errors.push({ path, keyword: "minItems" });
|
|
2096
|
+
if (sch.maxItems !== void 0 && val.length > sch.maxItems) errors.push({ path, keyword: "maxItems" });
|
|
2097
|
+
if (sch.uniqueItems && new Set(val).size !== val.length) errors.push({ path, keyword: "uniqueItems" });
|
|
2098
|
+
if (sch.items) {
|
|
2099
|
+
val.forEach((item, i) => check(item, sch.items, `${path}[${i}]`));
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
if (sch.const !== void 0 && val !== sch.const) errors.push({ path, keyword: "const" });
|
|
2103
|
+
if (sch.enum && !sch.enum.includes(val)) errors.push({ path, keyword: "enum" });
|
|
2104
|
+
return errors.length === 0;
|
|
2105
|
+
};
|
|
2106
|
+
const valid = check(value, schema);
|
|
2107
|
+
return valid || errors;
|
|
2108
|
+
};
|
|
2109
|
+
const lvInternals = globalThis.__LIGHTVIEW_INTERNALS__ || ((_a = globalThis.Lightview) == null ? void 0 : _a.internals);
|
|
2110
|
+
if (lvInternals) {
|
|
2111
|
+
const hooks2 = lvInternals.hooks || ((_b = globalThis.Lightview) == null ? void 0 : _b.hooks);
|
|
2112
|
+
if (hooks2) {
|
|
2113
|
+
hooks2.validate = (value, schema) => {
|
|
2114
|
+
const result = validateJSONSchema(value, schema);
|
|
2115
|
+
if (result === true) return true;
|
|
2116
|
+
const msg = result.map((e) => `${e.path || "root"}: failed ${e.keyword}${e.message ? " (" + e.message + ")" : ""}`).join(", ");
|
|
2117
|
+
throw new Error(`Lightview Validation Error: ${msg}`);
|
|
2118
|
+
};
|
|
2119
|
+
}
|
|
2120
|
+
if (globalThis.Lightview) globalThis.Lightview.validate = validateJSONSchema;
|
|
2121
|
+
}
|
|
1898
2122
|
const LightviewX = {
|
|
1899
|
-
state,
|
|
2123
|
+
state: state$1,
|
|
1900
2124
|
themeSignal,
|
|
1901
2125
|
setTheme,
|
|
1902
2126
|
registerStyleSheet,
|
|
@@ -1912,6 +2136,7 @@
|
|
|
1912
2136
|
preloadComponentCSS,
|
|
1913
2137
|
createCustomElement,
|
|
1914
2138
|
customElementWrapper,
|
|
2139
|
+
validate: validateJSONSchema,
|
|
1915
2140
|
internals: {
|
|
1916
2141
|
handleSrcAttribute,
|
|
1917
2142
|
parseElements
|
|
@@ -1959,23 +2184,26 @@
|
|
|
1959
2184
|
};
|
|
1960
2185
|
const registerHelper = (name, fn, options = {}) => {
|
|
1961
2186
|
helpers.set(name, fn);
|
|
2187
|
+
if (globalThis.__LIGHTVIEW_INTERNALS__) {
|
|
2188
|
+
globalThis.__LIGHTVIEW_INTERNALS__.helpers.set(name, fn);
|
|
2189
|
+
}
|
|
1962
2190
|
if (options) helperOptions.set(name, options);
|
|
1963
2191
|
};
|
|
1964
2192
|
const registerOperator = (helperName, symbol, position, precedence) => {
|
|
1965
|
-
var
|
|
2193
|
+
var _a2;
|
|
1966
2194
|
if (!["prefix", "postfix", "infix"].includes(position)) {
|
|
1967
2195
|
throw new Error(`Invalid operator position: ${position}. Must be 'prefix', 'postfix', or 'infix'.`);
|
|
1968
2196
|
}
|
|
1969
2197
|
if (!helpers.has(helperName)) {
|
|
1970
|
-
(
|
|
2198
|
+
(_a2 = globalThis.console) == null ? void 0 : _a2.warn(`LightviewCDOM: Operator "${symbol}" registered for helper "${helperName}" which is not yet registered.`);
|
|
1971
2199
|
}
|
|
1972
2200
|
const prec = precedence ?? DEFAULT_PRECEDENCE[position];
|
|
1973
2201
|
operators[position].set(symbol, { helper: helperName, precedence: prec });
|
|
1974
2202
|
};
|
|
1975
2203
|
const getLV = () => globalThis.Lightview || null;
|
|
1976
2204
|
const getRegistry = () => {
|
|
1977
|
-
var
|
|
1978
|
-
return ((
|
|
2205
|
+
var _a2;
|
|
2206
|
+
return ((_a2 = getLV()) == null ? void 0 : _a2.registry) || null;
|
|
1979
2207
|
};
|
|
1980
2208
|
class BindingTarget {
|
|
1981
2209
|
constructor(parent, key) {
|
|
@@ -2032,19 +2260,12 @@
|
|
|
2032
2260
|
if (typeof path !== "string") return path;
|
|
2033
2261
|
const registry2 = getRegistry();
|
|
2034
2262
|
if (path === ".") return unwrapSignal(context);
|
|
2035
|
-
if (path.startsWith("
|
|
2263
|
+
if (path.startsWith("=/")) {
|
|
2036
2264
|
const [rootName, ...rest] = path.slice(2).split("/");
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
return traverse(localState[rootName], rest);
|
|
2042
|
-
}
|
|
2043
|
-
cur = cur.__parent__;
|
|
2044
|
-
}
|
|
2045
|
-
const rootSignal = registry2 == null ? void 0 : registry2.get(rootName);
|
|
2046
|
-
if (!rootSignal) return void 0;
|
|
2047
|
-
return traverse(rootSignal, rest);
|
|
2265
|
+
const LV = getLV();
|
|
2266
|
+
const root = LV ? LV.get(rootName, { scope: (context == null ? void 0 : context.__node__) || context }) : registry2 == null ? void 0 : registry2.get(rootName);
|
|
2267
|
+
if (!root) return void 0;
|
|
2268
|
+
return traverse(root, rest);
|
|
2048
2269
|
}
|
|
2049
2270
|
if (path.startsWith("./")) {
|
|
2050
2271
|
return traverse(context, path.slice(2).split("/"));
|
|
@@ -2067,20 +2288,13 @@
|
|
|
2067
2288
|
if (typeof path !== "string") return path;
|
|
2068
2289
|
const registry2 = getRegistry();
|
|
2069
2290
|
if (path === ".") return context;
|
|
2070
|
-
if (path.startsWith("
|
|
2291
|
+
if (path.startsWith("=/")) {
|
|
2071
2292
|
const segments = path.slice(2).split(/[/.]/);
|
|
2072
2293
|
const rootName = segments.shift();
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
return traverseAsContext(localState[rootName], segments);
|
|
2078
|
-
}
|
|
2079
|
-
cur = cur.__parent__;
|
|
2080
|
-
}
|
|
2081
|
-
const rootSignal = registry2 == null ? void 0 : registry2.get(rootName);
|
|
2082
|
-
if (!rootSignal) return void 0;
|
|
2083
|
-
return traverseAsContext(rootSignal, segments);
|
|
2294
|
+
const LV = getLV();
|
|
2295
|
+
const root = LV ? LV.get(rootName, { scope: (context == null ? void 0 : context.__node__) || context }) : registry2 == null ? void 0 : registry2.get(rootName);
|
|
2296
|
+
if (!root) return void 0;
|
|
2297
|
+
return traverseAsContext(root, segments);
|
|
2084
2298
|
}
|
|
2085
2299
|
if (path.startsWith("./")) {
|
|
2086
2300
|
return traverseAsContext(context, path.slice(2).split(/[\/.]/));
|
|
@@ -2108,6 +2322,7 @@
|
|
|
2108
2322
|
return this.fn(context);
|
|
2109
2323
|
}
|
|
2110
2324
|
}
|
|
2325
|
+
const isNode = (val) => val && typeof val === "object" && globalThis.Node && val instanceof globalThis.Node;
|
|
2111
2326
|
const resolveArgument = (arg, context, globalMode = false) => {
|
|
2112
2327
|
if (arg.startsWith("'") && arg.endsWith("'") || arg.startsWith('"') && arg.endsWith('"')) {
|
|
2113
2328
|
return { value: arg.slice(1, -1), isLiteral: true };
|
|
@@ -2128,9 +2343,21 @@
|
|
|
2128
2343
|
isLazy: true
|
|
2129
2344
|
};
|
|
2130
2345
|
}
|
|
2346
|
+
if (arg === "$this" || arg.startsWith("$this/") || arg.startsWith("$this.")) {
|
|
2347
|
+
return {
|
|
2348
|
+
value: new LazyValue((context2) => {
|
|
2349
|
+
const node = (context2 == null ? void 0 : context2.__node__) || context2;
|
|
2350
|
+
if (arg === "$this") return node;
|
|
2351
|
+
const path = arg.startsWith("$this.") ? arg.slice(6) : arg.slice(6);
|
|
2352
|
+
return resolvePath(path, node);
|
|
2353
|
+
}),
|
|
2354
|
+
isLazy: true
|
|
2355
|
+
};
|
|
2356
|
+
}
|
|
2131
2357
|
if (arg === "$event" || arg.startsWith("$event/") || arg.startsWith("$event.")) {
|
|
2132
2358
|
return {
|
|
2133
|
-
value: new LazyValue((
|
|
2359
|
+
value: new LazyValue((context2) => {
|
|
2360
|
+
const event = (context2 == null ? void 0 : context2.$event) || (context2 == null ? void 0 : context2.event) || context2;
|
|
2134
2361
|
if (arg === "$event") return event;
|
|
2135
2362
|
const path = arg.startsWith("$event.") ? arg.slice(7) : arg.slice(7);
|
|
2136
2363
|
return resolvePath(path, event);
|
|
@@ -2143,11 +2370,23 @@
|
|
|
2143
2370
|
const data = parseJPRX(arg);
|
|
2144
2371
|
const resolveTemplate = (node, context2) => {
|
|
2145
2372
|
if (typeof node === "string") {
|
|
2146
|
-
if (node.startsWith("
|
|
2373
|
+
if (node.startsWith("=")) {
|
|
2147
2374
|
const res = resolveExpression(node, context2);
|
|
2148
2375
|
const final = res instanceof LazyValue ? res.resolve(context2) : res;
|
|
2149
2376
|
return unwrapSignal(final);
|
|
2150
2377
|
}
|
|
2378
|
+
if (node === "$this" || node.startsWith("$this/") || node.startsWith("$this.")) {
|
|
2379
|
+
const path = node.startsWith("$this.") || node.startsWith("$this/") ? node.slice(6) : node.slice(6);
|
|
2380
|
+
const ctxNode = (context2 == null ? void 0 : context2.__node__) || context2;
|
|
2381
|
+
const res = node === "$this" ? ctxNode : resolvePath(path, ctxNode);
|
|
2382
|
+
return unwrapSignal(res);
|
|
2383
|
+
}
|
|
2384
|
+
if (node === "$event" || node.startsWith("$event/") || node.startsWith("$event.")) {
|
|
2385
|
+
const path = node.startsWith("$event.") || node.startsWith("$event/") ? node.slice(7) : node.slice(7);
|
|
2386
|
+
const event = (context2 == null ? void 0 : context2.$event) || (context2 == null ? void 0 : context2.event) || (context2 && !isNode(context2) ? context2 : null);
|
|
2387
|
+
const res = node === "$event" ? event : resolvePath(path, event);
|
|
2388
|
+
return unwrapSignal(res);
|
|
2389
|
+
}
|
|
2151
2390
|
if (node === "_" || node.startsWith("_/") || node.startsWith("_.")) {
|
|
2152
2391
|
const path = node.startsWith("_.") || node.startsWith("_/") ? node.slice(2) : node.slice(2);
|
|
2153
2392
|
const res = node === "_" ? context2 : resolvePath(path, context2);
|
|
@@ -2165,7 +2404,7 @@
|
|
|
2165
2404
|
};
|
|
2166
2405
|
const hasReactive = (obj) => {
|
|
2167
2406
|
if (typeof obj === "string") {
|
|
2168
|
-
return obj.startsWith("
|
|
2407
|
+
return obj.startsWith("=") || obj.startsWith("_") || obj.startsWith("../");
|
|
2169
2408
|
}
|
|
2170
2409
|
if (Array.isArray(obj)) return obj.some(hasReactive);
|
|
2171
2410
|
if (obj && typeof obj === "object") return Object.values(obj).some(hasReactive);
|
|
@@ -2184,9 +2423,9 @@
|
|
|
2184
2423
|
if (arg.includes("(")) {
|
|
2185
2424
|
let nestedExpr = arg;
|
|
2186
2425
|
if (arg.startsWith("/")) {
|
|
2187
|
-
nestedExpr = "
|
|
2188
|
-
} else if (globalMode && !arg.startsWith("
|
|
2189
|
-
nestedExpr =
|
|
2426
|
+
nestedExpr = "=" + arg;
|
|
2427
|
+
} else if (globalMode && !arg.startsWith("=") && !arg.startsWith("./")) {
|
|
2428
|
+
nestedExpr = `=/${arg}`;
|
|
2190
2429
|
}
|
|
2191
2430
|
const val = resolveExpression(nestedExpr, context);
|
|
2192
2431
|
if (val instanceof LazyValue) {
|
|
@@ -2196,11 +2435,11 @@
|
|
|
2196
2435
|
}
|
|
2197
2436
|
let normalizedPath;
|
|
2198
2437
|
if (arg.startsWith("/")) {
|
|
2199
|
-
normalizedPath = "
|
|
2200
|
-
} else if (arg.startsWith("
|
|
2438
|
+
normalizedPath = "=" + arg;
|
|
2439
|
+
} else if (arg.startsWith("=") || arg.startsWith("./") || arg.startsWith("../")) {
|
|
2201
2440
|
normalizedPath = arg;
|
|
2202
2441
|
} else if (globalMode) {
|
|
2203
|
-
normalizedPath =
|
|
2442
|
+
normalizedPath = `=/${arg}`;
|
|
2204
2443
|
} else {
|
|
2205
2444
|
normalizedPath = `./${arg}`;
|
|
2206
2445
|
}
|
|
@@ -2245,6 +2484,8 @@
|
|
|
2245
2484
|
// ... suffix
|
|
2246
2485
|
PLACEHOLDER: "PLACEHOLDER",
|
|
2247
2486
|
// _, _/path
|
|
2487
|
+
THIS: "THIS",
|
|
2488
|
+
// $this
|
|
2248
2489
|
EVENT: "EVENT",
|
|
2249
2490
|
// $event, $event.target
|
|
2250
2491
|
EOF: "EOF"
|
|
@@ -2267,15 +2508,16 @@
|
|
|
2267
2508
|
i++;
|
|
2268
2509
|
continue;
|
|
2269
2510
|
}
|
|
2270
|
-
if (expr[i] === "
|
|
2271
|
-
|
|
2272
|
-
|
|
2511
|
+
if (expr[i] === "=" && i + 1 < len2) {
|
|
2512
|
+
const prefixOps = [...operators.prefix.keys()].sort((a, b) => b.length - a.length);
|
|
2513
|
+
let isPrefixOp = false;
|
|
2514
|
+
for (const op of prefixOps) {
|
|
2273
2515
|
if (expr.slice(i + 1, i + 1 + op.length) === op) {
|
|
2274
|
-
|
|
2516
|
+
isPrefixOp = true;
|
|
2275
2517
|
break;
|
|
2276
2518
|
}
|
|
2277
2519
|
}
|
|
2278
|
-
if (
|
|
2520
|
+
if (isPrefixOp) {
|
|
2279
2521
|
i++;
|
|
2280
2522
|
continue;
|
|
2281
2523
|
}
|
|
@@ -2311,7 +2553,7 @@
|
|
|
2311
2553
|
continue;
|
|
2312
2554
|
}
|
|
2313
2555
|
const validBefore = /[\s)]/.test(before) || i === 0 || tokens.length === 0 || tokens[tokens.length - 1].type === TokenType.LPAREN || tokens[tokens.length - 1].type === TokenType.COMMA || tokens[tokens.length - 1].type === TokenType.OPERATOR;
|
|
2314
|
-
const validAfter = /[\s(
|
|
2556
|
+
const validAfter = /[\s(=./'"0-9_]/.test(after) || i + op.length >= len2 || opSymbols.some((o) => expr.slice(i + op.length).startsWith(o));
|
|
2315
2557
|
if (validBefore || validAfter) {
|
|
2316
2558
|
matchedOp = op;
|
|
2317
2559
|
break;
|
|
@@ -2367,6 +2609,16 @@
|
|
|
2367
2609
|
tokens.push({ type: TokenType.PLACEHOLDER, value: placeholder });
|
|
2368
2610
|
continue;
|
|
2369
2611
|
}
|
|
2612
|
+
if (expr.slice(i, i + 5) === "$this") {
|
|
2613
|
+
let thisPath = "$this";
|
|
2614
|
+
i += 5;
|
|
2615
|
+
while (i < len2 && /[a-zA-Z0-9_./]/.test(expr[i])) {
|
|
2616
|
+
thisPath += expr[i];
|
|
2617
|
+
i++;
|
|
2618
|
+
}
|
|
2619
|
+
tokens.push({ type: TokenType.THIS, value: thisPath });
|
|
2620
|
+
continue;
|
|
2621
|
+
}
|
|
2370
2622
|
if (expr.slice(i, i + 6) === "$event") {
|
|
2371
2623
|
let eventPath = "$event";
|
|
2372
2624
|
i += 6;
|
|
@@ -2377,7 +2629,7 @@
|
|
|
2377
2629
|
tokens.push({ type: TokenType.EVENT, value: eventPath });
|
|
2378
2630
|
continue;
|
|
2379
2631
|
}
|
|
2380
|
-
if (expr[i] === "
|
|
2632
|
+
if (expr[i] === "=" || expr[i] === "." || expr[i] === "/") {
|
|
2381
2633
|
let path = "";
|
|
2382
2634
|
while (i < len2) {
|
|
2383
2635
|
let isOp = false;
|
|
@@ -2437,7 +2689,7 @@
|
|
|
2437
2689
|
const hasOperatorSyntax = (expr) => {
|
|
2438
2690
|
if (!expr || typeof expr !== "string") return false;
|
|
2439
2691
|
if (expr.includes("(")) return false;
|
|
2440
|
-
if (
|
|
2692
|
+
if (/^=(\+\+|--|!!)\/?/.test(expr)) {
|
|
2441
2693
|
return true;
|
|
2442
2694
|
}
|
|
2443
2695
|
if (/(\+\+|--)$/.test(expr)) {
|
|
@@ -2500,6 +2752,9 @@
|
|
|
2500
2752
|
tok = this.peek();
|
|
2501
2753
|
continue;
|
|
2502
2754
|
}
|
|
2755
|
+
if (!operators.postfix.has(tok.value) && !operators.infix.has(tok.value)) {
|
|
2756
|
+
break;
|
|
2757
|
+
}
|
|
2503
2758
|
this.consume();
|
|
2504
2759
|
const nextTok = this.peek();
|
|
2505
2760
|
if (nextTok.type === TokenType.PATH || nextTok.type === TokenType.LITERAL || nextTok.type === TokenType.LPAREN || nextTok.type === TokenType.PLACEHOLDER || nextTok.type === TokenType.EVENT || nextTok.type === TokenType.OPERATOR && operators.prefix.has(nextTok.value)) {
|
|
@@ -2537,6 +2792,10 @@
|
|
|
2537
2792
|
this.consume();
|
|
2538
2793
|
return { type: "Placeholder", value: tok.value };
|
|
2539
2794
|
}
|
|
2795
|
+
if (tok.type === TokenType.THIS) {
|
|
2796
|
+
this.consume();
|
|
2797
|
+
return { type: "This", value: tok.value };
|
|
2798
|
+
}
|
|
2540
2799
|
if (tok.type === TokenType.EVENT) {
|
|
2541
2800
|
this.consume();
|
|
2542
2801
|
return { type: "Event", value: tok.value };
|
|
@@ -2572,8 +2831,17 @@
|
|
|
2572
2831
|
return resolvePath(path, item);
|
|
2573
2832
|
});
|
|
2574
2833
|
}
|
|
2834
|
+
case "This": {
|
|
2835
|
+
return new LazyValue((context2) => {
|
|
2836
|
+
const node = (context2 == null ? void 0 : context2.__node__) || context2;
|
|
2837
|
+
if (ast.value === "$this") return node;
|
|
2838
|
+
const path = ast.value.startsWith("$this.") ? ast.value.slice(6) : ast.value.slice(6);
|
|
2839
|
+
return resolvePath(path, node);
|
|
2840
|
+
});
|
|
2841
|
+
}
|
|
2575
2842
|
case "Event": {
|
|
2576
|
-
return new LazyValue((
|
|
2843
|
+
return new LazyValue((context2) => {
|
|
2844
|
+
const event = (context2 == null ? void 0 : context2.$event) || (context2 == null ? void 0 : context2.event) || context2;
|
|
2577
2845
|
if (ast.value === "$event") return event;
|
|
2578
2846
|
const path = ast.value.startsWith("$event.") ? ast.value.slice(7) : ast.value.slice(7);
|
|
2579
2847
|
return resolvePath(path, event);
|
|
@@ -2621,7 +2889,12 @@
|
|
|
2621
2889
|
const opts = helperOptions.get(opInfo.helper) || {};
|
|
2622
2890
|
const left = evaluateAST(ast.left, context, opts.pathAware);
|
|
2623
2891
|
const right = evaluateAST(ast.right, context, false);
|
|
2624
|
-
|
|
2892
|
+
const finalArgs = [];
|
|
2893
|
+
if (Array.isArray(left) && ast.left.type === "Explosion") finalArgs.push(...left);
|
|
2894
|
+
else finalArgs.push(unwrapSignal(left));
|
|
2895
|
+
if (Array.isArray(right) && ast.right.type === "Explosion") finalArgs.push(...right);
|
|
2896
|
+
else finalArgs.push(unwrapSignal(right));
|
|
2897
|
+
return helper(...finalArgs);
|
|
2625
2898
|
}
|
|
2626
2899
|
default:
|
|
2627
2900
|
throw new Error(`JPRX: Unknown AST node type: ${ast.type}`);
|
|
@@ -2634,13 +2907,13 @@
|
|
|
2634
2907
|
return evaluateAST(ast, context);
|
|
2635
2908
|
};
|
|
2636
2909
|
const resolveExpression = (expr, context) => {
|
|
2637
|
-
var
|
|
2910
|
+
var _a2, _b2;
|
|
2638
2911
|
if (typeof expr !== "string") return expr;
|
|
2639
2912
|
if (hasOperatorSyntax(expr)) {
|
|
2640
2913
|
try {
|
|
2641
2914
|
return parseWithPratt(expr, context);
|
|
2642
2915
|
} catch (e) {
|
|
2643
|
-
(
|
|
2916
|
+
(_a2 = globalThis.console) == null ? void 0 : _a2.warn("JPRX: Pratt parser failed, falling back to legacy:", e.message);
|
|
2644
2917
|
}
|
|
2645
2918
|
}
|
|
2646
2919
|
const funcStart = expr.indexOf("(");
|
|
@@ -2648,19 +2921,19 @@
|
|
|
2648
2921
|
const fullPath = expr.slice(0, funcStart).trim();
|
|
2649
2922
|
const argsStr = expr.slice(funcStart + 1, -1);
|
|
2650
2923
|
const segments = fullPath.split("/");
|
|
2651
|
-
let funcName = segments.pop().replace(
|
|
2924
|
+
let funcName = segments.pop().replace(/^=/, "");
|
|
2652
2925
|
if (funcName === "" && (segments.length > 0 || fullPath === "/")) {
|
|
2653
2926
|
funcName = "/";
|
|
2654
2927
|
}
|
|
2655
2928
|
const navPath = segments.join("/");
|
|
2656
|
-
const isGlobalExpr = expr.startsWith("
|
|
2929
|
+
const isGlobalExpr = expr.startsWith("=/") || expr.startsWith("=");
|
|
2657
2930
|
let baseContext = context;
|
|
2658
|
-
if (navPath && navPath !== "
|
|
2931
|
+
if (navPath && navPath !== "=") {
|
|
2659
2932
|
baseContext = resolvePathAsContext(navPath, context);
|
|
2660
2933
|
}
|
|
2661
2934
|
const helper = helpers.get(funcName);
|
|
2662
2935
|
if (!helper) {
|
|
2663
|
-
(
|
|
2936
|
+
(_b2 = globalThis.console) == null ? void 0 : _b2.warn(`LightviewCDOM: Helper "${funcName}" not found.`);
|
|
2664
2937
|
return expr;
|
|
2665
2938
|
}
|
|
2666
2939
|
const options = helperOptions.get(funcName) || {};
|
|
@@ -2688,7 +2961,7 @@
|
|
|
2688
2961
|
let hasLazy = false;
|
|
2689
2962
|
for (let i = 0; i < argsList.length; i++) {
|
|
2690
2963
|
const arg = argsList[i];
|
|
2691
|
-
const useGlobalMode = isGlobalExpr && (navPath === "
|
|
2964
|
+
const useGlobalMode = isGlobalExpr && (navPath === "=" || !navPath);
|
|
2692
2965
|
const res = resolveArgument(arg, baseContext, useGlobalMode);
|
|
2693
2966
|
if (res.isLazy) hasLazy = true;
|
|
2694
2967
|
const shouldUnwrap = !(options.pathAware && i === 0);
|
|
@@ -2712,7 +2985,7 @@
|
|
|
2712
2985
|
return helper(...finalArgs);
|
|
2713
2986
|
});
|
|
2714
2987
|
}
|
|
2715
|
-
const result = helper(
|
|
2988
|
+
const result = helper.apply((context == null ? void 0 : context.__node__) || null, resolvedArgs);
|
|
2716
2989
|
return unwrapSignal(result);
|
|
2717
2990
|
}
|
|
2718
2991
|
return unwrapSignal(resolvePath(expr, context));
|
|
@@ -2834,7 +3107,7 @@
|
|
|
2834
3107
|
i++;
|
|
2835
3108
|
}
|
|
2836
3109
|
const word = input.slice(start, i);
|
|
2837
|
-
if (word.startsWith("
|
|
3110
|
+
if (word.startsWith("=")) {
|
|
2838
3111
|
return word;
|
|
2839
3112
|
}
|
|
2840
3113
|
if (word === "true") return true;
|
|
@@ -2920,7 +3193,7 @@
|
|
|
2920
3193
|
return res;
|
|
2921
3194
|
};
|
|
2922
3195
|
const parseJPRX = (input) => {
|
|
2923
|
-
var
|
|
3196
|
+
var _a2, _b2;
|
|
2924
3197
|
let result = "";
|
|
2925
3198
|
let i = 0;
|
|
2926
3199
|
const len2 = input.length;
|
|
@@ -2972,7 +3245,7 @@
|
|
|
2972
3245
|
i++;
|
|
2973
3246
|
continue;
|
|
2974
3247
|
}
|
|
2975
|
-
if (char === "
|
|
3248
|
+
if (char === "=") {
|
|
2976
3249
|
let expr = "";
|
|
2977
3250
|
let parenDepth = 0;
|
|
2978
3251
|
let braceDepth = 0;
|
|
@@ -3001,7 +3274,7 @@
|
|
|
3001
3274
|
result += JSON.stringify(expr);
|
|
3002
3275
|
continue;
|
|
3003
3276
|
}
|
|
3004
|
-
if (/[a-zA-Z_
|
|
3277
|
+
if (/[a-zA-Z_$/./]/.test(char)) {
|
|
3005
3278
|
let word = "";
|
|
3006
3279
|
while (i < len2 && /[a-zA-Z0-9_$/.-]/.test(input[i])) {
|
|
3007
3280
|
word += input[i];
|
|
@@ -3037,8 +3310,8 @@
|
|
|
3037
3310
|
try {
|
|
3038
3311
|
return JSON.parse(result);
|
|
3039
3312
|
} catch (e) {
|
|
3040
|
-
(
|
|
3041
|
-
(
|
|
3313
|
+
(_a2 = globalThis.console) == null ? void 0 : _a2.error("parseJPRX: JSON parse failed", e);
|
|
3314
|
+
(_b2 = globalThis.console) == null ? void 0 : _b2.error("Transformed input:", result);
|
|
3042
3315
|
throw e;
|
|
3043
3316
|
}
|
|
3044
3317
|
};
|
|
@@ -3391,6 +3664,21 @@
|
|
|
3391
3664
|
if (typeof current === "object" && current !== null) return set(target, {});
|
|
3392
3665
|
return set(target, null);
|
|
3393
3666
|
};
|
|
3667
|
+
function state(val, options) {
|
|
3668
|
+
if (globalThis.Lightview) {
|
|
3669
|
+
const finalOptions = typeof options === "string" ? { name: options } : options;
|
|
3670
|
+
return globalThis.Lightview.state(val, finalOptions);
|
|
3671
|
+
}
|
|
3672
|
+
throw new Error("JPRX: $state requires a UI library implementation.");
|
|
3673
|
+
}
|
|
3674
|
+
function signal(val, options) {
|
|
3675
|
+
if (globalThis.Lightview) {
|
|
3676
|
+
const finalOptions = typeof options === "string" ? { name: options } : options;
|
|
3677
|
+
return globalThis.Lightview.signal(val, finalOptions);
|
|
3678
|
+
}
|
|
3679
|
+
throw new Error("JPRX: $signal requires a UI library implementation.");
|
|
3680
|
+
}
|
|
3681
|
+
const bind = (path, options) => ({ __JPRX_BIND__: true, path, options });
|
|
3394
3682
|
const registerStateHelpers = (register) => {
|
|
3395
3683
|
const opts = { pathAware: true };
|
|
3396
3684
|
register("set", set, opts);
|
|
@@ -3404,6 +3692,9 @@
|
|
|
3404
3692
|
register("pop", pop, opts);
|
|
3405
3693
|
register("assign", assign, opts);
|
|
3406
3694
|
register("clear", clear, opts);
|
|
3695
|
+
register("state", state);
|
|
3696
|
+
register("signal", signal);
|
|
3697
|
+
register("bind", bind);
|
|
3407
3698
|
};
|
|
3408
3699
|
const fetchHelper = (url, options = {}) => {
|
|
3409
3700
|
const fetchOptions = { ...options };
|
|
@@ -3441,6 +3732,74 @@
|
|
|
3441
3732
|
registerStatsHelpers(registerHelper);
|
|
3442
3733
|
registerStateHelpers((name, fn) => registerHelper(name, fn, { pathAware: true }));
|
|
3443
3734
|
registerNetworkHelpers(registerHelper);
|
|
3735
|
+
registerHelper("move", (selector, location = "beforeend") => {
|
|
3736
|
+
return {
|
|
3737
|
+
isLazy: true,
|
|
3738
|
+
resolve: (eventOrNode) => {
|
|
3739
|
+
const isEvent = eventOrNode && typeof eventOrNode === "object" && "target" in eventOrNode;
|
|
3740
|
+
const node = isEvent ? eventOrNode.currentTarget || eventOrNode.target : eventOrNode;
|
|
3741
|
+
if (!(node instanceof Node) || !selector) return;
|
|
3742
|
+
const target = document.querySelector(selector);
|
|
3743
|
+
if (!target) {
|
|
3744
|
+
console.warn(`[Lightview-CDOM] move target not found: ${selector}`);
|
|
3745
|
+
return;
|
|
3746
|
+
}
|
|
3747
|
+
if (node.id) {
|
|
3748
|
+
const escapedId = CSS.escape(node.id);
|
|
3749
|
+
if (target.id === node.id && target !== node) {
|
|
3750
|
+
target.replaceWith(node);
|
|
3751
|
+
return;
|
|
3752
|
+
}
|
|
3753
|
+
const existing = target.querySelector(`#${escapedId}`);
|
|
3754
|
+
if (existing && existing !== node) {
|
|
3755
|
+
existing.replaceWith(node);
|
|
3756
|
+
return;
|
|
3757
|
+
}
|
|
3758
|
+
}
|
|
3759
|
+
globalThis.Lightview.$(target).content(node, location);
|
|
3760
|
+
}
|
|
3761
|
+
};
|
|
3762
|
+
}, { pathAware: true });
|
|
3763
|
+
registerHelper("mount", async (url, options = {}) => {
|
|
3764
|
+
const { target = "body", location = "beforeend" } = options;
|
|
3765
|
+
try {
|
|
3766
|
+
const fetchOptions = { ...options };
|
|
3767
|
+
delete fetchOptions.target;
|
|
3768
|
+
delete fetchOptions.location;
|
|
3769
|
+
const headers = { ...fetchOptions.headers };
|
|
3770
|
+
let body = fetchOptions.body;
|
|
3771
|
+
if (body !== void 0) {
|
|
3772
|
+
if (body !== null && typeof body === "object") {
|
|
3773
|
+
body = JSON.stringify(body);
|
|
3774
|
+
if (!headers["Content-Type"]) headers["Content-Type"] = "application/json";
|
|
3775
|
+
} else {
|
|
3776
|
+
body = String(body);
|
|
3777
|
+
if (!headers["Content-Type"]) headers["Content-Type"] = "text/plain";
|
|
3778
|
+
}
|
|
3779
|
+
fetchOptions.body = body;
|
|
3780
|
+
fetchOptions.headers = headers;
|
|
3781
|
+
}
|
|
3782
|
+
const response = await globalThis.fetch(url, fetchOptions);
|
|
3783
|
+
const contentType = response.headers.get("Content-Type") || "";
|
|
3784
|
+
const text = await response.text();
|
|
3785
|
+
let content = text;
|
|
3786
|
+
const isCDOM = contentType.includes("application/cdom") || contentType.includes("application/jprx") || contentType.includes("application/vdom") || contentType.includes("application/odom") || url.endsWith(".cdom") || url.endsWith(".jprx") || url.endsWith(".vdom") || url.endsWith(".odom");
|
|
3787
|
+
if (isCDOM || contentType.includes("application/json") && text.trim().startsWith("{")) {
|
|
3788
|
+
try {
|
|
3789
|
+
content = hydrate(parseJPRX(text));
|
|
3790
|
+
} catch (e) {
|
|
3791
|
+
}
|
|
3792
|
+
}
|
|
3793
|
+
const targetEl = document.querySelector(target);
|
|
3794
|
+
if (targetEl) {
|
|
3795
|
+
globalThis.Lightview.$(targetEl).content(content, location);
|
|
3796
|
+
} else {
|
|
3797
|
+
console.warn(`[Lightview-CDOM] $mount target not found: ${target}`);
|
|
3798
|
+
}
|
|
3799
|
+
} catch (err) {
|
|
3800
|
+
console.error(`[Lightview-CDOM] $mount failed for ${url}:`, err);
|
|
3801
|
+
}
|
|
3802
|
+
});
|
|
3444
3803
|
registerOperator("increment", "++", "prefix", 80);
|
|
3445
3804
|
registerOperator("increment", "++", "postfix", 80);
|
|
3446
3805
|
registerOperator("decrement", "--", "prefix", 80);
|
|
@@ -3455,309 +3814,135 @@
|
|
|
3455
3814
|
registerOperator("gte", ">=", "infix", 40);
|
|
3456
3815
|
registerOperator("lte", "<=", "infix", 40);
|
|
3457
3816
|
registerOperator("neq", "!=", "infix", 40);
|
|
3458
|
-
const localStates = /* @__PURE__ */ new WeakMap();
|
|
3459
3817
|
const getContext = (node, event = null) => {
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
const ShadowRoot2 = globalThis.ShadowRoot;
|
|
3463
|
-
while (cur) {
|
|
3464
|
-
const local = localStates.get(cur) || (cur && typeof cur === "object" ? cur.__state__ : null);
|
|
3465
|
-
if (local) chain.unshift(local);
|
|
3466
|
-
cur = cur.parentElement || (cur && typeof cur === "object" ? cur.__parent__ : null) || (ShadowRoot2 && cur.parentNode instanceof ShadowRoot2 ? cur.parentNode.host : null);
|
|
3467
|
-
}
|
|
3468
|
-
const globalRegistry = getRegistry$1();
|
|
3469
|
-
const handler = {
|
|
3470
|
-
get(target, prop, receiver) {
|
|
3471
|
-
var _a;
|
|
3818
|
+
return new Proxy({}, {
|
|
3819
|
+
get(_, prop) {
|
|
3472
3820
|
if (prop === "$event" || prop === "event") return event;
|
|
3473
|
-
if (prop === "
|
|
3474
|
-
|
|
3475
|
-
const s = chain[i];
|
|
3476
|
-
if (prop in s) return s[prop];
|
|
3477
|
-
}
|
|
3478
|
-
if (globalRegistry && globalRegistry.has(prop)) return unwrapSignal(globalRegistry.get(prop));
|
|
3479
|
-
const globalState = (_a = globalThis.Lightview) == null ? void 0 : _a.state;
|
|
3480
|
-
if (globalState && prop in globalState) return unwrapSignal(globalState[prop]);
|
|
3481
|
-
return void 0;
|
|
3821
|
+
if (prop === "$this" || prop === "this" || prop === "__node__") return node;
|
|
3822
|
+
return unwrapSignal(globalThis.Lightview.getState(prop, { scope: node }));
|
|
3482
3823
|
},
|
|
3483
|
-
set(
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
if (prop in s) {
|
|
3488
|
-
s[prop] = value;
|
|
3489
|
-
return true;
|
|
3490
|
-
}
|
|
3491
|
-
}
|
|
3492
|
-
if (chain.length > 0) {
|
|
3493
|
-
chain[chain.length - 1][prop] = value;
|
|
3494
|
-
return true;
|
|
3495
|
-
}
|
|
3496
|
-
const globalState = (_a = globalThis.Lightview) == null ? void 0 : _a.state;
|
|
3497
|
-
if (globalState && prop in globalState) {
|
|
3498
|
-
globalState[prop] = value;
|
|
3824
|
+
set(_, prop, value) {
|
|
3825
|
+
const res = globalThis.Lightview.getState(prop, { scope: node });
|
|
3826
|
+
if (res && (typeof res === "object" || typeof res === "function") && "value" in res) {
|
|
3827
|
+
res.value = value;
|
|
3499
3828
|
return true;
|
|
3500
3829
|
}
|
|
3501
|
-
if (globalRegistry && globalRegistry.has(prop)) {
|
|
3502
|
-
const s = globalRegistry.get(prop);
|
|
3503
|
-
if (s && (typeof s === "object" || typeof s === "function") && "value" in s) {
|
|
3504
|
-
s.value = value;
|
|
3505
|
-
return true;
|
|
3506
|
-
}
|
|
3507
|
-
}
|
|
3508
3830
|
return false;
|
|
3509
|
-
},
|
|
3510
|
-
has(target, prop) {
|
|
3511
|
-
var _a;
|
|
3512
|
-
const exists = prop === "$event" || prop === "event" || !!chain.find((s) => prop in s);
|
|
3513
|
-
const inGlobal = ((_a = globalThis.Lightview) == null ? void 0 : _a.state) && prop in globalThis.Lightview.state || globalRegistry && globalRegistry.has(prop);
|
|
3514
|
-
return exists || inGlobal;
|
|
3515
|
-
},
|
|
3516
|
-
ownKeys(target) {
|
|
3517
|
-
var _a;
|
|
3518
|
-
const keys = /* @__PURE__ */ new Set();
|
|
3519
|
-
if (event) {
|
|
3520
|
-
keys.add("$event");
|
|
3521
|
-
keys.add("event");
|
|
3522
|
-
}
|
|
3523
|
-
for (const s of chain) {
|
|
3524
|
-
for (const key in s) keys.add(key);
|
|
3525
|
-
}
|
|
3526
|
-
const globalState = (_a = globalThis.Lightview) == null ? void 0 : _a.state;
|
|
3527
|
-
if (globalState) {
|
|
3528
|
-
for (const key in globalState) keys.add(key);
|
|
3529
|
-
}
|
|
3530
|
-
return Array.from(keys);
|
|
3531
|
-
},
|
|
3532
|
-
getOwnPropertyDescriptor(target, prop) {
|
|
3533
|
-
return { enumerable: true, configurable: true };
|
|
3534
3831
|
}
|
|
3535
|
-
};
|
|
3536
|
-
return new Proxy({}, handler);
|
|
3537
|
-
};
|
|
3538
|
-
const handleCDOMState = (node) => {
|
|
3539
|
-
var _a;
|
|
3540
|
-
const attr = node["cdom-state"] || node.getAttribute && node.getAttribute("cdom-state");
|
|
3541
|
-
if (!attr || localStates.has(node)) return;
|
|
3542
|
-
try {
|
|
3543
|
-
const data = typeof attr === "object" ? attr : JSON.parse(attr);
|
|
3544
|
-
const s = state(data);
|
|
3545
|
-
localStates.set(node, s);
|
|
3546
|
-
if (node && typeof node === "object") {
|
|
3547
|
-
node.__state__ = s;
|
|
3548
|
-
}
|
|
3549
|
-
} catch (e) {
|
|
3550
|
-
(_a = globalThis.console) == null ? void 0 : _a.error("LightviewCDOM: Failed to parse cdom-state", e);
|
|
3551
|
-
}
|
|
3832
|
+
});
|
|
3552
3833
|
};
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3834
|
+
globalThis.Lightview.hooks.processAttribute = (domNode, key, value) => {
|
|
3835
|
+
if (value == null ? void 0 : value.__JPRX_BIND__) {
|
|
3836
|
+
const { path, options } = value;
|
|
3837
|
+
const type = domNode.type || "";
|
|
3838
|
+
const tagName = domNode.tagName.toLowerCase();
|
|
3839
|
+
let prop = "value";
|
|
3840
|
+
let event = "input";
|
|
3841
|
+
if (type === "checkbox" || type === "radio") {
|
|
3842
|
+
prop = "checked";
|
|
3843
|
+
event = "change";
|
|
3844
|
+
} else if (tagName === "select") {
|
|
3845
|
+
event = "change";
|
|
3846
|
+
}
|
|
3847
|
+
const res = globalThis.Lightview.get(path.replace(/^=/, ""), { scope: domNode });
|
|
3848
|
+
const runner = globalThis.Lightview.effect(() => {
|
|
3849
|
+
const val = unwrapSignal(res);
|
|
3850
|
+
if (domNode[prop] !== val) {
|
|
3851
|
+
domNode[prop] = val === void 0 ? "" : val;
|
|
3852
|
+
}
|
|
3853
|
+
});
|
|
3854
|
+
globalThis.Lightview.internals.trackEffect(domNode, runner);
|
|
3855
|
+
domNode.addEventListener(event, () => {
|
|
3856
|
+
if (res && "value" in res) res.value = domNode[prop];
|
|
3857
|
+
});
|
|
3858
|
+
return unwrapSignal(res) ?? domNode[prop];
|
|
3574
3859
|
}
|
|
3575
|
-
|
|
3576
|
-
const val = unwrapSignal(target);
|
|
3577
|
-
if (node[prop] !== val) {
|
|
3578
|
-
node[prop] = val === void 0 ? "" : val;
|
|
3579
|
-
}
|
|
3580
|
-
});
|
|
3581
|
-
node.addEventListener(event, () => {
|
|
3582
|
-
const val = node[prop];
|
|
3583
|
-
if (target && target.isBindingTarget) {
|
|
3584
|
-
target.value = val;
|
|
3585
|
-
} else {
|
|
3586
|
-
set(context, { [path]: val });
|
|
3587
|
-
}
|
|
3588
|
-
});
|
|
3860
|
+
return void 0;
|
|
3589
3861
|
};
|
|
3590
3862
|
const activate = (root = document.body) => {
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
child = child.nextSibling;
|
|
3600
|
-
}
|
|
3601
|
-
};
|
|
3602
|
-
walk(root);
|
|
3863
|
+
};
|
|
3864
|
+
const makeEventHandler = (expr) => (eventOrNode) => {
|
|
3865
|
+
const isEvent = eventOrNode && typeof eventOrNode === "object" && "target" in eventOrNode;
|
|
3866
|
+
const target = isEvent ? eventOrNode.currentTarget || eventOrNode.target : eventOrNode;
|
|
3867
|
+
const context = getContext(target, isEvent ? eventOrNode : null);
|
|
3868
|
+
const result = resolveExpression(expr, context);
|
|
3869
|
+
if (result && typeof result === "object" && result.isLazy) return result.resolve(eventOrNode);
|
|
3870
|
+
return result;
|
|
3603
3871
|
};
|
|
3604
3872
|
const hydrate = (node, parent = null) => {
|
|
3873
|
+
var _a2, _b2, _c;
|
|
3605
3874
|
if (!node) return node;
|
|
3606
|
-
if (typeof node === "string" && node.startsWith("
|
|
3875
|
+
if (typeof node === "string" && node.startsWith("'=")) {
|
|
3876
|
+
return node.slice(1);
|
|
3877
|
+
}
|
|
3878
|
+
if (typeof node === "string" && node.startsWith("=")) {
|
|
3607
3879
|
return parseExpression(node, parent);
|
|
3608
3880
|
}
|
|
3881
|
+
if (typeof node !== "object") return node;
|
|
3609
3882
|
if (Array.isArray(node)) {
|
|
3610
3883
|
return node.map((item) => hydrate(item, parent));
|
|
3611
3884
|
}
|
|
3612
|
-
if (node instanceof String)
|
|
3613
|
-
|
|
3885
|
+
if (node instanceof String) return node.toString();
|
|
3886
|
+
if (parent && !("__parent__" in node)) {
|
|
3887
|
+
Object.defineProperty(node, "__parent__", { value: parent, enumerable: false, writable: true });
|
|
3888
|
+
(_c = (_b2 = (_a2 = globalThis.Lightview) == null ? void 0 : _a2.internals) == null ? void 0 : _b2.parents) == null ? void 0 : _c.set(node, parent);
|
|
3614
3889
|
}
|
|
3615
|
-
if (
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
});
|
|
3890
|
+
if (!node.tag) {
|
|
3891
|
+
let potentialTag = null;
|
|
3892
|
+
const reserved = ["children", "attributes", "tag", "__parent__"];
|
|
3893
|
+
for (const key in node) {
|
|
3894
|
+
if (reserved.includes(key) || key.startsWith("on")) continue;
|
|
3895
|
+
potentialTag = key;
|
|
3896
|
+
break;
|
|
3623
3897
|
}
|
|
3624
|
-
if (
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
"
|
|
3633
|
-
|
|
3634
|
-
"value",
|
|
3635
|
-
"placeholder",
|
|
3636
|
-
"step",
|
|
3637
|
-
"min",
|
|
3638
|
-
"max",
|
|
3639
|
-
"pattern",
|
|
3640
|
-
"disabled",
|
|
3641
|
-
"checked",
|
|
3642
|
-
"selected",
|
|
3643
|
-
"readonly",
|
|
3644
|
-
"required",
|
|
3645
|
-
"multiple",
|
|
3646
|
-
"rows",
|
|
3647
|
-
"cols",
|
|
3648
|
-
"size",
|
|
3649
|
-
"maxlength",
|
|
3650
|
-
"minlength",
|
|
3651
|
-
"autocomplete",
|
|
3652
|
-
// Common element attributes
|
|
3653
|
-
"id",
|
|
3654
|
-
"class",
|
|
3655
|
-
"className",
|
|
3656
|
-
"style",
|
|
3657
|
-
"title",
|
|
3658
|
-
"tabindex",
|
|
3659
|
-
"role",
|
|
3660
|
-
"href",
|
|
3661
|
-
"src",
|
|
3662
|
-
"alt",
|
|
3663
|
-
"width",
|
|
3664
|
-
"height",
|
|
3665
|
-
"target",
|
|
3666
|
-
"rel",
|
|
3667
|
-
// Data attributes
|
|
3668
|
-
"data",
|
|
3669
|
-
"label",
|
|
3670
|
-
"text",
|
|
3671
|
-
"description",
|
|
3672
|
-
"content",
|
|
3673
|
-
// Common data property names
|
|
3674
|
-
"price",
|
|
3675
|
-
"qty",
|
|
3676
|
-
"items",
|
|
3677
|
-
"count",
|
|
3678
|
-
"total",
|
|
3679
|
-
"amount",
|
|
3680
|
-
"url"
|
|
3681
|
-
];
|
|
3682
|
-
if (attrNames.includes(key)) {
|
|
3683
|
-
continue;
|
|
3898
|
+
if (potentialTag) {
|
|
3899
|
+
const content = node[potentialTag];
|
|
3900
|
+
node.tag = potentialTag;
|
|
3901
|
+
if (Array.isArray(content)) {
|
|
3902
|
+
node.children = content;
|
|
3903
|
+
} else if (typeof content === "object") {
|
|
3904
|
+
node.attributes = node.attributes || {};
|
|
3905
|
+
for (const k in content) {
|
|
3906
|
+
if (k === "children") node.children = content[k];
|
|
3907
|
+
else node.attributes[k] = content[k];
|
|
3684
3908
|
}
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
node[k] = content[k];
|
|
3701
|
-
} else {
|
|
3702
|
-
node.attributes[k] = content[k];
|
|
3703
|
-
}
|
|
3704
|
-
}
|
|
3909
|
+
} else node.children = [content];
|
|
3910
|
+
delete node[potentialTag];
|
|
3911
|
+
}
|
|
3912
|
+
}
|
|
3913
|
+
for (const key in node) {
|
|
3914
|
+
if (key === "tag" || key === "__parent__") continue;
|
|
3915
|
+
const value = node[key];
|
|
3916
|
+
if (key === "attributes" && typeof value === "object" && value !== null) {
|
|
3917
|
+
for (const attrKey in value) {
|
|
3918
|
+
const attrVal = value[attrKey];
|
|
3919
|
+
if (typeof attrVal === "string" && attrVal.startsWith("'=")) {
|
|
3920
|
+
value[attrKey] = attrVal.slice(1);
|
|
3921
|
+
} else if (typeof attrVal === "string" && attrVal.startsWith("=")) {
|
|
3922
|
+
if (attrKey.startsWith("on")) {
|
|
3923
|
+
value[attrKey] = makeEventHandler(attrVal);
|
|
3705
3924
|
} else {
|
|
3706
|
-
|
|
3925
|
+
value[attrKey] = parseExpression(attrVal, node);
|
|
3707
3926
|
}
|
|
3708
|
-
|
|
3927
|
+
} else if (typeof attrVal === "object" && attrVal !== null) {
|
|
3928
|
+
value[attrKey] = hydrate(attrVal, node);
|
|
3709
3929
|
}
|
|
3710
3930
|
}
|
|
3931
|
+
continue;
|
|
3711
3932
|
}
|
|
3712
|
-
if (
|
|
3713
|
-
|
|
3714
|
-
}
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
if (key === "
|
|
3718
|
-
|
|
3719
|
-
}
|
|
3720
|
-
if (typeof value === "string" && value.startsWith("$")) {
|
|
3721
|
-
if (key.startsWith("on")) {
|
|
3722
|
-
node[key] = (event) => {
|
|
3723
|
-
const element2 = event.currentTarget;
|
|
3724
|
-
const context = getContext(element2, event);
|
|
3725
|
-
const result = resolveExpression(value, context);
|
|
3726
|
-
if (result && typeof result === "object" && result.isLazy && typeof result.resolve === "function") {
|
|
3727
|
-
return result.resolve(event);
|
|
3728
|
-
}
|
|
3729
|
-
return result;
|
|
3730
|
-
};
|
|
3731
|
-
} else if (key === "children") {
|
|
3732
|
-
node[key] = [parseExpression(value, node)];
|
|
3733
|
-
} else {
|
|
3734
|
-
node[key] = parseExpression(value, node);
|
|
3735
|
-
}
|
|
3736
|
-
} else if (key === "attributes" && typeof value === "object" && value !== null) {
|
|
3737
|
-
for (const attrKey in value) {
|
|
3738
|
-
const attrValue = value[attrKey];
|
|
3739
|
-
if (typeof attrValue === "string" && attrValue.startsWith("$")) {
|
|
3740
|
-
if (attrKey.startsWith("on")) {
|
|
3741
|
-
value[attrKey] = (event) => {
|
|
3742
|
-
const element2 = event.currentTarget;
|
|
3743
|
-
const context = getContext(element2, event);
|
|
3744
|
-
const result = resolveExpression(attrValue, context);
|
|
3745
|
-
if (result && typeof result === "object" && result.isLazy && typeof result.resolve === "function") {
|
|
3746
|
-
return result.resolve(event);
|
|
3747
|
-
}
|
|
3748
|
-
return result;
|
|
3749
|
-
};
|
|
3750
|
-
} else {
|
|
3751
|
-
value[attrKey] = parseExpression(attrValue, node);
|
|
3752
|
-
}
|
|
3753
|
-
}
|
|
3754
|
-
}
|
|
3755
|
-
node[key] = value;
|
|
3933
|
+
if (typeof value === "string" && value.startsWith("'=")) {
|
|
3934
|
+
node[key] = value.slice(1);
|
|
3935
|
+
} else if (typeof value === "string" && value.startsWith("=")) {
|
|
3936
|
+
if (key === "onmount" || key === "onunmount" || key.startsWith("on")) {
|
|
3937
|
+
node[key] = makeEventHandler(value);
|
|
3938
|
+
} else if (key === "children") {
|
|
3939
|
+
node[key] = [parseExpression(value, node)];
|
|
3756
3940
|
} else {
|
|
3757
|
-
node[key] =
|
|
3941
|
+
node[key] = parseExpression(value, node);
|
|
3758
3942
|
}
|
|
3943
|
+
} else {
|
|
3944
|
+
node[key] = hydrate(value, node);
|
|
3759
3945
|
}
|
|
3760
|
-
return node;
|
|
3761
3946
|
}
|
|
3762
3947
|
return node;
|
|
3763
3948
|
};
|
|
@@ -3772,8 +3957,10 @@
|
|
|
3772
3957
|
parseJPRX,
|
|
3773
3958
|
unwrapSignal,
|
|
3774
3959
|
getContext,
|
|
3775
|
-
handleCDOMState
|
|
3776
|
-
|
|
3960
|
+
handleCDOMState: () => {
|
|
3961
|
+
},
|
|
3962
|
+
handleCDOMBind: () => {
|
|
3963
|
+
},
|
|
3777
3964
|
activate,
|
|
3778
3965
|
hydrate,
|
|
3779
3966
|
version: "1.0.0"
|