lightview 2.2.2 → 2.3.5
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/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/calculator.html +427 -0
- package/docs/cdom-nav.html +2 -1
- package/docs/cdom.html +382 -113
- package/jprx/README.md +113 -72
- package/jprx/helpers/calc.js +82 -0
- package/jprx/helpers/lookup.js +39 -0
- package/jprx/helpers/math.js +4 -0
- package/jprx/helpers/state.js +21 -0
- package/jprx/index.js +3 -0
- package/jprx/package.json +2 -2
- package/jprx/parser.js +171 -89
- package/jprx/specs/expressions.json +71 -0
- package/jprx/specs/helpers.json +150 -0
- package/lightview-all.js +2375 -487
- package/lightview-cdom.js +1997 -590
- package/lightview-router.js +6 -0
- package/lightview-x.js +226 -54
- package/lightview.js +351 -42
- package/package.json +3 -1
- package/src/lightview-cdom.js +213 -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/start-dev.js +1 -1
- 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("
|
|
2147
|
-
const res = resolveExpression(node, context2);
|
|
2373
|
+
if (node.startsWith("=")) {
|
|
2374
|
+
const res = resolveExpression$1(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,11 +2423,11 @@
|
|
|
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
|
-
const val = resolveExpression(nestedExpr, context);
|
|
2430
|
+
const val = resolveExpression$1(nestedExpr, context);
|
|
2192
2431
|
if (val instanceof LazyValue) {
|
|
2193
2432
|
return { value: val, isLazy: true };
|
|
2194
2433
|
}
|
|
@@ -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}`);
|
|
@@ -2633,14 +2906,14 @@
|
|
|
2633
2906
|
const ast = parser.parseExpression(0);
|
|
2634
2907
|
return evaluateAST(ast, context);
|
|
2635
2908
|
};
|
|
2636
|
-
const resolveExpression = (expr, context) => {
|
|
2637
|
-
var
|
|
2909
|
+
const resolveExpression$1 = (expr, context) => {
|
|
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));
|
|
@@ -2720,7 +2993,7 @@
|
|
|
2720
2993
|
const parseExpression = (expr, context) => {
|
|
2721
2994
|
const LV = getLV();
|
|
2722
2995
|
if (!LV || typeof expr !== "string") return expr;
|
|
2723
|
-
return LV.computed(() => resolveExpression(expr, context));
|
|
2996
|
+
return LV.computed(() => resolveExpression$1(expr, context));
|
|
2724
2997
|
};
|
|
2725
2998
|
const parseCDOMC = (input) => {
|
|
2726
2999
|
let i = 0;
|
|
@@ -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];
|
|
@@ -3011,6 +3284,32 @@
|
|
|
3011
3284
|
while (j < len2 && /\s/.test(input[j])) j++;
|
|
3012
3285
|
if (input[j] === ":") {
|
|
3013
3286
|
result += `"${word}"`;
|
|
3287
|
+
} else if (input[j] === "(") {
|
|
3288
|
+
let expr = word;
|
|
3289
|
+
i = j;
|
|
3290
|
+
let parenDepth = 0;
|
|
3291
|
+
let inQuote = null;
|
|
3292
|
+
while (i < len2) {
|
|
3293
|
+
const c = input[i];
|
|
3294
|
+
if (inQuote) {
|
|
3295
|
+
if (c === inQuote && input[i - 1] !== "\\") inQuote = null;
|
|
3296
|
+
} else if (c === '"' || c === "'") {
|
|
3297
|
+
inQuote = c;
|
|
3298
|
+
} else {
|
|
3299
|
+
if (c === "(") parenDepth++;
|
|
3300
|
+
else if (c === ")") {
|
|
3301
|
+
parenDepth--;
|
|
3302
|
+
if (parenDepth === 0) {
|
|
3303
|
+
expr += c;
|
|
3304
|
+
i++;
|
|
3305
|
+
break;
|
|
3306
|
+
}
|
|
3307
|
+
}
|
|
3308
|
+
}
|
|
3309
|
+
expr += c;
|
|
3310
|
+
i++;
|
|
3311
|
+
}
|
|
3312
|
+
result += JSON.stringify("=" + expr);
|
|
3014
3313
|
} else {
|
|
3015
3314
|
if (word === "true" || word === "false" || word === "null") {
|
|
3016
3315
|
result += word;
|
|
@@ -3037,12 +3336,12 @@
|
|
|
3037
3336
|
try {
|
|
3038
3337
|
return JSON.parse(result);
|
|
3039
3338
|
} catch (e) {
|
|
3040
|
-
(
|
|
3041
|
-
(
|
|
3339
|
+
(_a2 = globalThis.console) == null ? void 0 : _a2.error("parseJPRX: JSON parse failed", e);
|
|
3340
|
+
(_b2 = globalThis.console) == null ? void 0 : _b2.error("Transformed input:", result);
|
|
3042
3341
|
throw e;
|
|
3043
3342
|
}
|
|
3044
3343
|
};
|
|
3045
|
-
const add = (...args) => args.reduce((a, b) => Number(a) + Number(b), 0);
|
|
3344
|
+
const add$1 = (...args) => args.reduce((a, b) => Number(a) + Number(b), 0);
|
|
3046
3345
|
const subtract = (a, b) => Number(a) - Number(b);
|
|
3047
3346
|
const multiply = (...args) => args.reduce((a, b) => Number(a) * Number(b), 1);
|
|
3048
3347
|
const divide = (a, b) => Number(a) / Number(b);
|
|
@@ -3050,12 +3349,14 @@
|
|
|
3050
3349
|
const ceil = (val) => Math.ceil(val);
|
|
3051
3350
|
const floor = (val) => Math.floor(val);
|
|
3052
3351
|
const abs = (val) => Math.abs(val);
|
|
3053
|
-
const mod = (a, b) => a % b;
|
|
3352
|
+
const mod$1 = (a, b) => a % b;
|
|
3054
3353
|
const pow = (a, b) => Math.pow(a, b);
|
|
3055
3354
|
const sqrt = (val) => Math.sqrt(val);
|
|
3355
|
+
const negate = (val) => -Number(val);
|
|
3356
|
+
const toPercent = (val) => Number(val) / 100;
|
|
3056
3357
|
const registerMathHelpers = (register) => {
|
|
3057
|
-
register("+", add);
|
|
3058
|
-
register("add", add);
|
|
3358
|
+
register("+", add$1);
|
|
3359
|
+
register("add", add$1);
|
|
3059
3360
|
register("-", subtract);
|
|
3060
3361
|
register("sub", subtract);
|
|
3061
3362
|
register("*", multiply);
|
|
@@ -3066,11 +3367,13 @@
|
|
|
3066
3367
|
register("ceil", ceil);
|
|
3067
3368
|
register("floor", floor);
|
|
3068
3369
|
register("abs", abs);
|
|
3069
|
-
register("mod", mod);
|
|
3370
|
+
register("mod", mod$1);
|
|
3070
3371
|
register("pow", pow);
|
|
3071
3372
|
register("sqrt", sqrt);
|
|
3373
|
+
register("negate", negate);
|
|
3374
|
+
register("toPercent", toPercent);
|
|
3072
3375
|
};
|
|
3073
|
-
const ifHelper = (
|
|
3376
|
+
const ifHelper = (condition2, thenVal, elseVal) => condition2 ? thenVal : elseVal;
|
|
3074
3377
|
const andHelper = (...args) => args.every(Boolean);
|
|
3075
3378
|
const orHelper = (...args) => args.some(Boolean);
|
|
3076
3379
|
const notHelper = (val) => !val;
|
|
@@ -3094,7 +3397,7 @@
|
|
|
3094
3397
|
const items = args.slice(0, -1);
|
|
3095
3398
|
return items.join(separator);
|
|
3096
3399
|
};
|
|
3097
|
-
const concat = (...args) => args.join("");
|
|
3400
|
+
const concat$1 = (...args) => args.join("");
|
|
3098
3401
|
const upper = (s) => String(s).toUpperCase();
|
|
3099
3402
|
const lower = (s) => String(s).toLowerCase();
|
|
3100
3403
|
const trim = (s) => String(s).trim();
|
|
@@ -3108,13 +3411,13 @@
|
|
|
3108
3411
|
const titleCase = (s) => {
|
|
3109
3412
|
return String(s).toLowerCase().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
3110
3413
|
};
|
|
3111
|
-
const contains$
|
|
3414
|
+
const contains$2 = (s, search) => String(s).includes(search);
|
|
3112
3415
|
const startsWith = (s, prefix) => String(s).startsWith(prefix);
|
|
3113
3416
|
const endsWith = (s, suffix) => String(s).endsWith(suffix);
|
|
3114
3417
|
const defaultHelper = (val, fallback) => val !== void 0 && val !== null ? val : fallback;
|
|
3115
3418
|
const registerStringHelpers = (register) => {
|
|
3116
3419
|
register("join", join$1);
|
|
3117
|
-
register("concat", concat);
|
|
3420
|
+
register("concat", concat$1);
|
|
3118
3421
|
register("upper", upper);
|
|
3119
3422
|
register("lower", lower);
|
|
3120
3423
|
register("trim", trim);
|
|
@@ -3123,7 +3426,7 @@
|
|
|
3123
3426
|
register("split", split);
|
|
3124
3427
|
register("capitalize", capitalize);
|
|
3125
3428
|
register("titleCase", titleCase);
|
|
3126
|
-
register("contains", contains$
|
|
3429
|
+
register("contains", contains$2);
|
|
3127
3430
|
register("startsWith", startsWith);
|
|
3128
3431
|
register("endsWith", endsWith);
|
|
3129
3432
|
register("default", defaultHelper);
|
|
@@ -3196,7 +3499,7 @@
|
|
|
3196
3499
|
const lte = (a, b) => a <= b;
|
|
3197
3500
|
const neq = (a, b) => a !== b;
|
|
3198
3501
|
const between = (val, min2, max2) => val >= min2 && val <= max2;
|
|
3199
|
-
const contains = (arr, val) => Array.isArray(arr) && arr.includes(val);
|
|
3502
|
+
const contains$1 = (arr, val) => Array.isArray(arr) && arr.includes(val);
|
|
3200
3503
|
const registerCompareHelpers = (register) => {
|
|
3201
3504
|
register("gt", gt);
|
|
3202
3505
|
register(">", gt);
|
|
@@ -3209,7 +3512,7 @@
|
|
|
3209
3512
|
register("neq", neq);
|
|
3210
3513
|
register("!=", neq);
|
|
3211
3514
|
register("between", between);
|
|
3212
|
-
register("in", contains);
|
|
3515
|
+
register("in", contains$1);
|
|
3213
3516
|
};
|
|
3214
3517
|
const sumIf = (arr, predicate) => {
|
|
3215
3518
|
if (!Array.isArray(arr)) return 0;
|
|
@@ -3300,16 +3603,35 @@
|
|
|
3300
3603
|
};
|
|
3301
3604
|
const index = (arr, idx) => Array.isArray(arr) ? arr[idx] : void 0;
|
|
3302
3605
|
const match = (val, arr) => Array.isArray(arr) ? arr.indexOf(val) : -1;
|
|
3606
|
+
const pathRef = (path, context) => {
|
|
3607
|
+
if (path && typeof path === "object" && "value" in path) {
|
|
3608
|
+
return unwrapSignal(path.value);
|
|
3609
|
+
}
|
|
3610
|
+
if (typeof path === "string") {
|
|
3611
|
+
const normalized = path.startsWith("=") ? path : "=" + path;
|
|
3612
|
+
const resolved = resolvePath(normalized, context);
|
|
3613
|
+
const value = unwrapSignal(resolved);
|
|
3614
|
+
if (typeof value === "number") return value;
|
|
3615
|
+
if (typeof value === "string" && value !== "" && !isNaN(parseFloat(value)) && isFinite(Number(value))) {
|
|
3616
|
+
return parseFloat(value);
|
|
3617
|
+
}
|
|
3618
|
+
return value;
|
|
3619
|
+
}
|
|
3620
|
+
return unwrapSignal(path);
|
|
3621
|
+
};
|
|
3303
3622
|
const registerLookupHelpers = (register) => {
|
|
3304
3623
|
register("lookup", lookup);
|
|
3305
3624
|
register("vlookup", vlookup);
|
|
3306
3625
|
register("index", index);
|
|
3307
3626
|
register("match", match);
|
|
3627
|
+
register("$", pathRef, { pathAware: true });
|
|
3628
|
+
register("val", pathRef, { pathAware: true });
|
|
3629
|
+
register("indirect", pathRef, { pathAware: true });
|
|
3308
3630
|
};
|
|
3309
3631
|
const sum = (...args) => args.reduce((a, b) => a + (Number(b) || 0), 0);
|
|
3310
3632
|
const avg = (...args) => args.length === 0 ? 0 : sum(...args) / args.length;
|
|
3311
|
-
const min = (...args) => Math.min(...args);
|
|
3312
|
-
const max = (...args) => Math.max(...args);
|
|
3633
|
+
const min$1 = (...args) => Math.min(...args);
|
|
3634
|
+
const max$1 = (...args) => Math.max(...args);
|
|
3313
3635
|
const median = (...args) => {
|
|
3314
3636
|
if (args.length === 0) return 0;
|
|
3315
3637
|
const sorted = [...args].sort((a, b) => a - b);
|
|
@@ -3331,8 +3653,8 @@
|
|
|
3331
3653
|
const registerStatsHelpers = (register) => {
|
|
3332
3654
|
register("sum", sum);
|
|
3333
3655
|
register("avg", avg);
|
|
3334
|
-
register("min", min);
|
|
3335
|
-
register("max", max);
|
|
3656
|
+
register("min", min$1);
|
|
3657
|
+
register("max", max$1);
|
|
3336
3658
|
register("median", median);
|
|
3337
3659
|
register("stdev", stdev);
|
|
3338
3660
|
register("var", variance);
|
|
@@ -3391,6 +3713,21 @@
|
|
|
3391
3713
|
if (typeof current === "object" && current !== null) return set(target, {});
|
|
3392
3714
|
return set(target, null);
|
|
3393
3715
|
};
|
|
3716
|
+
function state(val, options) {
|
|
3717
|
+
if (globalThis.Lightview) {
|
|
3718
|
+
const finalOptions = typeof options === "string" ? { name: options } : options;
|
|
3719
|
+
return globalThis.Lightview.state(val, finalOptions);
|
|
3720
|
+
}
|
|
3721
|
+
throw new Error("JPRX: $state requires a UI library implementation.");
|
|
3722
|
+
}
|
|
3723
|
+
function signal(val, options) {
|
|
3724
|
+
if (globalThis.Lightview) {
|
|
3725
|
+
const finalOptions = typeof options === "string" ? { name: options } : options;
|
|
3726
|
+
return globalThis.Lightview.signal(val, finalOptions);
|
|
3727
|
+
}
|
|
3728
|
+
throw new Error("JPRX: $signal requires a UI library implementation.");
|
|
3729
|
+
}
|
|
3730
|
+
const bind = (path, options) => ({ __JPRX_BIND__: true, path, options });
|
|
3394
3731
|
const registerStateHelpers = (register) => {
|
|
3395
3732
|
const opts = { pathAware: true };
|
|
3396
3733
|
register("set", set, opts);
|
|
@@ -3404,6 +3741,9 @@
|
|
|
3404
3741
|
register("pop", pop, opts);
|
|
3405
3742
|
register("assign", assign, opts);
|
|
3406
3743
|
register("clear", clear, opts);
|
|
3744
|
+
register("state", state);
|
|
3745
|
+
register("signal", signal);
|
|
3746
|
+
register("bind", bind);
|
|
3407
3747
|
};
|
|
3408
3748
|
const fetchHelper = (url, options = {}) => {
|
|
3409
3749
|
const fetchOptions = { ...options };
|
|
@@ -3429,351 +3769,1899 @@
|
|
|
3429
3769
|
const registerNetworkHelpers = (register) => {
|
|
3430
3770
|
register("fetch", fetchHelper);
|
|
3431
3771
|
};
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3772
|
+
var INUMBER = "INUMBER";
|
|
3773
|
+
var IOP1 = "IOP1";
|
|
3774
|
+
var IOP2 = "IOP2";
|
|
3775
|
+
var IOP3 = "IOP3";
|
|
3776
|
+
var IVAR = "IVAR";
|
|
3777
|
+
var IVARNAME = "IVARNAME";
|
|
3778
|
+
var IFUNCALL = "IFUNCALL";
|
|
3779
|
+
var IFUNDEF = "IFUNDEF";
|
|
3780
|
+
var IEXPR = "IEXPR";
|
|
3781
|
+
var IEXPREVAL = "IEXPREVAL";
|
|
3782
|
+
var IMEMBER = "IMEMBER";
|
|
3783
|
+
var IENDSTATEMENT = "IENDSTATEMENT";
|
|
3784
|
+
var IARRAY = "IARRAY";
|
|
3785
|
+
function Instruction(type, value) {
|
|
3786
|
+
this.type = type;
|
|
3787
|
+
this.value = value !== void 0 && value !== null ? value : 0;
|
|
3788
|
+
}
|
|
3789
|
+
Instruction.prototype.toString = function() {
|
|
3790
|
+
switch (this.type) {
|
|
3791
|
+
case INUMBER:
|
|
3792
|
+
case IOP1:
|
|
3793
|
+
case IOP2:
|
|
3794
|
+
case IOP3:
|
|
3795
|
+
case IVAR:
|
|
3796
|
+
case IVARNAME:
|
|
3797
|
+
case IENDSTATEMENT:
|
|
3798
|
+
return this.value;
|
|
3799
|
+
case IFUNCALL:
|
|
3800
|
+
return "CALL " + this.value;
|
|
3801
|
+
case IFUNDEF:
|
|
3802
|
+
return "DEF " + this.value;
|
|
3803
|
+
case IARRAY:
|
|
3804
|
+
return "ARRAY " + this.value;
|
|
3805
|
+
case IMEMBER:
|
|
3806
|
+
return "." + this.value;
|
|
3807
|
+
default:
|
|
3808
|
+
return "Invalid Instruction";
|
|
3809
|
+
}
|
|
3810
|
+
};
|
|
3811
|
+
function unaryInstruction(value) {
|
|
3812
|
+
return new Instruction(IOP1, value);
|
|
3813
|
+
}
|
|
3814
|
+
function binaryInstruction(value) {
|
|
3815
|
+
return new Instruction(IOP2, value);
|
|
3816
|
+
}
|
|
3817
|
+
function ternaryInstruction(value) {
|
|
3818
|
+
return new Instruction(IOP3, value);
|
|
3819
|
+
}
|
|
3820
|
+
function simplify(tokens, unaryOps, binaryOps, ternaryOps, values) {
|
|
3821
|
+
var nstack = [];
|
|
3822
|
+
var newexpression = [];
|
|
3823
|
+
var n1, n2, n3;
|
|
3824
|
+
var f;
|
|
3825
|
+
for (var i = 0; i < tokens.length; i++) {
|
|
3826
|
+
var item = tokens[i];
|
|
3827
|
+
var type = item.type;
|
|
3828
|
+
if (type === INUMBER || type === IVARNAME) {
|
|
3829
|
+
if (Array.isArray(item.value)) {
|
|
3830
|
+
nstack.push.apply(nstack, simplify(item.value.map(function(x) {
|
|
3831
|
+
return new Instruction(INUMBER, x);
|
|
3832
|
+
}).concat(new Instruction(IARRAY, item.value.length)), unaryOps, binaryOps, ternaryOps, values));
|
|
3833
|
+
} else {
|
|
3834
|
+
nstack.push(item);
|
|
3835
|
+
}
|
|
3836
|
+
} else if (type === IVAR && values.hasOwnProperty(item.value)) {
|
|
3837
|
+
item = new Instruction(INUMBER, values[item.value]);
|
|
3838
|
+
nstack.push(item);
|
|
3839
|
+
} else if (type === IOP2 && nstack.length > 1) {
|
|
3840
|
+
n2 = nstack.pop();
|
|
3841
|
+
n1 = nstack.pop();
|
|
3842
|
+
f = binaryOps[item.value];
|
|
3843
|
+
item = new Instruction(INUMBER, f(n1.value, n2.value));
|
|
3844
|
+
nstack.push(item);
|
|
3845
|
+
} else if (type === IOP3 && nstack.length > 2) {
|
|
3846
|
+
n3 = nstack.pop();
|
|
3847
|
+
n2 = nstack.pop();
|
|
3848
|
+
n1 = nstack.pop();
|
|
3849
|
+
if (item.value === "?") {
|
|
3850
|
+
nstack.push(n1.value ? n2.value : n3.value);
|
|
3851
|
+
} else {
|
|
3852
|
+
f = ternaryOps[item.value];
|
|
3853
|
+
item = new Instruction(INUMBER, f(n1.value, n2.value, n3.value));
|
|
3854
|
+
nstack.push(item);
|
|
3855
|
+
}
|
|
3856
|
+
} else if (type === IOP1 && nstack.length > 0) {
|
|
3857
|
+
n1 = nstack.pop();
|
|
3858
|
+
f = unaryOps[item.value];
|
|
3859
|
+
item = new Instruction(INUMBER, f(n1.value));
|
|
3860
|
+
nstack.push(item);
|
|
3861
|
+
} else if (type === IEXPR) {
|
|
3862
|
+
while (nstack.length > 0) {
|
|
3863
|
+
newexpression.push(nstack.shift());
|
|
3864
|
+
}
|
|
3865
|
+
newexpression.push(new Instruction(IEXPR, simplify(item.value, unaryOps, binaryOps, ternaryOps, values)));
|
|
3866
|
+
} else if (type === IMEMBER && nstack.length > 0) {
|
|
3867
|
+
n1 = nstack.pop();
|
|
3868
|
+
nstack.push(new Instruction(INUMBER, n1.value[item.value]));
|
|
3869
|
+
} else {
|
|
3870
|
+
while (nstack.length > 0) {
|
|
3871
|
+
newexpression.push(nstack.shift());
|
|
3872
|
+
}
|
|
3873
|
+
newexpression.push(item);
|
|
3874
|
+
}
|
|
3875
|
+
}
|
|
3876
|
+
while (nstack.length > 0) {
|
|
3877
|
+
newexpression.push(nstack.shift());
|
|
3878
|
+
}
|
|
3879
|
+
return newexpression;
|
|
3880
|
+
}
|
|
3881
|
+
function substitute(tokens, variable, expr) {
|
|
3882
|
+
var newexpression = [];
|
|
3883
|
+
for (var i = 0; i < tokens.length; i++) {
|
|
3884
|
+
var item = tokens[i];
|
|
3885
|
+
var type = item.type;
|
|
3886
|
+
if (type === IVAR && item.value === variable) {
|
|
3887
|
+
for (var j = 0; j < expr.tokens.length; j++) {
|
|
3888
|
+
var expritem = expr.tokens[j];
|
|
3889
|
+
var replitem;
|
|
3890
|
+
if (expritem.type === IOP1) {
|
|
3891
|
+
replitem = unaryInstruction(expritem.value);
|
|
3892
|
+
} else if (expritem.type === IOP2) {
|
|
3893
|
+
replitem = binaryInstruction(expritem.value);
|
|
3894
|
+
} else if (expritem.type === IOP3) {
|
|
3895
|
+
replitem = ternaryInstruction(expritem.value);
|
|
3896
|
+
} else {
|
|
3897
|
+
replitem = new Instruction(expritem.type, expritem.value);
|
|
3490
3898
|
}
|
|
3899
|
+
newexpression.push(replitem);
|
|
3491
3900
|
}
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3901
|
+
} else if (type === IEXPR) {
|
|
3902
|
+
newexpression.push(new Instruction(IEXPR, substitute(item.value, variable, expr)));
|
|
3903
|
+
} else {
|
|
3904
|
+
newexpression.push(item);
|
|
3905
|
+
}
|
|
3906
|
+
}
|
|
3907
|
+
return newexpression;
|
|
3908
|
+
}
|
|
3909
|
+
function evaluate(tokens, expr, values) {
|
|
3910
|
+
var nstack = [];
|
|
3911
|
+
var n1, n2, n3;
|
|
3912
|
+
var f, args, argCount;
|
|
3913
|
+
if (isExpressionEvaluator(tokens)) {
|
|
3914
|
+
return resolveExpression(tokens, values);
|
|
3915
|
+
}
|
|
3916
|
+
var numTokens = tokens.length;
|
|
3917
|
+
for (var i = 0; i < numTokens; i++) {
|
|
3918
|
+
var item = tokens[i];
|
|
3919
|
+
var type = item.type;
|
|
3920
|
+
if (type === INUMBER || type === IVARNAME) {
|
|
3921
|
+
nstack.push(item.value);
|
|
3922
|
+
} else if (type === IOP2) {
|
|
3923
|
+
n2 = nstack.pop();
|
|
3924
|
+
n1 = nstack.pop();
|
|
3925
|
+
if (item.value === "and") {
|
|
3926
|
+
nstack.push(n1 ? !!evaluate(n2, expr, values) : false);
|
|
3927
|
+
} else if (item.value === "or") {
|
|
3928
|
+
nstack.push(n1 ? true : !!evaluate(n2, expr, values));
|
|
3929
|
+
} else if (item.value === "=") {
|
|
3930
|
+
f = expr.binaryOps[item.value];
|
|
3931
|
+
nstack.push(f(n1, evaluate(n2, expr, values), values));
|
|
3932
|
+
} else {
|
|
3933
|
+
f = expr.binaryOps[item.value];
|
|
3934
|
+
nstack.push(f(resolveExpression(n1, values), resolveExpression(n2, values)));
|
|
3495
3935
|
}
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3936
|
+
} else if (type === IOP3) {
|
|
3937
|
+
n3 = nstack.pop();
|
|
3938
|
+
n2 = nstack.pop();
|
|
3939
|
+
n1 = nstack.pop();
|
|
3940
|
+
if (item.value === "?") {
|
|
3941
|
+
nstack.push(evaluate(n1 ? n2 : n3, expr, values));
|
|
3942
|
+
} else {
|
|
3943
|
+
f = expr.ternaryOps[item.value];
|
|
3944
|
+
nstack.push(f(resolveExpression(n1, values), resolveExpression(n2, values), resolveExpression(n3, values)));
|
|
3500
3945
|
}
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3946
|
+
} else if (type === IVAR) {
|
|
3947
|
+
if (item.value in expr.functions) {
|
|
3948
|
+
nstack.push(expr.functions[item.value]);
|
|
3949
|
+
} else if (item.value in expr.unaryOps && expr.parser.isOperatorEnabled(item.value)) {
|
|
3950
|
+
nstack.push(expr.unaryOps[item.value]);
|
|
3951
|
+
} else {
|
|
3952
|
+
var v = values[item.value];
|
|
3953
|
+
if (v !== void 0) {
|
|
3954
|
+
nstack.push(v);
|
|
3955
|
+
} else {
|
|
3956
|
+
throw new Error("undefined variable: " + item.value);
|
|
3506
3957
|
}
|
|
3507
3958
|
}
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
var _a;
|
|
3518
|
-
const keys = /* @__PURE__ */ new Set();
|
|
3519
|
-
if (event) {
|
|
3520
|
-
keys.add("$event");
|
|
3521
|
-
keys.add("event");
|
|
3959
|
+
} else if (type === IOP1) {
|
|
3960
|
+
n1 = nstack.pop();
|
|
3961
|
+
f = expr.unaryOps[item.value];
|
|
3962
|
+
nstack.push(f(resolveExpression(n1, values)));
|
|
3963
|
+
} else if (type === IFUNCALL) {
|
|
3964
|
+
argCount = item.value;
|
|
3965
|
+
args = [];
|
|
3966
|
+
while (argCount-- > 0) {
|
|
3967
|
+
args.unshift(resolveExpression(nstack.pop(), values));
|
|
3522
3968
|
}
|
|
3523
|
-
|
|
3524
|
-
|
|
3969
|
+
f = nstack.pop();
|
|
3970
|
+
if (f.apply && f.call) {
|
|
3971
|
+
nstack.push(f.apply(void 0, args));
|
|
3972
|
+
} else {
|
|
3973
|
+
throw new Error(f + " is not a function");
|
|
3525
3974
|
}
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3975
|
+
} else if (type === IFUNDEF) {
|
|
3976
|
+
nstack.push(function() {
|
|
3977
|
+
var n22 = nstack.pop();
|
|
3978
|
+
var args2 = [];
|
|
3979
|
+
var argCount2 = item.value;
|
|
3980
|
+
while (argCount2-- > 0) {
|
|
3981
|
+
args2.unshift(nstack.pop());
|
|
3982
|
+
}
|
|
3983
|
+
var n12 = nstack.pop();
|
|
3984
|
+
var f2 = function() {
|
|
3985
|
+
var scope = Object.assign({}, values);
|
|
3986
|
+
for (var i2 = 0, len2 = args2.length; i2 < len2; i2++) {
|
|
3987
|
+
scope[args2[i2]] = arguments[i2];
|
|
3988
|
+
}
|
|
3989
|
+
return evaluate(n22, expr, scope);
|
|
3990
|
+
};
|
|
3991
|
+
Object.defineProperty(f2, "name", {
|
|
3992
|
+
value: n12,
|
|
3993
|
+
writable: false
|
|
3994
|
+
});
|
|
3995
|
+
values[n12] = f2;
|
|
3996
|
+
return f2;
|
|
3997
|
+
}());
|
|
3998
|
+
} else if (type === IEXPR) {
|
|
3999
|
+
nstack.push(createExpressionEvaluator(item, expr));
|
|
4000
|
+
} else if (type === IEXPREVAL) {
|
|
4001
|
+
nstack.push(item);
|
|
4002
|
+
} else if (type === IMEMBER) {
|
|
4003
|
+
n1 = nstack.pop();
|
|
4004
|
+
nstack.push(n1[item.value]);
|
|
4005
|
+
} else if (type === IENDSTATEMENT) {
|
|
4006
|
+
nstack.pop();
|
|
4007
|
+
} else if (type === IARRAY) {
|
|
4008
|
+
argCount = item.value;
|
|
4009
|
+
args = [];
|
|
4010
|
+
while (argCount-- > 0) {
|
|
4011
|
+
args.unshift(nstack.pop());
|
|
3529
4012
|
}
|
|
3530
|
-
|
|
3531
|
-
},
|
|
3532
|
-
getOwnPropertyDescriptor(target, prop) {
|
|
3533
|
-
return { enumerable: true, configurable: true };
|
|
3534
|
-
}
|
|
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
|
-
}
|
|
3552
|
-
};
|
|
3553
|
-
const handleCDOMBind = (node) => {
|
|
3554
|
-
const path = node["cdom-bind"] || node.getAttribute("cdom-bind");
|
|
3555
|
-
if (!path) return;
|
|
3556
|
-
const type = node.type || "";
|
|
3557
|
-
const tagName = node.tagName.toLowerCase();
|
|
3558
|
-
let prop = "value";
|
|
3559
|
-
let event = "input";
|
|
3560
|
-
if (type === "checkbox" || type === "radio") {
|
|
3561
|
-
prop = "checked";
|
|
3562
|
-
event = "change";
|
|
3563
|
-
} else if (tagName === "select") {
|
|
3564
|
-
event = "change";
|
|
3565
|
-
}
|
|
3566
|
-
const context = getContext(node);
|
|
3567
|
-
let target = resolvePathAsContext(path, context);
|
|
3568
|
-
if (target && target.isBindingTarget && target.value === void 0) {
|
|
3569
|
-
const val = node[prop];
|
|
3570
|
-
if (val !== void 0 && val !== "") {
|
|
3571
|
-
set(context, { [target.key]: val });
|
|
3572
|
-
target = resolvePathAsContext(path, context);
|
|
3573
|
-
}
|
|
3574
|
-
}
|
|
3575
|
-
effect(() => {
|
|
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;
|
|
4013
|
+
nstack.push(args);
|
|
3585
4014
|
} else {
|
|
3586
|
-
|
|
3587
|
-
}
|
|
3588
|
-
});
|
|
3589
|
-
};
|
|
3590
|
-
const activate = (root = document.body) => {
|
|
3591
|
-
const walk = (node) => {
|
|
3592
|
-
if (node.nodeType === 1) {
|
|
3593
|
-
if (node.hasAttribute("cdom-state")) handleCDOMState(node);
|
|
3594
|
-
if (node.hasAttribute("cdom-bind")) handleCDOMBind(node);
|
|
4015
|
+
throw new Error("invalid Expression");
|
|
3595
4016
|
}
|
|
3596
|
-
let child = node.firstChild;
|
|
3597
|
-
while (child) {
|
|
3598
|
-
walk(child);
|
|
3599
|
-
child = child.nextSibling;
|
|
3600
|
-
}
|
|
3601
|
-
};
|
|
3602
|
-
walk(root);
|
|
3603
|
-
};
|
|
3604
|
-
const hydrate = (node, parent = null) => {
|
|
3605
|
-
if (!node) return node;
|
|
3606
|
-
if (typeof node === "string" && node.startsWith("$")) {
|
|
3607
|
-
return parseExpression(node, parent);
|
|
3608
4017
|
}
|
|
3609
|
-
if (
|
|
3610
|
-
|
|
4018
|
+
if (nstack.length > 1) {
|
|
4019
|
+
throw new Error("invalid Expression (parity)");
|
|
3611
4020
|
}
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
if (
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
writable: true,
|
|
3621
|
-
configurable: true
|
|
3622
|
-
});
|
|
4021
|
+
return nstack[0] === 0 ? 0 : resolveExpression(nstack[0], values);
|
|
4022
|
+
}
|
|
4023
|
+
function createExpressionEvaluator(token, expr, values) {
|
|
4024
|
+
if (isExpressionEvaluator(token)) return token;
|
|
4025
|
+
return {
|
|
4026
|
+
type: IEXPREVAL,
|
|
4027
|
+
value: function(scope) {
|
|
4028
|
+
return evaluate(token.value, expr, scope);
|
|
3623
4029
|
}
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
4030
|
+
};
|
|
4031
|
+
}
|
|
4032
|
+
function isExpressionEvaluator(n) {
|
|
4033
|
+
return n && n.type === IEXPREVAL;
|
|
4034
|
+
}
|
|
4035
|
+
function resolveExpression(n, values) {
|
|
4036
|
+
return isExpressionEvaluator(n) ? n.value(values) : n;
|
|
4037
|
+
}
|
|
4038
|
+
function expressionToString(tokens, toJS) {
|
|
4039
|
+
var nstack = [];
|
|
4040
|
+
var n1, n2, n3;
|
|
4041
|
+
var f, args, argCount;
|
|
4042
|
+
for (var i = 0; i < tokens.length; i++) {
|
|
4043
|
+
var item = tokens[i];
|
|
4044
|
+
var type = item.type;
|
|
4045
|
+
if (type === INUMBER) {
|
|
4046
|
+
if (typeof item.value === "number" && item.value < 0) {
|
|
4047
|
+
nstack.push("(" + item.value + ")");
|
|
4048
|
+
} else if (Array.isArray(item.value)) {
|
|
4049
|
+
nstack.push("[" + item.value.map(escapeValue).join(", ") + "]");
|
|
4050
|
+
} else {
|
|
4051
|
+
nstack.push(escapeValue(item.value));
|
|
4052
|
+
}
|
|
4053
|
+
} else if (type === IOP2) {
|
|
4054
|
+
n2 = nstack.pop();
|
|
4055
|
+
n1 = nstack.pop();
|
|
4056
|
+
f = item.value;
|
|
4057
|
+
if (toJS) {
|
|
4058
|
+
if (f === "^") {
|
|
4059
|
+
nstack.push("Math.pow(" + n1 + ", " + n2 + ")");
|
|
4060
|
+
} else if (f === "and") {
|
|
4061
|
+
nstack.push("(!!" + n1 + " && !!" + n2 + ")");
|
|
4062
|
+
} else if (f === "or") {
|
|
4063
|
+
nstack.push("(!!" + n1 + " || !!" + n2 + ")");
|
|
4064
|
+
} else if (f === "||") {
|
|
4065
|
+
nstack.push("(function(a,b){ return Array.isArray(a) && Array.isArray(b) ? a.concat(b) : String(a) + String(b); }((" + n1 + "),(" + n2 + ")))");
|
|
4066
|
+
} else if (f === "==") {
|
|
4067
|
+
nstack.push("(" + n1 + " === " + n2 + ")");
|
|
4068
|
+
} else if (f === "!=") {
|
|
4069
|
+
nstack.push("(" + n1 + " !== " + n2 + ")");
|
|
4070
|
+
} else if (f === "[") {
|
|
4071
|
+
nstack.push(n1 + "[(" + n2 + ") | 0]");
|
|
4072
|
+
} else {
|
|
4073
|
+
nstack.push("(" + n1 + " " + f + " " + n2 + ")");
|
|
3629
4074
|
}
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
"
|
|
3633
|
-
|
|
3634
|
-
"
|
|
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;
|
|
4075
|
+
} else {
|
|
4076
|
+
if (f === "[") {
|
|
4077
|
+
nstack.push(n1 + "[" + n2 + "]");
|
|
4078
|
+
} else {
|
|
4079
|
+
nstack.push("(" + n1 + " " + f + " " + n2 + ")");
|
|
3684
4080
|
}
|
|
3685
|
-
potentialTag = key;
|
|
3686
|
-
break;
|
|
3687
4081
|
}
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
4082
|
+
} else if (type === IOP3) {
|
|
4083
|
+
n3 = nstack.pop();
|
|
4084
|
+
n2 = nstack.pop();
|
|
4085
|
+
n1 = nstack.pop();
|
|
4086
|
+
f = item.value;
|
|
4087
|
+
if (f === "?") {
|
|
4088
|
+
nstack.push("(" + n1 + " ? " + n2 + " : " + n3 + ")");
|
|
4089
|
+
} else {
|
|
4090
|
+
throw new Error("invalid Expression");
|
|
4091
|
+
}
|
|
4092
|
+
} else if (type === IVAR || type === IVARNAME) {
|
|
4093
|
+
nstack.push(item.value);
|
|
4094
|
+
} else if (type === IOP1) {
|
|
4095
|
+
n1 = nstack.pop();
|
|
4096
|
+
f = item.value;
|
|
4097
|
+
if (f === "-" || f === "+") {
|
|
4098
|
+
nstack.push("(" + f + n1 + ")");
|
|
4099
|
+
} else if (toJS) {
|
|
4100
|
+
if (f === "not") {
|
|
4101
|
+
nstack.push("(!" + n1 + ")");
|
|
4102
|
+
} else if (f === "!") {
|
|
4103
|
+
nstack.push("fac(" + n1 + ")");
|
|
4104
|
+
} else {
|
|
4105
|
+
nstack.push(f + "(" + n1 + ")");
|
|
3709
4106
|
}
|
|
4107
|
+
} else if (f === "!") {
|
|
4108
|
+
nstack.push("(" + n1 + "!)");
|
|
4109
|
+
} else {
|
|
4110
|
+
nstack.push("(" + f + " " + n1 + ")");
|
|
4111
|
+
}
|
|
4112
|
+
} else if (type === IFUNCALL) {
|
|
4113
|
+
argCount = item.value;
|
|
4114
|
+
args = [];
|
|
4115
|
+
while (argCount-- > 0) {
|
|
4116
|
+
args.unshift(nstack.pop());
|
|
4117
|
+
}
|
|
4118
|
+
f = nstack.pop();
|
|
4119
|
+
nstack.push(f + "(" + args.join(", ") + ")");
|
|
4120
|
+
} else if (type === IFUNDEF) {
|
|
4121
|
+
n2 = nstack.pop();
|
|
4122
|
+
argCount = item.value;
|
|
4123
|
+
args = [];
|
|
4124
|
+
while (argCount-- > 0) {
|
|
4125
|
+
args.unshift(nstack.pop());
|
|
4126
|
+
}
|
|
4127
|
+
n1 = nstack.pop();
|
|
4128
|
+
if (toJS) {
|
|
4129
|
+
nstack.push("(" + n1 + " = function(" + args.join(", ") + ") { return " + n2 + " })");
|
|
4130
|
+
} else {
|
|
4131
|
+
nstack.push("(" + n1 + "(" + args.join(", ") + ") = " + n2 + ")");
|
|
4132
|
+
}
|
|
4133
|
+
} else if (type === IMEMBER) {
|
|
4134
|
+
n1 = nstack.pop();
|
|
4135
|
+
nstack.push(n1 + "." + item.value);
|
|
4136
|
+
} else if (type === IARRAY) {
|
|
4137
|
+
argCount = item.value;
|
|
4138
|
+
args = [];
|
|
4139
|
+
while (argCount-- > 0) {
|
|
4140
|
+
args.unshift(nstack.pop());
|
|
3710
4141
|
}
|
|
4142
|
+
nstack.push("[" + args.join(", ") + "]");
|
|
4143
|
+
} else if (type === IEXPR) {
|
|
4144
|
+
nstack.push("(" + expressionToString(item.value, toJS) + ")");
|
|
4145
|
+
} else if (type === IENDSTATEMENT) ;
|
|
4146
|
+
else {
|
|
4147
|
+
throw new Error("invalid Expression");
|
|
3711
4148
|
}
|
|
3712
|
-
|
|
3713
|
-
|
|
4149
|
+
}
|
|
4150
|
+
if (nstack.length > 1) {
|
|
4151
|
+
if (toJS) {
|
|
4152
|
+
nstack = [nstack.join(",")];
|
|
4153
|
+
} else {
|
|
4154
|
+
nstack = [nstack.join(";")];
|
|
3714
4155
|
}
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
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
|
-
}
|
|
4156
|
+
}
|
|
4157
|
+
return String(nstack[0]);
|
|
4158
|
+
}
|
|
4159
|
+
function escapeValue(v) {
|
|
4160
|
+
if (typeof v === "string") {
|
|
4161
|
+
return JSON.stringify(v).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
4162
|
+
}
|
|
4163
|
+
return v;
|
|
4164
|
+
}
|
|
4165
|
+
function contains(array, obj) {
|
|
4166
|
+
for (var i = 0; i < array.length; i++) {
|
|
4167
|
+
if (array[i] === obj) {
|
|
4168
|
+
return true;
|
|
4169
|
+
}
|
|
4170
|
+
}
|
|
4171
|
+
return false;
|
|
4172
|
+
}
|
|
4173
|
+
function getSymbols(tokens, symbols, options) {
|
|
4174
|
+
options = options || {};
|
|
4175
|
+
var withMembers = !!options.withMembers;
|
|
4176
|
+
var prevVar = null;
|
|
4177
|
+
for (var i = 0; i < tokens.length; i++) {
|
|
4178
|
+
var item = tokens[i];
|
|
4179
|
+
if (item.type === IVAR || item.type === IVARNAME) {
|
|
4180
|
+
if (!withMembers && !contains(symbols, item.value)) {
|
|
4181
|
+
symbols.push(item.value);
|
|
4182
|
+
} else if (prevVar !== null) {
|
|
4183
|
+
if (!contains(symbols, prevVar)) {
|
|
4184
|
+
symbols.push(prevVar);
|
|
3754
4185
|
}
|
|
3755
|
-
|
|
4186
|
+
prevVar = item.value;
|
|
3756
4187
|
} else {
|
|
3757
|
-
|
|
4188
|
+
prevVar = item.value;
|
|
4189
|
+
}
|
|
4190
|
+
} else if (item.type === IMEMBER && withMembers && prevVar !== null) {
|
|
4191
|
+
prevVar += "." + item.value;
|
|
4192
|
+
} else if (item.type === IEXPR) {
|
|
4193
|
+
getSymbols(item.value, symbols, options);
|
|
4194
|
+
} else if (prevVar !== null) {
|
|
4195
|
+
if (!contains(symbols, prevVar)) {
|
|
4196
|
+
symbols.push(prevVar);
|
|
3758
4197
|
}
|
|
4198
|
+
prevVar = null;
|
|
3759
4199
|
}
|
|
3760
|
-
return node;
|
|
3761
4200
|
}
|
|
3762
|
-
|
|
4201
|
+
if (prevVar !== null && !contains(symbols, prevVar)) {
|
|
4202
|
+
symbols.push(prevVar);
|
|
4203
|
+
}
|
|
4204
|
+
}
|
|
4205
|
+
function Expression(tokens, parser) {
|
|
4206
|
+
this.tokens = tokens;
|
|
4207
|
+
this.parser = parser;
|
|
4208
|
+
this.unaryOps = parser.unaryOps;
|
|
4209
|
+
this.binaryOps = parser.binaryOps;
|
|
4210
|
+
this.ternaryOps = parser.ternaryOps;
|
|
4211
|
+
this.functions = parser.functions;
|
|
4212
|
+
}
|
|
4213
|
+
Expression.prototype.simplify = function(values) {
|
|
4214
|
+
values = values || {};
|
|
4215
|
+
return new Expression(simplify(this.tokens, this.unaryOps, this.binaryOps, this.ternaryOps, values), this.parser);
|
|
4216
|
+
};
|
|
4217
|
+
Expression.prototype.substitute = function(variable, expr) {
|
|
4218
|
+
if (!(expr instanceof Expression)) {
|
|
4219
|
+
expr = this.parser.parse(String(expr));
|
|
4220
|
+
}
|
|
4221
|
+
return new Expression(substitute(this.tokens, variable, expr), this.parser);
|
|
4222
|
+
};
|
|
4223
|
+
Expression.prototype.evaluate = function(values) {
|
|
4224
|
+
values = values || {};
|
|
4225
|
+
return evaluate(this.tokens, this, values);
|
|
4226
|
+
};
|
|
4227
|
+
Expression.prototype.toString = function() {
|
|
4228
|
+
return expressionToString(this.tokens, false);
|
|
4229
|
+
};
|
|
4230
|
+
Expression.prototype.symbols = function(options) {
|
|
4231
|
+
options = options || {};
|
|
4232
|
+
var vars = [];
|
|
4233
|
+
getSymbols(this.tokens, vars, options);
|
|
4234
|
+
return vars;
|
|
4235
|
+
};
|
|
4236
|
+
Expression.prototype.variables = function(options) {
|
|
4237
|
+
options = options || {};
|
|
4238
|
+
var vars = [];
|
|
4239
|
+
getSymbols(this.tokens, vars, options);
|
|
4240
|
+
var functions = this.functions;
|
|
4241
|
+
return vars.filter(function(name) {
|
|
4242
|
+
return !(name in functions);
|
|
4243
|
+
});
|
|
3763
4244
|
};
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
4245
|
+
Expression.prototype.toJSFunction = function(param, variables) {
|
|
4246
|
+
var expr = this;
|
|
4247
|
+
var f = new Function(param, "with(this.functions) with (this.ternaryOps) with (this.binaryOps) with (this.unaryOps) { return " + expressionToString(this.simplify(variables).tokens, true) + "; }");
|
|
4248
|
+
return function() {
|
|
4249
|
+
return f.apply(expr, arguments);
|
|
4250
|
+
};
|
|
4251
|
+
};
|
|
4252
|
+
var TEOF = "TEOF";
|
|
4253
|
+
var TOP = "TOP";
|
|
4254
|
+
var TNUMBER = "TNUMBER";
|
|
4255
|
+
var TSTRING = "TSTRING";
|
|
4256
|
+
var TPAREN = "TPAREN";
|
|
4257
|
+
var TBRACKET = "TBRACKET";
|
|
4258
|
+
var TCOMMA = "TCOMMA";
|
|
4259
|
+
var TNAME = "TNAME";
|
|
4260
|
+
var TSEMICOLON = "TSEMICOLON";
|
|
4261
|
+
function Token(type, value, index2) {
|
|
4262
|
+
this.type = type;
|
|
4263
|
+
this.value = value;
|
|
4264
|
+
this.index = index2;
|
|
4265
|
+
}
|
|
4266
|
+
Token.prototype.toString = function() {
|
|
4267
|
+
return this.type + ": " + this.value;
|
|
4268
|
+
};
|
|
4269
|
+
function TokenStream(parser, expression) {
|
|
4270
|
+
this.pos = 0;
|
|
4271
|
+
this.current = null;
|
|
4272
|
+
this.unaryOps = parser.unaryOps;
|
|
4273
|
+
this.binaryOps = parser.binaryOps;
|
|
4274
|
+
this.ternaryOps = parser.ternaryOps;
|
|
4275
|
+
this.consts = parser.consts;
|
|
4276
|
+
this.expression = expression;
|
|
4277
|
+
this.savedPosition = 0;
|
|
4278
|
+
this.savedCurrent = null;
|
|
4279
|
+
this.options = parser.options;
|
|
4280
|
+
this.parser = parser;
|
|
4281
|
+
}
|
|
4282
|
+
TokenStream.prototype.newToken = function(type, value, pos) {
|
|
4283
|
+
return new Token(type, value, pos != null ? pos : this.pos);
|
|
4284
|
+
};
|
|
4285
|
+
TokenStream.prototype.save = function() {
|
|
4286
|
+
this.savedPosition = this.pos;
|
|
4287
|
+
this.savedCurrent = this.current;
|
|
4288
|
+
};
|
|
4289
|
+
TokenStream.prototype.restore = function() {
|
|
4290
|
+
this.pos = this.savedPosition;
|
|
4291
|
+
this.current = this.savedCurrent;
|
|
4292
|
+
};
|
|
4293
|
+
TokenStream.prototype.next = function() {
|
|
4294
|
+
if (this.pos >= this.expression.length) {
|
|
4295
|
+
return this.newToken(TEOF, "EOF");
|
|
4296
|
+
}
|
|
4297
|
+
if (this.isWhitespace() || this.isComment()) {
|
|
4298
|
+
return this.next();
|
|
4299
|
+
} else if (this.isRadixInteger() || this.isNumber() || this.isOperator() || this.isString() || this.isParen() || this.isBracket() || this.isComma() || this.isSemicolon() || this.isNamedOp() || this.isConst() || this.isName()) {
|
|
4300
|
+
return this.current;
|
|
4301
|
+
} else {
|
|
4302
|
+
this.parseError('Unknown character "' + this.expression.charAt(this.pos) + '"');
|
|
4303
|
+
}
|
|
4304
|
+
};
|
|
4305
|
+
TokenStream.prototype.isString = function() {
|
|
4306
|
+
var r = false;
|
|
4307
|
+
var startPos = this.pos;
|
|
4308
|
+
var quote = this.expression.charAt(startPos);
|
|
4309
|
+
if (quote === "'" || quote === '"') {
|
|
4310
|
+
var index2 = this.expression.indexOf(quote, startPos + 1);
|
|
4311
|
+
while (index2 >= 0 && this.pos < this.expression.length) {
|
|
4312
|
+
this.pos = index2 + 1;
|
|
4313
|
+
if (this.expression.charAt(index2 - 1) !== "\\") {
|
|
4314
|
+
var rawString = this.expression.substring(startPos + 1, index2);
|
|
4315
|
+
this.current = this.newToken(TSTRING, this.unescape(rawString), startPos);
|
|
4316
|
+
r = true;
|
|
4317
|
+
break;
|
|
4318
|
+
}
|
|
4319
|
+
index2 = this.expression.indexOf(quote, index2 + 1);
|
|
4320
|
+
}
|
|
4321
|
+
}
|
|
4322
|
+
return r;
|
|
4323
|
+
};
|
|
4324
|
+
TokenStream.prototype.isParen = function() {
|
|
4325
|
+
var c = this.expression.charAt(this.pos);
|
|
4326
|
+
if (c === "(" || c === ")") {
|
|
4327
|
+
this.current = this.newToken(TPAREN, c);
|
|
4328
|
+
this.pos++;
|
|
4329
|
+
return true;
|
|
4330
|
+
}
|
|
4331
|
+
return false;
|
|
4332
|
+
};
|
|
4333
|
+
TokenStream.prototype.isBracket = function() {
|
|
4334
|
+
var c = this.expression.charAt(this.pos);
|
|
4335
|
+
if ((c === "[" || c === "]") && this.isOperatorEnabled("[")) {
|
|
4336
|
+
this.current = this.newToken(TBRACKET, c);
|
|
4337
|
+
this.pos++;
|
|
4338
|
+
return true;
|
|
4339
|
+
}
|
|
4340
|
+
return false;
|
|
4341
|
+
};
|
|
4342
|
+
TokenStream.prototype.isComma = function() {
|
|
4343
|
+
var c = this.expression.charAt(this.pos);
|
|
4344
|
+
if (c === ",") {
|
|
4345
|
+
this.current = this.newToken(TCOMMA, ",");
|
|
4346
|
+
this.pos++;
|
|
4347
|
+
return true;
|
|
4348
|
+
}
|
|
4349
|
+
return false;
|
|
4350
|
+
};
|
|
4351
|
+
TokenStream.prototype.isSemicolon = function() {
|
|
4352
|
+
var c = this.expression.charAt(this.pos);
|
|
4353
|
+
if (c === ";") {
|
|
4354
|
+
this.current = this.newToken(TSEMICOLON, ";");
|
|
4355
|
+
this.pos++;
|
|
4356
|
+
return true;
|
|
4357
|
+
}
|
|
4358
|
+
return false;
|
|
4359
|
+
};
|
|
4360
|
+
TokenStream.prototype.isConst = function() {
|
|
4361
|
+
var startPos = this.pos;
|
|
4362
|
+
var i = startPos;
|
|
4363
|
+
for (; i < this.expression.length; i++) {
|
|
4364
|
+
var c = this.expression.charAt(i);
|
|
4365
|
+
if (c.toUpperCase() === c.toLowerCase()) {
|
|
4366
|
+
if (i === this.pos || c !== "_" && c !== "." && (c < "0" || c > "9")) {
|
|
4367
|
+
break;
|
|
4368
|
+
}
|
|
4369
|
+
}
|
|
4370
|
+
}
|
|
4371
|
+
if (i > startPos) {
|
|
4372
|
+
var str = this.expression.substring(startPos, i);
|
|
4373
|
+
if (str in this.consts) {
|
|
4374
|
+
this.current = this.newToken(TNUMBER, this.consts[str]);
|
|
4375
|
+
this.pos += str.length;
|
|
4376
|
+
return true;
|
|
4377
|
+
}
|
|
4378
|
+
}
|
|
4379
|
+
return false;
|
|
4380
|
+
};
|
|
4381
|
+
TokenStream.prototype.isNamedOp = function() {
|
|
4382
|
+
var startPos = this.pos;
|
|
4383
|
+
var i = startPos;
|
|
4384
|
+
for (; i < this.expression.length; i++) {
|
|
4385
|
+
var c = this.expression.charAt(i);
|
|
4386
|
+
if (c.toUpperCase() === c.toLowerCase()) {
|
|
4387
|
+
if (i === this.pos || c !== "_" && (c < "0" || c > "9")) {
|
|
4388
|
+
break;
|
|
4389
|
+
}
|
|
4390
|
+
}
|
|
4391
|
+
}
|
|
4392
|
+
if (i > startPos) {
|
|
4393
|
+
var str = this.expression.substring(startPos, i);
|
|
4394
|
+
if (this.isOperatorEnabled(str) && (str in this.binaryOps || str in this.unaryOps || str in this.ternaryOps)) {
|
|
4395
|
+
this.current = this.newToken(TOP, str);
|
|
4396
|
+
this.pos += str.length;
|
|
4397
|
+
return true;
|
|
4398
|
+
}
|
|
4399
|
+
}
|
|
4400
|
+
return false;
|
|
4401
|
+
};
|
|
4402
|
+
TokenStream.prototype.isName = function() {
|
|
4403
|
+
var startPos = this.pos;
|
|
4404
|
+
var i = startPos;
|
|
4405
|
+
var hasLetter = false;
|
|
4406
|
+
for (; i < this.expression.length; i++) {
|
|
4407
|
+
var c = this.expression.charAt(i);
|
|
4408
|
+
if (c.toUpperCase() === c.toLowerCase()) {
|
|
4409
|
+
if (i === this.pos && (c === "$" || c === "_")) {
|
|
4410
|
+
if (c === "_") {
|
|
4411
|
+
hasLetter = true;
|
|
4412
|
+
}
|
|
4413
|
+
continue;
|
|
4414
|
+
} else if (i === this.pos || !hasLetter || c !== "_" && (c < "0" || c > "9")) {
|
|
4415
|
+
break;
|
|
4416
|
+
}
|
|
4417
|
+
} else {
|
|
4418
|
+
hasLetter = true;
|
|
4419
|
+
}
|
|
4420
|
+
}
|
|
4421
|
+
if (hasLetter) {
|
|
4422
|
+
var str = this.expression.substring(startPos, i);
|
|
4423
|
+
this.current = this.newToken(TNAME, str);
|
|
4424
|
+
this.pos += str.length;
|
|
4425
|
+
return true;
|
|
4426
|
+
}
|
|
4427
|
+
return false;
|
|
4428
|
+
};
|
|
4429
|
+
TokenStream.prototype.isWhitespace = function() {
|
|
4430
|
+
var r = false;
|
|
4431
|
+
var c = this.expression.charAt(this.pos);
|
|
4432
|
+
while (c === " " || c === " " || c === "\n" || c === "\r") {
|
|
4433
|
+
r = true;
|
|
4434
|
+
this.pos++;
|
|
4435
|
+
if (this.pos >= this.expression.length) {
|
|
4436
|
+
break;
|
|
4437
|
+
}
|
|
4438
|
+
c = this.expression.charAt(this.pos);
|
|
4439
|
+
}
|
|
4440
|
+
return r;
|
|
4441
|
+
};
|
|
4442
|
+
var codePointPattern = /^[0-9a-f]{4}$/i;
|
|
4443
|
+
TokenStream.prototype.unescape = function(v) {
|
|
4444
|
+
var index2 = v.indexOf("\\");
|
|
4445
|
+
if (index2 < 0) {
|
|
4446
|
+
return v;
|
|
4447
|
+
}
|
|
4448
|
+
var buffer = v.substring(0, index2);
|
|
4449
|
+
while (index2 >= 0) {
|
|
4450
|
+
var c = v.charAt(++index2);
|
|
4451
|
+
switch (c) {
|
|
4452
|
+
case "'":
|
|
4453
|
+
buffer += "'";
|
|
4454
|
+
break;
|
|
4455
|
+
case '"':
|
|
4456
|
+
buffer += '"';
|
|
4457
|
+
break;
|
|
4458
|
+
case "\\":
|
|
4459
|
+
buffer += "\\";
|
|
4460
|
+
break;
|
|
4461
|
+
case "/":
|
|
4462
|
+
buffer += "/";
|
|
4463
|
+
break;
|
|
4464
|
+
case "b":
|
|
4465
|
+
buffer += "\b";
|
|
4466
|
+
break;
|
|
4467
|
+
case "f":
|
|
4468
|
+
buffer += "\f";
|
|
4469
|
+
break;
|
|
4470
|
+
case "n":
|
|
4471
|
+
buffer += "\n";
|
|
4472
|
+
break;
|
|
4473
|
+
case "r":
|
|
4474
|
+
buffer += "\r";
|
|
4475
|
+
break;
|
|
4476
|
+
case "t":
|
|
4477
|
+
buffer += " ";
|
|
4478
|
+
break;
|
|
4479
|
+
case "u":
|
|
4480
|
+
var codePoint = v.substring(index2 + 1, index2 + 5);
|
|
4481
|
+
if (!codePointPattern.test(codePoint)) {
|
|
4482
|
+
this.parseError("Illegal escape sequence: \\u" + codePoint);
|
|
4483
|
+
}
|
|
4484
|
+
buffer += String.fromCharCode(parseInt(codePoint, 16));
|
|
4485
|
+
index2 += 4;
|
|
4486
|
+
break;
|
|
4487
|
+
default:
|
|
4488
|
+
throw this.parseError('Illegal escape sequence: "\\' + c + '"');
|
|
4489
|
+
}
|
|
4490
|
+
++index2;
|
|
4491
|
+
var backslash = v.indexOf("\\", index2);
|
|
4492
|
+
buffer += v.substring(index2, backslash < 0 ? v.length : backslash);
|
|
4493
|
+
index2 = backslash;
|
|
4494
|
+
}
|
|
4495
|
+
return buffer;
|
|
4496
|
+
};
|
|
4497
|
+
TokenStream.prototype.isComment = function() {
|
|
4498
|
+
var c = this.expression.charAt(this.pos);
|
|
4499
|
+
if (c === "/" && this.expression.charAt(this.pos + 1) === "*") {
|
|
4500
|
+
this.pos = this.expression.indexOf("*/", this.pos) + 2;
|
|
4501
|
+
if (this.pos === 1) {
|
|
4502
|
+
this.pos = this.expression.length;
|
|
4503
|
+
}
|
|
4504
|
+
return true;
|
|
4505
|
+
}
|
|
4506
|
+
return false;
|
|
4507
|
+
};
|
|
4508
|
+
TokenStream.prototype.isRadixInteger = function() {
|
|
4509
|
+
var pos = this.pos;
|
|
4510
|
+
if (pos >= this.expression.length - 2 || this.expression.charAt(pos) !== "0") {
|
|
4511
|
+
return false;
|
|
4512
|
+
}
|
|
4513
|
+
++pos;
|
|
4514
|
+
var radix;
|
|
4515
|
+
var validDigit;
|
|
4516
|
+
if (this.expression.charAt(pos) === "x") {
|
|
4517
|
+
radix = 16;
|
|
4518
|
+
validDigit = /^[0-9a-f]$/i;
|
|
4519
|
+
++pos;
|
|
4520
|
+
} else if (this.expression.charAt(pos) === "b") {
|
|
4521
|
+
radix = 2;
|
|
4522
|
+
validDigit = /^[01]$/i;
|
|
4523
|
+
++pos;
|
|
4524
|
+
} else {
|
|
4525
|
+
return false;
|
|
4526
|
+
}
|
|
4527
|
+
var valid = false;
|
|
4528
|
+
var startPos = pos;
|
|
4529
|
+
while (pos < this.expression.length) {
|
|
4530
|
+
var c = this.expression.charAt(pos);
|
|
4531
|
+
if (validDigit.test(c)) {
|
|
4532
|
+
pos++;
|
|
4533
|
+
valid = true;
|
|
4534
|
+
} else {
|
|
4535
|
+
break;
|
|
4536
|
+
}
|
|
4537
|
+
}
|
|
4538
|
+
if (valid) {
|
|
4539
|
+
this.current = this.newToken(TNUMBER, parseInt(this.expression.substring(startPos, pos), radix));
|
|
4540
|
+
this.pos = pos;
|
|
4541
|
+
}
|
|
4542
|
+
return valid;
|
|
4543
|
+
};
|
|
4544
|
+
TokenStream.prototype.isNumber = function() {
|
|
4545
|
+
var valid = false;
|
|
4546
|
+
var pos = this.pos;
|
|
4547
|
+
var startPos = pos;
|
|
4548
|
+
var resetPos = pos;
|
|
4549
|
+
var foundDot = false;
|
|
4550
|
+
var foundDigits = false;
|
|
4551
|
+
var c;
|
|
4552
|
+
while (pos < this.expression.length) {
|
|
4553
|
+
c = this.expression.charAt(pos);
|
|
4554
|
+
if (c >= "0" && c <= "9" || !foundDot && c === ".") {
|
|
4555
|
+
if (c === ".") {
|
|
4556
|
+
foundDot = true;
|
|
4557
|
+
} else {
|
|
4558
|
+
foundDigits = true;
|
|
4559
|
+
}
|
|
4560
|
+
pos++;
|
|
4561
|
+
valid = foundDigits;
|
|
4562
|
+
} else {
|
|
4563
|
+
break;
|
|
4564
|
+
}
|
|
4565
|
+
}
|
|
4566
|
+
if (valid) {
|
|
4567
|
+
resetPos = pos;
|
|
4568
|
+
}
|
|
4569
|
+
if (c === "e" || c === "E") {
|
|
4570
|
+
pos++;
|
|
4571
|
+
var acceptSign = true;
|
|
4572
|
+
var validExponent = false;
|
|
4573
|
+
while (pos < this.expression.length) {
|
|
4574
|
+
c = this.expression.charAt(pos);
|
|
4575
|
+
if (acceptSign && (c === "+" || c === "-")) {
|
|
4576
|
+
acceptSign = false;
|
|
4577
|
+
} else if (c >= "0" && c <= "9") {
|
|
4578
|
+
validExponent = true;
|
|
4579
|
+
acceptSign = false;
|
|
4580
|
+
} else {
|
|
4581
|
+
break;
|
|
4582
|
+
}
|
|
4583
|
+
pos++;
|
|
4584
|
+
}
|
|
4585
|
+
if (!validExponent) {
|
|
4586
|
+
pos = resetPos;
|
|
4587
|
+
}
|
|
4588
|
+
}
|
|
4589
|
+
if (valid) {
|
|
4590
|
+
this.current = this.newToken(TNUMBER, parseFloat(this.expression.substring(startPos, pos)));
|
|
4591
|
+
this.pos = pos;
|
|
4592
|
+
} else {
|
|
4593
|
+
this.pos = resetPos;
|
|
4594
|
+
}
|
|
4595
|
+
return valid;
|
|
4596
|
+
};
|
|
4597
|
+
TokenStream.prototype.isOperator = function() {
|
|
4598
|
+
var startPos = this.pos;
|
|
4599
|
+
var c = this.expression.charAt(this.pos);
|
|
4600
|
+
if (c === "+" || c === "-" || c === "*" || c === "/" || c === "%" || c === "^" || c === "?" || c === ":" || c === ".") {
|
|
4601
|
+
this.current = this.newToken(TOP, c);
|
|
4602
|
+
} else if (c === "∙" || c === "•") {
|
|
4603
|
+
this.current = this.newToken(TOP, "*");
|
|
4604
|
+
} else if (c === ">") {
|
|
4605
|
+
if (this.expression.charAt(this.pos + 1) === "=") {
|
|
4606
|
+
this.current = this.newToken(TOP, ">=");
|
|
4607
|
+
this.pos++;
|
|
4608
|
+
} else {
|
|
4609
|
+
this.current = this.newToken(TOP, ">");
|
|
4610
|
+
}
|
|
4611
|
+
} else if (c === "<") {
|
|
4612
|
+
if (this.expression.charAt(this.pos + 1) === "=") {
|
|
4613
|
+
this.current = this.newToken(TOP, "<=");
|
|
4614
|
+
this.pos++;
|
|
4615
|
+
} else {
|
|
4616
|
+
this.current = this.newToken(TOP, "<");
|
|
4617
|
+
}
|
|
4618
|
+
} else if (c === "|") {
|
|
4619
|
+
if (this.expression.charAt(this.pos + 1) === "|") {
|
|
4620
|
+
this.current = this.newToken(TOP, "||");
|
|
4621
|
+
this.pos++;
|
|
4622
|
+
} else {
|
|
4623
|
+
return false;
|
|
4624
|
+
}
|
|
4625
|
+
} else if (c === "=") {
|
|
4626
|
+
if (this.expression.charAt(this.pos + 1) === "=") {
|
|
4627
|
+
this.current = this.newToken(TOP, "==");
|
|
4628
|
+
this.pos++;
|
|
4629
|
+
} else {
|
|
4630
|
+
this.current = this.newToken(TOP, c);
|
|
4631
|
+
}
|
|
4632
|
+
} else if (c === "!") {
|
|
4633
|
+
if (this.expression.charAt(this.pos + 1) === "=") {
|
|
4634
|
+
this.current = this.newToken(TOP, "!=");
|
|
4635
|
+
this.pos++;
|
|
4636
|
+
} else {
|
|
4637
|
+
this.current = this.newToken(TOP, c);
|
|
4638
|
+
}
|
|
4639
|
+
} else {
|
|
4640
|
+
return false;
|
|
4641
|
+
}
|
|
4642
|
+
this.pos++;
|
|
4643
|
+
if (this.isOperatorEnabled(this.current.value)) {
|
|
4644
|
+
return true;
|
|
4645
|
+
} else {
|
|
4646
|
+
this.pos = startPos;
|
|
4647
|
+
return false;
|
|
4648
|
+
}
|
|
4649
|
+
};
|
|
4650
|
+
TokenStream.prototype.isOperatorEnabled = function(op) {
|
|
4651
|
+
return this.parser.isOperatorEnabled(op);
|
|
4652
|
+
};
|
|
4653
|
+
TokenStream.prototype.getCoordinates = function() {
|
|
4654
|
+
var line = 0;
|
|
4655
|
+
var column;
|
|
4656
|
+
var newline = -1;
|
|
4657
|
+
do {
|
|
4658
|
+
line++;
|
|
4659
|
+
column = this.pos - newline;
|
|
4660
|
+
newline = this.expression.indexOf("\n", newline + 1);
|
|
4661
|
+
} while (newline >= 0 && newline < this.pos);
|
|
4662
|
+
return {
|
|
4663
|
+
line,
|
|
4664
|
+
column
|
|
4665
|
+
};
|
|
4666
|
+
};
|
|
4667
|
+
TokenStream.prototype.parseError = function(msg) {
|
|
4668
|
+
var coords = this.getCoordinates();
|
|
4669
|
+
throw new Error("parse error [" + coords.line + ":" + coords.column + "]: " + msg);
|
|
4670
|
+
};
|
|
4671
|
+
function ParserState(parser, tokenStream, options) {
|
|
4672
|
+
this.parser = parser;
|
|
4673
|
+
this.tokens = tokenStream;
|
|
4674
|
+
this.current = null;
|
|
4675
|
+
this.nextToken = null;
|
|
4676
|
+
this.next();
|
|
4677
|
+
this.savedCurrent = null;
|
|
4678
|
+
this.savedNextToken = null;
|
|
4679
|
+
this.allowMemberAccess = options.allowMemberAccess !== false;
|
|
4680
|
+
}
|
|
4681
|
+
ParserState.prototype.next = function() {
|
|
4682
|
+
this.current = this.nextToken;
|
|
4683
|
+
return this.nextToken = this.tokens.next();
|
|
4684
|
+
};
|
|
4685
|
+
ParserState.prototype.tokenMatches = function(token, value) {
|
|
4686
|
+
if (typeof value === "undefined") {
|
|
4687
|
+
return true;
|
|
4688
|
+
} else if (Array.isArray(value)) {
|
|
4689
|
+
return contains(value, token.value);
|
|
4690
|
+
} else if (typeof value === "function") {
|
|
4691
|
+
return value(token);
|
|
4692
|
+
} else {
|
|
4693
|
+
return token.value === value;
|
|
4694
|
+
}
|
|
4695
|
+
};
|
|
4696
|
+
ParserState.prototype.save = function() {
|
|
4697
|
+
this.savedCurrent = this.current;
|
|
4698
|
+
this.savedNextToken = this.nextToken;
|
|
4699
|
+
this.tokens.save();
|
|
4700
|
+
};
|
|
4701
|
+
ParserState.prototype.restore = function() {
|
|
4702
|
+
this.tokens.restore();
|
|
4703
|
+
this.current = this.savedCurrent;
|
|
4704
|
+
this.nextToken = this.savedNextToken;
|
|
4705
|
+
};
|
|
4706
|
+
ParserState.prototype.accept = function(type, value) {
|
|
4707
|
+
if (this.nextToken.type === type && this.tokenMatches(this.nextToken, value)) {
|
|
4708
|
+
this.next();
|
|
4709
|
+
return true;
|
|
4710
|
+
}
|
|
4711
|
+
return false;
|
|
4712
|
+
};
|
|
4713
|
+
ParserState.prototype.expect = function(type, value) {
|
|
4714
|
+
if (!this.accept(type, value)) {
|
|
4715
|
+
var coords = this.tokens.getCoordinates();
|
|
4716
|
+
throw new Error("parse error [" + coords.line + ":" + coords.column + "]: Expected " + (value || type));
|
|
4717
|
+
}
|
|
4718
|
+
};
|
|
4719
|
+
ParserState.prototype.parseAtom = function(instr) {
|
|
4720
|
+
var unaryOps = this.tokens.unaryOps;
|
|
4721
|
+
function isPrefixOperator(token) {
|
|
4722
|
+
return token.value in unaryOps;
|
|
4723
|
+
}
|
|
4724
|
+
if (this.accept(TNAME) || this.accept(TOP, isPrefixOperator)) {
|
|
4725
|
+
instr.push(new Instruction(IVAR, this.current.value));
|
|
4726
|
+
} else if (this.accept(TNUMBER)) {
|
|
4727
|
+
instr.push(new Instruction(INUMBER, this.current.value));
|
|
4728
|
+
} else if (this.accept(TSTRING)) {
|
|
4729
|
+
instr.push(new Instruction(INUMBER, this.current.value));
|
|
4730
|
+
} else if (this.accept(TPAREN, "(")) {
|
|
4731
|
+
this.parseExpression(instr);
|
|
4732
|
+
this.expect(TPAREN, ")");
|
|
4733
|
+
} else if (this.accept(TBRACKET, "[")) {
|
|
4734
|
+
if (this.accept(TBRACKET, "]")) {
|
|
4735
|
+
instr.push(new Instruction(IARRAY, 0));
|
|
4736
|
+
} else {
|
|
4737
|
+
var argCount = this.parseArrayList(instr);
|
|
4738
|
+
instr.push(new Instruction(IARRAY, argCount));
|
|
4739
|
+
}
|
|
4740
|
+
} else {
|
|
4741
|
+
throw new Error("unexpected " + this.nextToken);
|
|
4742
|
+
}
|
|
4743
|
+
};
|
|
4744
|
+
ParserState.prototype.parseExpression = function(instr) {
|
|
4745
|
+
var exprInstr = [];
|
|
4746
|
+
if (this.parseUntilEndStatement(instr, exprInstr)) {
|
|
4747
|
+
return;
|
|
4748
|
+
}
|
|
4749
|
+
this.parseVariableAssignmentExpression(exprInstr);
|
|
4750
|
+
if (this.parseUntilEndStatement(instr, exprInstr)) {
|
|
4751
|
+
return;
|
|
4752
|
+
}
|
|
4753
|
+
this.pushExpression(instr, exprInstr);
|
|
4754
|
+
};
|
|
4755
|
+
ParserState.prototype.pushExpression = function(instr, exprInstr) {
|
|
4756
|
+
for (var i = 0, len2 = exprInstr.length; i < len2; i++) {
|
|
4757
|
+
instr.push(exprInstr[i]);
|
|
4758
|
+
}
|
|
4759
|
+
};
|
|
4760
|
+
ParserState.prototype.parseUntilEndStatement = function(instr, exprInstr) {
|
|
4761
|
+
if (!this.accept(TSEMICOLON)) return false;
|
|
4762
|
+
if (this.nextToken && this.nextToken.type !== TEOF && !(this.nextToken.type === TPAREN && this.nextToken.value === ")")) {
|
|
4763
|
+
exprInstr.push(new Instruction(IENDSTATEMENT));
|
|
4764
|
+
}
|
|
4765
|
+
if (this.nextToken.type !== TEOF) {
|
|
4766
|
+
this.parseExpression(exprInstr);
|
|
4767
|
+
}
|
|
4768
|
+
instr.push(new Instruction(IEXPR, exprInstr));
|
|
4769
|
+
return true;
|
|
4770
|
+
};
|
|
4771
|
+
ParserState.prototype.parseArrayList = function(instr) {
|
|
4772
|
+
var argCount = 0;
|
|
4773
|
+
while (!this.accept(TBRACKET, "]")) {
|
|
4774
|
+
this.parseExpression(instr);
|
|
4775
|
+
++argCount;
|
|
4776
|
+
while (this.accept(TCOMMA)) {
|
|
4777
|
+
this.parseExpression(instr);
|
|
4778
|
+
++argCount;
|
|
4779
|
+
}
|
|
4780
|
+
}
|
|
4781
|
+
return argCount;
|
|
4782
|
+
};
|
|
4783
|
+
ParserState.prototype.parseVariableAssignmentExpression = function(instr) {
|
|
4784
|
+
this.parseConditionalExpression(instr);
|
|
4785
|
+
while (this.accept(TOP, "=")) {
|
|
4786
|
+
var varName = instr.pop();
|
|
4787
|
+
var varValue = [];
|
|
4788
|
+
var lastInstrIndex = instr.length - 1;
|
|
4789
|
+
if (varName.type === IFUNCALL) {
|
|
4790
|
+
if (!this.tokens.isOperatorEnabled("()=")) {
|
|
4791
|
+
throw new Error("function definition is not permitted");
|
|
4792
|
+
}
|
|
4793
|
+
for (var i = 0, len2 = varName.value + 1; i < len2; i++) {
|
|
4794
|
+
var index2 = lastInstrIndex - i;
|
|
4795
|
+
if (instr[index2].type === IVAR) {
|
|
4796
|
+
instr[index2] = new Instruction(IVARNAME, instr[index2].value);
|
|
4797
|
+
}
|
|
4798
|
+
}
|
|
4799
|
+
this.parseVariableAssignmentExpression(varValue);
|
|
4800
|
+
instr.push(new Instruction(IEXPR, varValue));
|
|
4801
|
+
instr.push(new Instruction(IFUNDEF, varName.value));
|
|
4802
|
+
continue;
|
|
4803
|
+
}
|
|
4804
|
+
if (varName.type !== IVAR && varName.type !== IMEMBER) {
|
|
4805
|
+
throw new Error("expected variable for assignment");
|
|
4806
|
+
}
|
|
4807
|
+
this.parseVariableAssignmentExpression(varValue);
|
|
4808
|
+
instr.push(new Instruction(IVARNAME, varName.value));
|
|
4809
|
+
instr.push(new Instruction(IEXPR, varValue));
|
|
4810
|
+
instr.push(binaryInstruction("="));
|
|
4811
|
+
}
|
|
4812
|
+
};
|
|
4813
|
+
ParserState.prototype.parseConditionalExpression = function(instr) {
|
|
4814
|
+
this.parseOrExpression(instr);
|
|
4815
|
+
while (this.accept(TOP, "?")) {
|
|
4816
|
+
var trueBranch = [];
|
|
4817
|
+
var falseBranch = [];
|
|
4818
|
+
this.parseConditionalExpression(trueBranch);
|
|
4819
|
+
this.expect(TOP, ":");
|
|
4820
|
+
this.parseConditionalExpression(falseBranch);
|
|
4821
|
+
instr.push(new Instruction(IEXPR, trueBranch));
|
|
4822
|
+
instr.push(new Instruction(IEXPR, falseBranch));
|
|
4823
|
+
instr.push(ternaryInstruction("?"));
|
|
4824
|
+
}
|
|
4825
|
+
};
|
|
4826
|
+
ParserState.prototype.parseOrExpression = function(instr) {
|
|
4827
|
+
this.parseAndExpression(instr);
|
|
4828
|
+
while (this.accept(TOP, "or")) {
|
|
4829
|
+
var falseBranch = [];
|
|
4830
|
+
this.parseAndExpression(falseBranch);
|
|
4831
|
+
instr.push(new Instruction(IEXPR, falseBranch));
|
|
4832
|
+
instr.push(binaryInstruction("or"));
|
|
4833
|
+
}
|
|
4834
|
+
};
|
|
4835
|
+
ParserState.prototype.parseAndExpression = function(instr) {
|
|
4836
|
+
this.parseComparison(instr);
|
|
4837
|
+
while (this.accept(TOP, "and")) {
|
|
4838
|
+
var trueBranch = [];
|
|
4839
|
+
this.parseComparison(trueBranch);
|
|
4840
|
+
instr.push(new Instruction(IEXPR, trueBranch));
|
|
4841
|
+
instr.push(binaryInstruction("and"));
|
|
4842
|
+
}
|
|
4843
|
+
};
|
|
4844
|
+
var COMPARISON_OPERATORS = ["==", "!=", "<", "<=", ">=", ">", "in"];
|
|
4845
|
+
ParserState.prototype.parseComparison = function(instr) {
|
|
4846
|
+
this.parseAddSub(instr);
|
|
4847
|
+
while (this.accept(TOP, COMPARISON_OPERATORS)) {
|
|
4848
|
+
var op = this.current;
|
|
4849
|
+
this.parseAddSub(instr);
|
|
4850
|
+
instr.push(binaryInstruction(op.value));
|
|
4851
|
+
}
|
|
4852
|
+
};
|
|
4853
|
+
var ADD_SUB_OPERATORS = ["+", "-", "||"];
|
|
4854
|
+
ParserState.prototype.parseAddSub = function(instr) {
|
|
4855
|
+
this.parseTerm(instr);
|
|
4856
|
+
while (this.accept(TOP, ADD_SUB_OPERATORS)) {
|
|
4857
|
+
var op = this.current;
|
|
4858
|
+
this.parseTerm(instr);
|
|
4859
|
+
instr.push(binaryInstruction(op.value));
|
|
4860
|
+
}
|
|
4861
|
+
};
|
|
4862
|
+
var TERM_OPERATORS = ["*", "/", "%"];
|
|
4863
|
+
ParserState.prototype.parseTerm = function(instr) {
|
|
4864
|
+
this.parseFactor(instr);
|
|
4865
|
+
while (this.accept(TOP, TERM_OPERATORS)) {
|
|
4866
|
+
var op = this.current;
|
|
4867
|
+
this.parseFactor(instr);
|
|
4868
|
+
instr.push(binaryInstruction(op.value));
|
|
4869
|
+
}
|
|
4870
|
+
};
|
|
4871
|
+
ParserState.prototype.parseFactor = function(instr) {
|
|
4872
|
+
var unaryOps = this.tokens.unaryOps;
|
|
4873
|
+
function isPrefixOperator(token) {
|
|
4874
|
+
return token.value in unaryOps;
|
|
4875
|
+
}
|
|
4876
|
+
this.save();
|
|
4877
|
+
if (this.accept(TOP, isPrefixOperator)) {
|
|
4878
|
+
if (this.current.value !== "-" && this.current.value !== "+") {
|
|
4879
|
+
if (this.nextToken.type === TPAREN && this.nextToken.value === "(") {
|
|
4880
|
+
this.restore();
|
|
4881
|
+
this.parseExponential(instr);
|
|
4882
|
+
return;
|
|
4883
|
+
} else if (this.nextToken.type === TSEMICOLON || this.nextToken.type === TCOMMA || this.nextToken.type === TEOF || this.nextToken.type === TPAREN && this.nextToken.value === ")") {
|
|
4884
|
+
this.restore();
|
|
4885
|
+
this.parseAtom(instr);
|
|
4886
|
+
return;
|
|
4887
|
+
}
|
|
4888
|
+
}
|
|
4889
|
+
var op = this.current;
|
|
4890
|
+
this.parseFactor(instr);
|
|
4891
|
+
instr.push(unaryInstruction(op.value));
|
|
4892
|
+
} else {
|
|
4893
|
+
this.parseExponential(instr);
|
|
4894
|
+
}
|
|
4895
|
+
};
|
|
4896
|
+
ParserState.prototype.parseExponential = function(instr) {
|
|
4897
|
+
this.parsePostfixExpression(instr);
|
|
4898
|
+
while (this.accept(TOP, "^")) {
|
|
4899
|
+
this.parseFactor(instr);
|
|
4900
|
+
instr.push(binaryInstruction("^"));
|
|
4901
|
+
}
|
|
4902
|
+
};
|
|
4903
|
+
ParserState.prototype.parsePostfixExpression = function(instr) {
|
|
4904
|
+
this.parseFunctionCall(instr);
|
|
4905
|
+
while (this.accept(TOP, "!")) {
|
|
4906
|
+
instr.push(unaryInstruction("!"));
|
|
4907
|
+
}
|
|
4908
|
+
};
|
|
4909
|
+
ParserState.prototype.parseFunctionCall = function(instr) {
|
|
4910
|
+
var unaryOps = this.tokens.unaryOps;
|
|
4911
|
+
function isPrefixOperator(token) {
|
|
4912
|
+
return token.value in unaryOps;
|
|
4913
|
+
}
|
|
4914
|
+
if (this.accept(TOP, isPrefixOperator)) {
|
|
4915
|
+
var op = this.current;
|
|
4916
|
+
this.parseAtom(instr);
|
|
4917
|
+
instr.push(unaryInstruction(op.value));
|
|
4918
|
+
} else {
|
|
4919
|
+
this.parseMemberExpression(instr);
|
|
4920
|
+
while (this.accept(TPAREN, "(")) {
|
|
4921
|
+
if (this.accept(TPAREN, ")")) {
|
|
4922
|
+
instr.push(new Instruction(IFUNCALL, 0));
|
|
4923
|
+
} else {
|
|
4924
|
+
var argCount = this.parseArgumentList(instr);
|
|
4925
|
+
instr.push(new Instruction(IFUNCALL, argCount));
|
|
4926
|
+
}
|
|
4927
|
+
}
|
|
4928
|
+
}
|
|
4929
|
+
};
|
|
4930
|
+
ParserState.prototype.parseArgumentList = function(instr) {
|
|
4931
|
+
var argCount = 0;
|
|
4932
|
+
while (!this.accept(TPAREN, ")")) {
|
|
4933
|
+
this.parseExpression(instr);
|
|
4934
|
+
++argCount;
|
|
4935
|
+
while (this.accept(TCOMMA)) {
|
|
4936
|
+
this.parseExpression(instr);
|
|
4937
|
+
++argCount;
|
|
4938
|
+
}
|
|
4939
|
+
}
|
|
4940
|
+
return argCount;
|
|
4941
|
+
};
|
|
4942
|
+
ParserState.prototype.parseMemberExpression = function(instr) {
|
|
4943
|
+
this.parseAtom(instr);
|
|
4944
|
+
while (this.accept(TOP, ".") || this.accept(TBRACKET, "[")) {
|
|
4945
|
+
var op = this.current;
|
|
4946
|
+
if (op.value === ".") {
|
|
4947
|
+
if (!this.allowMemberAccess) {
|
|
4948
|
+
throw new Error('unexpected ".", member access is not permitted');
|
|
4949
|
+
}
|
|
4950
|
+
this.expect(TNAME);
|
|
4951
|
+
instr.push(new Instruction(IMEMBER, this.current.value));
|
|
4952
|
+
} else if (op.value === "[") {
|
|
4953
|
+
if (!this.tokens.isOperatorEnabled("[")) {
|
|
4954
|
+
throw new Error('unexpected "[]", arrays are disabled');
|
|
4955
|
+
}
|
|
4956
|
+
this.parseExpression(instr);
|
|
4957
|
+
this.expect(TBRACKET, "]");
|
|
4958
|
+
instr.push(binaryInstruction("["));
|
|
4959
|
+
} else {
|
|
4960
|
+
throw new Error("unexpected symbol: " + op.value);
|
|
4961
|
+
}
|
|
4962
|
+
}
|
|
4963
|
+
};
|
|
4964
|
+
function add(a, b) {
|
|
4965
|
+
return Number(a) + Number(b);
|
|
4966
|
+
}
|
|
4967
|
+
function sub(a, b) {
|
|
4968
|
+
return a - b;
|
|
4969
|
+
}
|
|
4970
|
+
function mul(a, b) {
|
|
4971
|
+
return a * b;
|
|
4972
|
+
}
|
|
4973
|
+
function div(a, b) {
|
|
4974
|
+
return a / b;
|
|
4975
|
+
}
|
|
4976
|
+
function mod(a, b) {
|
|
4977
|
+
return a % b;
|
|
4978
|
+
}
|
|
4979
|
+
function concat(a, b) {
|
|
4980
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
4981
|
+
return a.concat(b);
|
|
4982
|
+
}
|
|
4983
|
+
return "" + a + b;
|
|
4984
|
+
}
|
|
4985
|
+
function equal(a, b) {
|
|
4986
|
+
return a === b;
|
|
4987
|
+
}
|
|
4988
|
+
function notEqual(a, b) {
|
|
4989
|
+
return a !== b;
|
|
4990
|
+
}
|
|
4991
|
+
function greaterThan(a, b) {
|
|
4992
|
+
return a > b;
|
|
4993
|
+
}
|
|
4994
|
+
function lessThan(a, b) {
|
|
4995
|
+
return a < b;
|
|
4996
|
+
}
|
|
4997
|
+
function greaterThanEqual(a, b) {
|
|
4998
|
+
return a >= b;
|
|
4999
|
+
}
|
|
5000
|
+
function lessThanEqual(a, b) {
|
|
5001
|
+
return a <= b;
|
|
5002
|
+
}
|
|
5003
|
+
function andOperator(a, b) {
|
|
5004
|
+
return Boolean(a && b);
|
|
5005
|
+
}
|
|
5006
|
+
function orOperator(a, b) {
|
|
5007
|
+
return Boolean(a || b);
|
|
5008
|
+
}
|
|
5009
|
+
function inOperator(a, b) {
|
|
5010
|
+
return contains(b, a);
|
|
5011
|
+
}
|
|
5012
|
+
function sinh(a) {
|
|
5013
|
+
return (Math.exp(a) - Math.exp(-a)) / 2;
|
|
5014
|
+
}
|
|
5015
|
+
function cosh(a) {
|
|
5016
|
+
return (Math.exp(a) + Math.exp(-a)) / 2;
|
|
5017
|
+
}
|
|
5018
|
+
function tanh(a) {
|
|
5019
|
+
if (a === Infinity) return 1;
|
|
5020
|
+
if (a === -Infinity) return -1;
|
|
5021
|
+
return (Math.exp(a) - Math.exp(-a)) / (Math.exp(a) + Math.exp(-a));
|
|
5022
|
+
}
|
|
5023
|
+
function asinh(a) {
|
|
5024
|
+
if (a === -Infinity) return a;
|
|
5025
|
+
return Math.log(a + Math.sqrt(a * a + 1));
|
|
5026
|
+
}
|
|
5027
|
+
function acosh(a) {
|
|
5028
|
+
return Math.log(a + Math.sqrt(a * a - 1));
|
|
5029
|
+
}
|
|
5030
|
+
function atanh(a) {
|
|
5031
|
+
return Math.log((1 + a) / (1 - a)) / 2;
|
|
5032
|
+
}
|
|
5033
|
+
function log10(a) {
|
|
5034
|
+
return Math.log(a) * Math.LOG10E;
|
|
5035
|
+
}
|
|
5036
|
+
function neg(a) {
|
|
5037
|
+
return -a;
|
|
5038
|
+
}
|
|
5039
|
+
function not(a) {
|
|
5040
|
+
return !a;
|
|
5041
|
+
}
|
|
5042
|
+
function trunc(a) {
|
|
5043
|
+
return a < 0 ? Math.ceil(a) : Math.floor(a);
|
|
5044
|
+
}
|
|
5045
|
+
function random(a) {
|
|
5046
|
+
return Math.random() * (a || 1);
|
|
5047
|
+
}
|
|
5048
|
+
function factorial(a) {
|
|
5049
|
+
return gamma(a + 1);
|
|
5050
|
+
}
|
|
5051
|
+
function isInteger(value) {
|
|
5052
|
+
return isFinite(value) && value === Math.round(value);
|
|
5053
|
+
}
|
|
5054
|
+
var GAMMA_G = 4.7421875;
|
|
5055
|
+
var GAMMA_P = [
|
|
5056
|
+
0.9999999999999971,
|
|
5057
|
+
57.15623566586292,
|
|
5058
|
+
-59.59796035547549,
|
|
5059
|
+
14.136097974741746,
|
|
5060
|
+
-0.4919138160976202,
|
|
5061
|
+
3399464998481189e-20,
|
|
5062
|
+
4652362892704858e-20,
|
|
5063
|
+
-9837447530487956e-20,
|
|
5064
|
+
1580887032249125e-19,
|
|
5065
|
+
-21026444172410488e-20,
|
|
5066
|
+
21743961811521265e-20,
|
|
5067
|
+
-1643181065367639e-19,
|
|
5068
|
+
8441822398385275e-20,
|
|
5069
|
+
-26190838401581408e-21,
|
|
5070
|
+
36899182659531625e-22
|
|
5071
|
+
];
|
|
5072
|
+
function gamma(n) {
|
|
5073
|
+
var t, x;
|
|
5074
|
+
if (isInteger(n)) {
|
|
5075
|
+
if (n <= 0) {
|
|
5076
|
+
return isFinite(n) ? Infinity : NaN;
|
|
5077
|
+
}
|
|
5078
|
+
if (n > 171) {
|
|
5079
|
+
return Infinity;
|
|
5080
|
+
}
|
|
5081
|
+
var value = n - 2;
|
|
5082
|
+
var res = n - 1;
|
|
5083
|
+
while (value > 1) {
|
|
5084
|
+
res *= value;
|
|
5085
|
+
value--;
|
|
5086
|
+
}
|
|
5087
|
+
if (res === 0) {
|
|
5088
|
+
res = 1;
|
|
5089
|
+
}
|
|
5090
|
+
return res;
|
|
5091
|
+
}
|
|
5092
|
+
if (n < 0.5) {
|
|
5093
|
+
return Math.PI / (Math.sin(Math.PI * n) * gamma(1 - n));
|
|
5094
|
+
}
|
|
5095
|
+
if (n >= 171.35) {
|
|
5096
|
+
return Infinity;
|
|
5097
|
+
}
|
|
5098
|
+
if (n > 85) {
|
|
5099
|
+
var twoN = n * n;
|
|
5100
|
+
var threeN = twoN * n;
|
|
5101
|
+
var fourN = threeN * n;
|
|
5102
|
+
var fiveN = fourN * n;
|
|
5103
|
+
return Math.sqrt(2 * Math.PI / n) * Math.pow(n / Math.E, n) * (1 + 1 / (12 * n) + 1 / (288 * twoN) - 139 / (51840 * threeN) - 571 / (2488320 * fourN) + 163879 / (209018880 * fiveN) + 5246819 / (75246796800 * fiveN * n));
|
|
5104
|
+
}
|
|
5105
|
+
--n;
|
|
5106
|
+
x = GAMMA_P[0];
|
|
5107
|
+
for (var i = 1; i < GAMMA_P.length; ++i) {
|
|
5108
|
+
x += GAMMA_P[i] / (n + i);
|
|
5109
|
+
}
|
|
5110
|
+
t = n + GAMMA_G + 0.5;
|
|
5111
|
+
return Math.sqrt(2 * Math.PI) * Math.pow(t, n + 0.5) * Math.exp(-t) * x;
|
|
5112
|
+
}
|
|
5113
|
+
function stringOrArrayLength(s) {
|
|
5114
|
+
if (Array.isArray(s)) {
|
|
5115
|
+
return s.length;
|
|
5116
|
+
}
|
|
5117
|
+
return String(s).length;
|
|
5118
|
+
}
|
|
5119
|
+
function hypot() {
|
|
5120
|
+
var sum2 = 0;
|
|
5121
|
+
var larg = 0;
|
|
5122
|
+
for (var i = 0; i < arguments.length; i++) {
|
|
5123
|
+
var arg = Math.abs(arguments[i]);
|
|
5124
|
+
var div2;
|
|
5125
|
+
if (larg < arg) {
|
|
5126
|
+
div2 = larg / arg;
|
|
5127
|
+
sum2 = sum2 * div2 * div2 + 1;
|
|
5128
|
+
larg = arg;
|
|
5129
|
+
} else if (arg > 0) {
|
|
5130
|
+
div2 = arg / larg;
|
|
5131
|
+
sum2 += div2 * div2;
|
|
5132
|
+
} else {
|
|
5133
|
+
sum2 += arg;
|
|
5134
|
+
}
|
|
5135
|
+
}
|
|
5136
|
+
return larg === Infinity ? Infinity : larg * Math.sqrt(sum2);
|
|
5137
|
+
}
|
|
5138
|
+
function condition(cond, yep, nope) {
|
|
5139
|
+
return cond ? yep : nope;
|
|
5140
|
+
}
|
|
5141
|
+
function roundTo(value, exp) {
|
|
5142
|
+
if (typeof exp === "undefined" || +exp === 0) {
|
|
5143
|
+
return Math.round(value);
|
|
5144
|
+
}
|
|
5145
|
+
value = +value;
|
|
5146
|
+
exp = -+exp;
|
|
5147
|
+
if (isNaN(value) || !(typeof exp === "number" && exp % 1 === 0)) {
|
|
5148
|
+
return NaN;
|
|
5149
|
+
}
|
|
5150
|
+
value = value.toString().split("e");
|
|
5151
|
+
value = Math.round(+(value[0] + "e" + (value[1] ? +value[1] - exp : -exp)));
|
|
5152
|
+
value = value.toString().split("e");
|
|
5153
|
+
return +(value[0] + "e" + (value[1] ? +value[1] + exp : exp));
|
|
5154
|
+
}
|
|
5155
|
+
function setVar(name, value, variables) {
|
|
5156
|
+
if (variables) variables[name] = value;
|
|
5157
|
+
return value;
|
|
5158
|
+
}
|
|
5159
|
+
function arrayIndex(array, index2) {
|
|
5160
|
+
return array[index2 | 0];
|
|
5161
|
+
}
|
|
5162
|
+
function max(array) {
|
|
5163
|
+
if (arguments.length === 1 && Array.isArray(array)) {
|
|
5164
|
+
return Math.max.apply(Math, array);
|
|
5165
|
+
} else {
|
|
5166
|
+
return Math.max.apply(Math, arguments);
|
|
5167
|
+
}
|
|
5168
|
+
}
|
|
5169
|
+
function min(array) {
|
|
5170
|
+
if (arguments.length === 1 && Array.isArray(array)) {
|
|
5171
|
+
return Math.min.apply(Math, array);
|
|
5172
|
+
} else {
|
|
5173
|
+
return Math.min.apply(Math, arguments);
|
|
5174
|
+
}
|
|
5175
|
+
}
|
|
5176
|
+
function arrayMap(f, a) {
|
|
5177
|
+
if (typeof f !== "function") {
|
|
5178
|
+
throw new Error("First argument to map is not a function");
|
|
5179
|
+
}
|
|
5180
|
+
if (!Array.isArray(a)) {
|
|
5181
|
+
throw new Error("Second argument to map is not an array");
|
|
5182
|
+
}
|
|
5183
|
+
return a.map(function(x, i) {
|
|
5184
|
+
return f(x, i);
|
|
5185
|
+
});
|
|
5186
|
+
}
|
|
5187
|
+
function arrayFold(f, init, a) {
|
|
5188
|
+
if (typeof f !== "function") {
|
|
5189
|
+
throw new Error("First argument to fold is not a function");
|
|
5190
|
+
}
|
|
5191
|
+
if (!Array.isArray(a)) {
|
|
5192
|
+
throw new Error("Second argument to fold is not an array");
|
|
5193
|
+
}
|
|
5194
|
+
return a.reduce(function(acc, x, i) {
|
|
5195
|
+
return f(acc, x, i);
|
|
5196
|
+
}, init);
|
|
5197
|
+
}
|
|
5198
|
+
function arrayFilter(f, a) {
|
|
5199
|
+
if (typeof f !== "function") {
|
|
5200
|
+
throw new Error("First argument to filter is not a function");
|
|
5201
|
+
}
|
|
5202
|
+
if (!Array.isArray(a)) {
|
|
5203
|
+
throw new Error("Second argument to filter is not an array");
|
|
5204
|
+
}
|
|
5205
|
+
return a.filter(function(x, i) {
|
|
5206
|
+
return f(x, i);
|
|
5207
|
+
});
|
|
5208
|
+
}
|
|
5209
|
+
function stringOrArrayIndexOf(target, s) {
|
|
5210
|
+
if (!(Array.isArray(s) || typeof s === "string")) {
|
|
5211
|
+
throw new Error("Second argument to indexOf is not a string or array");
|
|
5212
|
+
}
|
|
5213
|
+
return s.indexOf(target);
|
|
5214
|
+
}
|
|
5215
|
+
function arrayJoin(sep, a) {
|
|
5216
|
+
if (!Array.isArray(a)) {
|
|
5217
|
+
throw new Error("Second argument to join is not an array");
|
|
5218
|
+
}
|
|
5219
|
+
return a.join(sep);
|
|
5220
|
+
}
|
|
5221
|
+
function sign(x) {
|
|
5222
|
+
return (x > 0) - (x < 0) || +x;
|
|
5223
|
+
}
|
|
5224
|
+
var ONE_THIRD = 1 / 3;
|
|
5225
|
+
function cbrt(x) {
|
|
5226
|
+
return x < 0 ? -Math.pow(-x, ONE_THIRD) : Math.pow(x, ONE_THIRD);
|
|
5227
|
+
}
|
|
5228
|
+
function expm1(x) {
|
|
5229
|
+
return Math.exp(x) - 1;
|
|
5230
|
+
}
|
|
5231
|
+
function log1p(x) {
|
|
5232
|
+
return Math.log(1 + x);
|
|
5233
|
+
}
|
|
5234
|
+
function log2(x) {
|
|
5235
|
+
return Math.log(x) / Math.LN2;
|
|
5236
|
+
}
|
|
5237
|
+
function Parser(options) {
|
|
5238
|
+
this.options = options || {};
|
|
5239
|
+
this.unaryOps = {
|
|
5240
|
+
sin: Math.sin,
|
|
5241
|
+
cos: Math.cos,
|
|
5242
|
+
tan: Math.tan,
|
|
5243
|
+
asin: Math.asin,
|
|
5244
|
+
acos: Math.acos,
|
|
5245
|
+
atan: Math.atan,
|
|
5246
|
+
sinh: Math.sinh || sinh,
|
|
5247
|
+
cosh: Math.cosh || cosh,
|
|
5248
|
+
tanh: Math.tanh || tanh,
|
|
5249
|
+
asinh: Math.asinh || asinh,
|
|
5250
|
+
acosh: Math.acosh || acosh,
|
|
5251
|
+
atanh: Math.atanh || atanh,
|
|
5252
|
+
sqrt: Math.sqrt,
|
|
5253
|
+
cbrt: Math.cbrt || cbrt,
|
|
5254
|
+
log: Math.log,
|
|
5255
|
+
log2: Math.log2 || log2,
|
|
5256
|
+
ln: Math.log,
|
|
5257
|
+
lg: Math.log10 || log10,
|
|
5258
|
+
log10: Math.log10 || log10,
|
|
5259
|
+
expm1: Math.expm1 || expm1,
|
|
5260
|
+
log1p: Math.log1p || log1p,
|
|
5261
|
+
abs: Math.abs,
|
|
5262
|
+
ceil: Math.ceil,
|
|
5263
|
+
floor: Math.floor,
|
|
5264
|
+
round: Math.round,
|
|
5265
|
+
trunc: Math.trunc || trunc,
|
|
5266
|
+
"-": neg,
|
|
5267
|
+
"+": Number,
|
|
5268
|
+
exp: Math.exp,
|
|
5269
|
+
not,
|
|
5270
|
+
length: stringOrArrayLength,
|
|
5271
|
+
"!": factorial,
|
|
5272
|
+
sign: Math.sign || sign
|
|
5273
|
+
};
|
|
5274
|
+
this.binaryOps = {
|
|
5275
|
+
"+": add,
|
|
5276
|
+
"-": sub,
|
|
5277
|
+
"*": mul,
|
|
5278
|
+
"/": div,
|
|
5279
|
+
"%": mod,
|
|
5280
|
+
"^": Math.pow,
|
|
5281
|
+
"||": concat,
|
|
5282
|
+
"==": equal,
|
|
5283
|
+
"!=": notEqual,
|
|
5284
|
+
">": greaterThan,
|
|
5285
|
+
"<": lessThan,
|
|
5286
|
+
">=": greaterThanEqual,
|
|
5287
|
+
"<=": lessThanEqual,
|
|
5288
|
+
and: andOperator,
|
|
5289
|
+
or: orOperator,
|
|
5290
|
+
"in": inOperator,
|
|
5291
|
+
"=": setVar,
|
|
5292
|
+
"[": arrayIndex
|
|
5293
|
+
};
|
|
5294
|
+
this.ternaryOps = {
|
|
5295
|
+
"?": condition
|
|
5296
|
+
};
|
|
5297
|
+
this.functions = {
|
|
5298
|
+
random,
|
|
5299
|
+
fac: factorial,
|
|
5300
|
+
min,
|
|
5301
|
+
max,
|
|
5302
|
+
hypot: Math.hypot || hypot,
|
|
5303
|
+
pyt: Math.hypot || hypot,
|
|
5304
|
+
// backward compat
|
|
5305
|
+
pow: Math.pow,
|
|
5306
|
+
atan2: Math.atan2,
|
|
5307
|
+
"if": condition,
|
|
5308
|
+
gamma,
|
|
5309
|
+
roundTo,
|
|
5310
|
+
map: arrayMap,
|
|
5311
|
+
fold: arrayFold,
|
|
5312
|
+
filter: arrayFilter,
|
|
5313
|
+
indexOf: stringOrArrayIndexOf,
|
|
5314
|
+
join: arrayJoin
|
|
5315
|
+
};
|
|
5316
|
+
this.consts = {
|
|
5317
|
+
E: Math.E,
|
|
5318
|
+
PI: Math.PI,
|
|
5319
|
+
"true": true,
|
|
5320
|
+
"false": false
|
|
5321
|
+
};
|
|
5322
|
+
}
|
|
5323
|
+
Parser.prototype.parse = function(expr) {
|
|
5324
|
+
var instr = [];
|
|
5325
|
+
var parserState = new ParserState(
|
|
5326
|
+
this,
|
|
5327
|
+
new TokenStream(this, expr),
|
|
5328
|
+
{ allowMemberAccess: this.options.allowMemberAccess }
|
|
5329
|
+
);
|
|
5330
|
+
parserState.parseExpression(instr);
|
|
5331
|
+
parserState.expect(TEOF, "EOF");
|
|
5332
|
+
return new Expression(instr, this);
|
|
5333
|
+
};
|
|
5334
|
+
Parser.prototype.evaluate = function(expr, variables) {
|
|
5335
|
+
return this.parse(expr).evaluate(variables);
|
|
5336
|
+
};
|
|
5337
|
+
var sharedParser = new Parser();
|
|
5338
|
+
Parser.parse = function(expr) {
|
|
5339
|
+
return sharedParser.parse(expr);
|
|
5340
|
+
};
|
|
5341
|
+
Parser.evaluate = function(expr, variables) {
|
|
5342
|
+
return sharedParser.parse(expr).evaluate(variables);
|
|
5343
|
+
};
|
|
5344
|
+
var optionNameMap = {
|
|
5345
|
+
"+": "add",
|
|
5346
|
+
"-": "subtract",
|
|
5347
|
+
"*": "multiply",
|
|
5348
|
+
"/": "divide",
|
|
5349
|
+
"%": "remainder",
|
|
5350
|
+
"^": "power",
|
|
5351
|
+
"!": "factorial",
|
|
5352
|
+
"<": "comparison",
|
|
5353
|
+
">": "comparison",
|
|
5354
|
+
"<=": "comparison",
|
|
5355
|
+
">=": "comparison",
|
|
5356
|
+
"==": "comparison",
|
|
5357
|
+
"!=": "comparison",
|
|
5358
|
+
"||": "concatenate",
|
|
5359
|
+
"and": "logical",
|
|
5360
|
+
"or": "logical",
|
|
5361
|
+
"not": "logical",
|
|
5362
|
+
"?": "conditional",
|
|
5363
|
+
":": "conditional",
|
|
5364
|
+
"=": "assignment",
|
|
5365
|
+
"[": "array",
|
|
5366
|
+
"()=": "fndef"
|
|
5367
|
+
};
|
|
5368
|
+
function getOptionName(op) {
|
|
5369
|
+
return optionNameMap.hasOwnProperty(op) ? optionNameMap[op] : op;
|
|
5370
|
+
}
|
|
5371
|
+
Parser.prototype.isOperatorEnabled = function(op) {
|
|
5372
|
+
var optionName = getOptionName(op);
|
|
5373
|
+
var operators2 = this.options.operators || {};
|
|
5374
|
+
return !(optionName in operators2) || !!operators2[optionName];
|
|
5375
|
+
};
|
|
5376
|
+
const calc = (expression, context) => {
|
|
5377
|
+
if (typeof expression !== "string") {
|
|
5378
|
+
return expression;
|
|
5379
|
+
}
|
|
5380
|
+
let processedExpression = expression;
|
|
5381
|
+
try {
|
|
5382
|
+
const pathResolver = (path) => {
|
|
5383
|
+
let currentPath = path;
|
|
5384
|
+
let value;
|
|
5385
|
+
let depth = 0;
|
|
5386
|
+
while (typeof currentPath === "string" && (currentPath.startsWith("/") || currentPath.startsWith("=/")) && depth < 5) {
|
|
5387
|
+
const normalizedPath = currentPath.startsWith("/") ? "=" + currentPath : currentPath;
|
|
5388
|
+
const resolved = resolvePath(normalizedPath, context);
|
|
5389
|
+
value = unwrapSignal(resolved);
|
|
5390
|
+
if (typeof value === "string" && (value.startsWith("/") || value.startsWith("=/")) && value !== currentPath) {
|
|
5391
|
+
currentPath = value;
|
|
5392
|
+
depth++;
|
|
5393
|
+
} else {
|
|
5394
|
+
break;
|
|
5395
|
+
}
|
|
5396
|
+
}
|
|
5397
|
+
if (typeof value === "number") return value;
|
|
5398
|
+
if (typeof value === "string") {
|
|
5399
|
+
const num = parseFloat(value);
|
|
5400
|
+
if (!isNaN(num) && isFinite(Number(value))) return num;
|
|
5401
|
+
return value === "" ? 0 : `"${value.replace(/"/g, '\\"')}"`;
|
|
5402
|
+
}
|
|
5403
|
+
return value === void 0 || value === null ? 0 : value;
|
|
5404
|
+
};
|
|
5405
|
+
const pathRegex = /\$\(\s*['"](.*?)['"]\s*\)/g;
|
|
5406
|
+
processedExpression = expression.replace(pathRegex, (match2, path) => {
|
|
5407
|
+
const val = pathResolver(path);
|
|
5408
|
+
return val;
|
|
5409
|
+
});
|
|
5410
|
+
const parser = new Parser();
|
|
5411
|
+
const parsed = parser.parse(processedExpression);
|
|
5412
|
+
return parsed.evaluate();
|
|
5413
|
+
} catch (error) {
|
|
5414
|
+
console.error("JPRX calc error:", error.message);
|
|
5415
|
+
console.error("Original expression:", expression);
|
|
5416
|
+
console.error("Processed expression:", processedExpression);
|
|
5417
|
+
return NaN;
|
|
5418
|
+
}
|
|
5419
|
+
};
|
|
5420
|
+
const registerCalcHelpers = (register) => {
|
|
5421
|
+
register("calc", calc, { pathAware: true });
|
|
5422
|
+
};
|
|
5423
|
+
registerMathHelpers(registerHelper);
|
|
5424
|
+
registerLogicHelpers(registerHelper);
|
|
5425
|
+
registerStringHelpers(registerHelper);
|
|
5426
|
+
registerArrayHelpers(registerHelper);
|
|
5427
|
+
registerCompareHelpers(registerHelper);
|
|
5428
|
+
registerConditionalHelpers(registerHelper);
|
|
5429
|
+
registerDateTimeHelpers(registerHelper);
|
|
5430
|
+
registerFormatHelpers(registerHelper);
|
|
5431
|
+
registerLookupHelpers(registerHelper);
|
|
5432
|
+
registerStatsHelpers(registerHelper);
|
|
5433
|
+
registerStateHelpers((name, fn) => registerHelper(name, fn, { pathAware: true }));
|
|
5434
|
+
registerNetworkHelpers(registerHelper);
|
|
5435
|
+
registerCalcHelpers(registerHelper);
|
|
5436
|
+
registerHelper("move", (selector, location = "beforeend") => {
|
|
5437
|
+
return {
|
|
5438
|
+
isLazy: true,
|
|
5439
|
+
resolve: (eventOrNode) => {
|
|
5440
|
+
const isEvent = eventOrNode && typeof eventOrNode === "object" && "target" in eventOrNode;
|
|
5441
|
+
const node = isEvent ? eventOrNode.currentTarget || eventOrNode.target : eventOrNode;
|
|
5442
|
+
if (!(node instanceof Node) || !selector) return;
|
|
5443
|
+
const target = document.querySelector(selector);
|
|
5444
|
+
if (!target) {
|
|
5445
|
+
console.warn(`[Lightview-CDOM] move target not found: ${selector}`);
|
|
5446
|
+
return;
|
|
5447
|
+
}
|
|
5448
|
+
if (node.id) {
|
|
5449
|
+
const escapedId = CSS.escape(node.id);
|
|
5450
|
+
if (target.id === node.id && target !== node) {
|
|
5451
|
+
target.replaceWith(node);
|
|
5452
|
+
return;
|
|
5453
|
+
}
|
|
5454
|
+
const existing = target.querySelector(`#${escapedId}`);
|
|
5455
|
+
if (existing && existing !== node) {
|
|
5456
|
+
existing.replaceWith(node);
|
|
5457
|
+
return;
|
|
5458
|
+
}
|
|
5459
|
+
}
|
|
5460
|
+
globalThis.Lightview.$(target).content(node, location);
|
|
5461
|
+
}
|
|
5462
|
+
};
|
|
5463
|
+
}, { pathAware: true });
|
|
5464
|
+
registerHelper("mount", async (url, options = {}) => {
|
|
5465
|
+
const { target = "body", location = "beforeend" } = options;
|
|
5466
|
+
try {
|
|
5467
|
+
const fetchOptions = { ...options };
|
|
5468
|
+
delete fetchOptions.target;
|
|
5469
|
+
delete fetchOptions.location;
|
|
5470
|
+
const headers = { ...fetchOptions.headers };
|
|
5471
|
+
let body = fetchOptions.body;
|
|
5472
|
+
if (body !== void 0) {
|
|
5473
|
+
if (body !== null && typeof body === "object") {
|
|
5474
|
+
body = JSON.stringify(body);
|
|
5475
|
+
if (!headers["Content-Type"]) headers["Content-Type"] = "application/json";
|
|
5476
|
+
} else {
|
|
5477
|
+
body = String(body);
|
|
5478
|
+
if (!headers["Content-Type"]) headers["Content-Type"] = "text/plain";
|
|
5479
|
+
}
|
|
5480
|
+
fetchOptions.body = body;
|
|
5481
|
+
fetchOptions.headers = headers;
|
|
5482
|
+
}
|
|
5483
|
+
const response = await globalThis.fetch(url, fetchOptions);
|
|
5484
|
+
const contentType = response.headers.get("Content-Type") || "";
|
|
5485
|
+
const text = await response.text();
|
|
5486
|
+
let content = text;
|
|
5487
|
+
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");
|
|
5488
|
+
if (isCDOM || contentType.includes("application/json") && text.trim().startsWith("{")) {
|
|
5489
|
+
try {
|
|
5490
|
+
content = hydrate(parseJPRX(text));
|
|
5491
|
+
} catch (e) {
|
|
5492
|
+
}
|
|
5493
|
+
}
|
|
5494
|
+
const targetEl = document.querySelector(target);
|
|
5495
|
+
if (targetEl) {
|
|
5496
|
+
globalThis.Lightview.$(targetEl).content(content, location);
|
|
5497
|
+
} else {
|
|
5498
|
+
console.warn(`[Lightview-CDOM] $mount target not found: ${target}`);
|
|
5499
|
+
}
|
|
5500
|
+
} catch (err) {
|
|
5501
|
+
console.error(`[Lightview-CDOM] $mount failed for ${url}:`, err);
|
|
5502
|
+
}
|
|
5503
|
+
});
|
|
5504
|
+
registerOperator("increment", "++", "prefix", 80);
|
|
5505
|
+
registerOperator("increment", "++", "postfix", 80);
|
|
5506
|
+
registerOperator("decrement", "--", "prefix", 80);
|
|
5507
|
+
registerOperator("decrement", "--", "postfix", 80);
|
|
5508
|
+
registerOperator("toggle", "!!", "prefix", 80);
|
|
5509
|
+
registerOperator("+", "+", "infix", 50);
|
|
5510
|
+
registerOperator("-", "-", "infix", 50);
|
|
5511
|
+
registerOperator("*", "*", "infix", 60);
|
|
5512
|
+
registerOperator("/", "/", "infix", 60);
|
|
5513
|
+
registerOperator("gt", ">", "infix", 40);
|
|
5514
|
+
registerOperator("lt", "<", "infix", 40);
|
|
5515
|
+
registerOperator("gte", ">=", "infix", 40);
|
|
5516
|
+
registerOperator("lte", "<=", "infix", 40);
|
|
5517
|
+
registerOperator("neq", "!=", "infix", 40);
|
|
5518
|
+
const getContext = (node, event = null) => {
|
|
5519
|
+
return new Proxy({}, {
|
|
5520
|
+
get(_, prop) {
|
|
5521
|
+
if (prop === "$event" || prop === "event") return event;
|
|
5522
|
+
if (prop === "$this" || prop === "this" || prop === "__node__") return node;
|
|
5523
|
+
return unwrapSignal(globalThis.Lightview.getState(prop, { scope: node }));
|
|
5524
|
+
},
|
|
5525
|
+
set(_, prop, value) {
|
|
5526
|
+
const res = globalThis.Lightview.getState(prop, { scope: node });
|
|
5527
|
+
if (res && (typeof res === "object" || typeof res === "function") && "value" in res) {
|
|
5528
|
+
res.value = value;
|
|
5529
|
+
return true;
|
|
5530
|
+
}
|
|
5531
|
+
return false;
|
|
5532
|
+
}
|
|
5533
|
+
});
|
|
5534
|
+
};
|
|
5535
|
+
globalThis.Lightview.hooks.processAttribute = (domNode, key, value) => {
|
|
5536
|
+
if (value == null ? void 0 : value.__JPRX_BIND__) {
|
|
5537
|
+
const { path, options } = value;
|
|
5538
|
+
const type = domNode.type || "";
|
|
5539
|
+
const tagName = domNode.tagName.toLowerCase();
|
|
5540
|
+
let prop = "value";
|
|
5541
|
+
let event = "input";
|
|
5542
|
+
if (type === "checkbox" || type === "radio") {
|
|
5543
|
+
prop = "checked";
|
|
5544
|
+
event = "change";
|
|
5545
|
+
} else if (tagName === "select") {
|
|
5546
|
+
event = "change";
|
|
5547
|
+
}
|
|
5548
|
+
const res = globalThis.Lightview.get(path.replace(/^=/, ""), { scope: domNode });
|
|
5549
|
+
const runner = globalThis.Lightview.effect(() => {
|
|
5550
|
+
const val = unwrapSignal(res);
|
|
5551
|
+
if (domNode[prop] !== val) {
|
|
5552
|
+
domNode[prop] = val === void 0 ? "" : val;
|
|
5553
|
+
}
|
|
5554
|
+
});
|
|
5555
|
+
globalThis.Lightview.internals.trackEffect(domNode, runner);
|
|
5556
|
+
domNode.addEventListener(event, () => {
|
|
5557
|
+
if (res && "value" in res) res.value = domNode[prop];
|
|
5558
|
+
});
|
|
5559
|
+
return unwrapSignal(res) ?? domNode[prop];
|
|
5560
|
+
}
|
|
5561
|
+
return void 0;
|
|
5562
|
+
};
|
|
5563
|
+
const activate = (root = document.body) => {
|
|
5564
|
+
};
|
|
5565
|
+
const makeEventHandler = (expr) => (eventOrNode) => {
|
|
5566
|
+
const isEvent = eventOrNode && typeof eventOrNode === "object" && "target" in eventOrNode;
|
|
5567
|
+
const target = isEvent ? eventOrNode.currentTarget || eventOrNode.target : eventOrNode;
|
|
5568
|
+
const context = getContext(target, isEvent ? eventOrNode : null);
|
|
5569
|
+
const result = resolveExpression$1(expr, context);
|
|
5570
|
+
if (result && typeof result === "object" && result.isLazy) return result.resolve(context);
|
|
5571
|
+
return result;
|
|
5572
|
+
};
|
|
5573
|
+
const hydrate = (node, parent = null) => {
|
|
5574
|
+
var _a2, _b2, _c;
|
|
5575
|
+
if (!node) return node;
|
|
5576
|
+
if (typeof node === "string" && node.startsWith("'=")) {
|
|
5577
|
+
return node.slice(1);
|
|
5578
|
+
}
|
|
5579
|
+
if (typeof node === "string" && node.startsWith("=")) {
|
|
5580
|
+
return parseExpression(node, parent);
|
|
5581
|
+
}
|
|
5582
|
+
if (typeof node !== "object") return node;
|
|
5583
|
+
if (Array.isArray(node)) {
|
|
5584
|
+
return node.map((item) => hydrate(item, parent));
|
|
5585
|
+
}
|
|
5586
|
+
if (node instanceof String) return node.toString();
|
|
5587
|
+
if (parent && !("__parent__" in node)) {
|
|
5588
|
+
Object.defineProperty(node, "__parent__", { value: parent, enumerable: false, writable: true });
|
|
5589
|
+
(_c = (_b2 = (_a2 = globalThis.Lightview) == null ? void 0 : _a2.internals) == null ? void 0 : _b2.parents) == null ? void 0 : _c.set(node, parent);
|
|
5590
|
+
}
|
|
5591
|
+
if (!node.tag) {
|
|
5592
|
+
let potentialTag = null;
|
|
5593
|
+
const reserved = ["children", "attributes", "tag", "__parent__"];
|
|
5594
|
+
for (const key in node) {
|
|
5595
|
+
if (reserved.includes(key) || key.startsWith("on")) continue;
|
|
5596
|
+
potentialTag = key;
|
|
5597
|
+
break;
|
|
5598
|
+
}
|
|
5599
|
+
if (potentialTag) {
|
|
5600
|
+
const content = node[potentialTag];
|
|
5601
|
+
node.tag = potentialTag;
|
|
5602
|
+
if (Array.isArray(content)) {
|
|
5603
|
+
node.children = content;
|
|
5604
|
+
} else if (typeof content === "object") {
|
|
5605
|
+
node.attributes = node.attributes || {};
|
|
5606
|
+
for (const k in content) {
|
|
5607
|
+
if (k === "children") node.children = content[k];
|
|
5608
|
+
else node.attributes[k] = content[k];
|
|
5609
|
+
}
|
|
5610
|
+
} else node.children = [content];
|
|
5611
|
+
delete node[potentialTag];
|
|
5612
|
+
}
|
|
5613
|
+
}
|
|
5614
|
+
for (const key in node) {
|
|
5615
|
+
if (key === "tag" || key === "__parent__") continue;
|
|
5616
|
+
const value = node[key];
|
|
5617
|
+
if (key === "attributes" && typeof value === "object" && value !== null) {
|
|
5618
|
+
for (const attrKey in value) {
|
|
5619
|
+
const attrVal = value[attrKey];
|
|
5620
|
+
if (typeof attrVal === "string" && attrVal.startsWith("'=")) {
|
|
5621
|
+
value[attrKey] = attrVal.slice(1);
|
|
5622
|
+
} else if (typeof attrVal === "string" && attrVal.startsWith("=")) {
|
|
5623
|
+
if (attrKey.startsWith("on")) {
|
|
5624
|
+
value[attrKey] = makeEventHandler(attrVal);
|
|
5625
|
+
} else {
|
|
5626
|
+
value[attrKey] = parseExpression(attrVal, node);
|
|
5627
|
+
}
|
|
5628
|
+
} else if (typeof attrVal === "object" && attrVal !== null) {
|
|
5629
|
+
value[attrKey] = hydrate(attrVal, node);
|
|
5630
|
+
}
|
|
5631
|
+
}
|
|
5632
|
+
continue;
|
|
5633
|
+
}
|
|
5634
|
+
if (typeof value === "string" && value.startsWith("'=")) {
|
|
5635
|
+
node[key] = value.slice(1);
|
|
5636
|
+
} else if (typeof value === "string" && value.startsWith("=")) {
|
|
5637
|
+
if (key === "onmount" || key === "onunmount" || key.startsWith("on")) {
|
|
5638
|
+
node[key] = makeEventHandler(value);
|
|
5639
|
+
} else if (key === "children") {
|
|
5640
|
+
node[key] = [parseExpression(value, node)];
|
|
5641
|
+
} else {
|
|
5642
|
+
node[key] = parseExpression(value, node);
|
|
5643
|
+
}
|
|
5644
|
+
} else {
|
|
5645
|
+
node[key] = hydrate(value, node);
|
|
5646
|
+
}
|
|
5647
|
+
}
|
|
5648
|
+
return node;
|
|
5649
|
+
};
|
|
5650
|
+
const LightviewCDOM = {
|
|
5651
|
+
registerHelper,
|
|
5652
|
+
registerOperator,
|
|
3767
5653
|
parseExpression,
|
|
3768
5654
|
resolvePath,
|
|
3769
5655
|
resolvePathAsContext,
|
|
3770
|
-
resolveExpression,
|
|
5656
|
+
resolveExpression: resolveExpression$1,
|
|
3771
5657
|
parseCDOMC,
|
|
3772
5658
|
parseJPRX,
|
|
3773
5659
|
unwrapSignal,
|
|
3774
5660
|
getContext,
|
|
3775
|
-
handleCDOMState
|
|
3776
|
-
|
|
5661
|
+
handleCDOMState: () => {
|
|
5662
|
+
},
|
|
5663
|
+
handleCDOMBind: () => {
|
|
5664
|
+
},
|
|
3777
5665
|
activate,
|
|
3778
5666
|
hydrate,
|
|
3779
5667
|
version: "1.0.0"
|