@xpell/core 2.0.0-alpha.10
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/CHANGELOG.md +83 -0
- package/LICENSE +21 -0
- package/README.md +96 -0
- package/dist/XCommand.d.ts +84 -0
- package/dist/XConst.d.ts +28 -0
- package/dist/XData.d.ts +51 -0
- package/dist/XError.d.ts +34 -0
- package/dist/XEventManager.d.ts +57 -0
- package/dist/XLogger.d.ts +32 -0
- package/dist/XModule.d.ts +161 -0
- package/dist/XNanoCommands.d.ts +42 -0
- package/dist/XObject.d.ts +287 -0
- package/dist/XObjectManager.d.ts +96 -0
- package/dist/XParams.d.ts +60 -0
- package/dist/XParser.d.ts +77 -0
- package/dist/XProtocol.d.ts +56 -0
- package/dist/XUtils.d.ts +100 -0
- package/dist/Xpell.d.ts +142 -0
- package/dist/index.d.ts +9 -0
- package/dist/xpell-core.cjs.js +3 -0
- package/dist/xpell-core.es.js +1428 -0
- package/docs/Codex.md +138 -0
- package/docs/XData 2.md +209 -0
- package/docs/api/.nojekyll +1 -0
- package/docs/api/assets/hierarchy.js +1 -0
- package/docs/api/assets/highlight.css +71 -0
- package/docs/api/assets/icons.js +18 -0
- package/docs/api/assets/icons.svg +1 -0
- package/docs/api/assets/main.js +60 -0
- package/docs/api/assets/navigation.js +1 -0
- package/docs/api/assets/search.js +1 -0
- package/docs/api/assets/style.css +1611 -0
- package/docs/api/classes/XCommand.html +23 -0
- package/docs/api/classes/XModule.html +57 -0
- package/docs/api/classes/XObject.html +133 -0
- package/docs/api/classes/XObjectManager.html +36 -0
- package/docs/api/classes/XObjectPack.html +6 -0
- package/docs/api/classes/XParams.html +8 -0
- package/docs/api/classes/XParser.html +21 -0
- package/docs/api/classes/XUtils.html +29 -0
- package/docs/api/classes/XpellEngine.html +36 -0
- package/docs/api/classes/_XData.html +23 -0
- package/docs/api/classes/_XEventManager.html +37 -0
- package/docs/api/classes/_XLogger.html +17 -0
- package/docs/api/hierarchy.html +1 -0
- package/docs/api/index.html +3 -0
- package/docs/api/interfaces/IXData.html +1 -0
- package/docs/api/interfaces/IXObjectData.html +17 -0
- package/docs/api/interfaces/XDataXporterHandler.html +1 -0
- package/docs/api/interfaces/XEventListener.html +6 -0
- package/docs/api/interfaces/XNanoCommand.html +2 -0
- package/docs/api/interfaces/XObjectOnEventIndex.html +1 -0
- package/docs/api/types/HTMLEventListenersIndex.html +1 -0
- package/docs/api/types/XCommandData.html +1 -0
- package/docs/api/types/XDataObject.html +1 -0
- package/docs/api/types/XDataVariable.html +1 -0
- package/docs/api/types/XDataXporter.html +1 -0
- package/docs/api/types/XEvent.html +1 -0
- package/docs/api/types/XEventListenerOptions.html +1 -0
- package/docs/api/types/XModuleData.html +1 -0
- package/docs/api/types/XNanoCommandPack.html +2 -0
- package/docs/api/types/XObjectData.html +1 -0
- package/docs/api/types/XObjectOnEventHandler.html +1 -0
- package/docs/api/variables/XData.html +1 -0
- package/docs/api/variables/XEventManager.html +1 -0
- package/docs/api/variables/XLogger.html +1 -0
- package/docs/api/variables/Xpell.html +3 -0
- package/docs/architecture/overview.md +190 -0
- package/package.json +66 -0
|
@@ -0,0 +1,1428 @@
|
|
|
1
|
+
class X {
|
|
2
|
+
/**
|
|
3
|
+
* Create ignore list for parser to ignore spell words
|
|
4
|
+
* @param list - comma-separated list of words
|
|
5
|
+
* @param reservedWords - base reserved words map (mutated)
|
|
6
|
+
*/
|
|
7
|
+
createIgnoreList(t, e) {
|
|
8
|
+
if (!t) return e;
|
|
9
|
+
const s = t.split(",").map((i) => i.trim()).filter(Boolean);
|
|
10
|
+
for (const i of s) e[i] = "";
|
|
11
|
+
return e;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* GUID / UUID v4 (cross-platform)
|
|
15
|
+
*
|
|
16
|
+
* Preference order:
|
|
17
|
+
* 1) globalThis.crypto.randomUUID()
|
|
18
|
+
* 2) globalThis.crypto.getRandomValues() (RFC4122 v4)
|
|
19
|
+
* 3) Math.random() fallback (NOT crypto-secure, legacy fallback only)
|
|
20
|
+
*/
|
|
21
|
+
guid() {
|
|
22
|
+
const e = globalThis.crypto;
|
|
23
|
+
if (e && typeof e.randomUUID == "function")
|
|
24
|
+
return e.randomUUID();
|
|
25
|
+
if (e && typeof e.getRandomValues == "function") {
|
|
26
|
+
const r = new Uint8Array(16);
|
|
27
|
+
e.getRandomValues(r), r[6] = r[6] & 15 | 64, r[8] = r[8] & 63 | 128;
|
|
28
|
+
const a = Array.from(r, (c) => c.toString(16).padStart(2, "0"));
|
|
29
|
+
return a.slice(0, 4).join("") + "-" + a.slice(4, 6).join("") + "-" + a.slice(6, 8).join("") + "-" + a.slice(8, 10).join("") + "-" + a.slice(10, 16).join("");
|
|
30
|
+
}
|
|
31
|
+
const s = "0123456789abcdef".split(""), i = [];
|
|
32
|
+
let n;
|
|
33
|
+
i[8] = i[13] = i[18] = i[23] = "-", i[14] = "4";
|
|
34
|
+
for (let r = 0; r < 36; r++)
|
|
35
|
+
i[r] || (n = (0 | Math.random() * 16) >>> 0, i[r] = s[r === 19 ? n & 3 | 8 : n & 15]);
|
|
36
|
+
return i.join("");
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Merge defaults into data object (mutates data)
|
|
40
|
+
* @param data - target data
|
|
41
|
+
* @param defaults - defaults object
|
|
42
|
+
* @param force - overwrite existing values
|
|
43
|
+
*/
|
|
44
|
+
mergeDefaultsWithData(t, e, s = !1) {
|
|
45
|
+
if (!t) return e;
|
|
46
|
+
t._id || (t._id = t.id ?? this.guid());
|
|
47
|
+
for (const i of Object.keys(e))
|
|
48
|
+
(!(i in t) || s) && (t[i] = e[i]);
|
|
49
|
+
return t;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Encode string to Base64 (UTF-8 safe, cross-platform)
|
|
53
|
+
*/
|
|
54
|
+
encode(t) {
|
|
55
|
+
const e = globalThis;
|
|
56
|
+
if (typeof e.btoa == "function") {
|
|
57
|
+
const s = encodeURIComponent(String(t)).replace(
|
|
58
|
+
/%([0-9A-F]{2})/g,
|
|
59
|
+
(i, n) => String.fromCharCode(parseInt(n, 16))
|
|
60
|
+
);
|
|
61
|
+
return e.btoa(s);
|
|
62
|
+
}
|
|
63
|
+
if (e.Buffer && typeof e.Buffer.from == "function")
|
|
64
|
+
return e.Buffer.from(String(t), "utf8").toString("base64");
|
|
65
|
+
throw new Error("Base64 encode not supported in this environment");
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Decode Base64 string to UTF-8 (cross-platform)
|
|
69
|
+
*/
|
|
70
|
+
decode(t) {
|
|
71
|
+
const e = globalThis;
|
|
72
|
+
if (typeof e.atob == "function") {
|
|
73
|
+
const s = e.atob(String(t)), i = Array.prototype.map.call(s, (n) => "%" + n.charCodeAt(0).toString(16).padStart(2, "0")).join("");
|
|
74
|
+
return decodeURIComponent(i);
|
|
75
|
+
}
|
|
76
|
+
if (e.Buffer && typeof e.Buffer.from == "function")
|
|
77
|
+
return e.Buffer.from(String(t), "base64").toString("utf8");
|
|
78
|
+
throw new Error("Base64 decode not supported in this environment");
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Returns a random integer between min and max (inclusive)
|
|
82
|
+
* NOTE: Not cryptographically secure (OK for UI, NOT for IDs)
|
|
83
|
+
*/
|
|
84
|
+
getRandomInt(t, e) {
|
|
85
|
+
return t = Math.ceil(t), e = Math.floor(e), Math.floor(Math.random() * (e - t + 1)) + t;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Extract parameter from XCommand
|
|
89
|
+
*/
|
|
90
|
+
getParam(t, e, s = 0) {
|
|
91
|
+
return t?._params?.[e] ?? s;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Default frame scheduler (cross-platform)
|
|
95
|
+
* - Browser: requestAnimationFrame
|
|
96
|
+
* - Node / non-DOM: setImmediate (fast) or setTimeout (paced by target fps)
|
|
97
|
+
*/
|
|
98
|
+
createDefaultScheduler(t) {
|
|
99
|
+
const e = globalThis;
|
|
100
|
+
if (typeof e.requestAnimationFrame == "function")
|
|
101
|
+
return (n) => e.requestAnimationFrame(n);
|
|
102
|
+
const s = typeof t == "number" && isFinite(t) && t > 0 ? t : 60;
|
|
103
|
+
if (typeof e.setImmediate == "function" && (!t || t >= 60))
|
|
104
|
+
return (n) => e.setImmediate(n);
|
|
105
|
+
const i = Math.max(1, Math.round(1e3 / s));
|
|
106
|
+
return (n) => e.setTimeout(n, i);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const p = new X();
|
|
110
|
+
class k {
|
|
111
|
+
#t = 0;
|
|
112
|
+
// displayed fps (stable)
|
|
113
|
+
#e = 0;
|
|
114
|
+
// EMA of ms/frame
|
|
115
|
+
#s = 0;
|
|
116
|
+
#i;
|
|
117
|
+
// weight of new samples (0..1)
|
|
118
|
+
#n;
|
|
119
|
+
// minimum integer change to update displayed fps
|
|
120
|
+
constructor(t = 0.05, e = 1) {
|
|
121
|
+
const s = Number(t);
|
|
122
|
+
this.#i = Number.isFinite(s) ? Math.min(1, Math.max(1e-3, s)) : 0.05;
|
|
123
|
+
const i = Number(e);
|
|
124
|
+
this.#n = Number.isFinite(i) ? Math.max(0, Math.floor(i)) : 1;
|
|
125
|
+
}
|
|
126
|
+
now() {
|
|
127
|
+
const t = globalThis.performance;
|
|
128
|
+
return t && typeof t.now == "function" ? t.now() : Date.now();
|
|
129
|
+
}
|
|
130
|
+
calc() {
|
|
131
|
+
const t = this.now();
|
|
132
|
+
if (this.#s === 0)
|
|
133
|
+
return this.#s = t, this.#t;
|
|
134
|
+
const e = t - this.#s;
|
|
135
|
+
if (this.#s = t, !Number.isFinite(e) || e <= 0) return this.#t;
|
|
136
|
+
this.#e === 0 ? this.#e = e : this.#e = (1 - this.#i) * this.#e + this.#i * e;
|
|
137
|
+
const s = 1e3 / this.#e;
|
|
138
|
+
if (!Number.isFinite(s) || s <= 0) return this.#t;
|
|
139
|
+
const i = Math.round(s);
|
|
140
|
+
return this.#t !== 0 && this.#n > 0 && Math.abs(i - this.#t) < this.#n ? this.#t : (this.#t = i, this.#t);
|
|
141
|
+
}
|
|
142
|
+
reset() {
|
|
143
|
+
this.#t = 0, this.#e = 0, this.#s = 0;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
class F {
|
|
147
|
+
constructor(t) {
|
|
148
|
+
this._enabled = !0, this._show_date = !1, this._show_time = !0, this._debug = !1, t && this.configure(t);
|
|
149
|
+
}
|
|
150
|
+
configure(t) {
|
|
151
|
+
typeof t._enabled == "boolean" && (this._enabled = t._enabled), typeof t._show_date == "boolean" && (this._show_date = t._show_date), typeof t._show_time == "boolean" && (this._show_time = t._show_time), typeof t._debug == "boolean" && (this._debug = t._debug);
|
|
152
|
+
}
|
|
153
|
+
_dt() {
|
|
154
|
+
const t = /* @__PURE__ */ new Date(), e = this._show_date ? `${t.getDate()}.${t.getMonth()}.${t.getFullYear()} ` : "", s = this._show_time ? `${t.getHours()}:${t.getMinutes()}:${t.getSeconds()}.${t.getMilliseconds()}|` : "";
|
|
155
|
+
return e + s;
|
|
156
|
+
}
|
|
157
|
+
log(t, ...e) {
|
|
158
|
+
this._enabled && console.log(this._dt(), t, ...e);
|
|
159
|
+
}
|
|
160
|
+
warn(t, ...e) {
|
|
161
|
+
this._enabled && console.warn(this._dt(), t, ...e);
|
|
162
|
+
}
|
|
163
|
+
error(t, ...e) {
|
|
164
|
+
this._enabled && console.error(this._dt(), t, ...e);
|
|
165
|
+
}
|
|
166
|
+
debug(t, ...e) {
|
|
167
|
+
!this._enabled || !this._debug || console.debug(this._dt(), t, ...e);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
const _ = new F(), x = typeof process < "u" && !!process?.env && process.env.NODE_ENV === "production";
|
|
171
|
+
x || console.info(
|
|
172
|
+
"[Xpell] _xlog is redirected to console in development mode. Tip: enable 'Show timestamps' in DevTools → Console for timed logs."
|
|
173
|
+
);
|
|
174
|
+
const y = x ? _ : console;
|
|
175
|
+
class S {
|
|
176
|
+
constructor() {
|
|
177
|
+
this._objects = {}, this._listeners = /* @__PURE__ */ new Map(), this._any_listeners = /* @__PURE__ */ new Set(), this._compat_writes = !0, this._warn_legacy_writes = !0, this._verbose = !1, this._compat_legacy_keys = !0, this._o_proxy = null, this._objects = {};
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Shared memory view.
|
|
181
|
+
* Reads are always supported.
|
|
182
|
+
* Writes are supported in compat mode (optional) and should be migrated to set()/delete()/touch().
|
|
183
|
+
*/
|
|
184
|
+
get _o() {
|
|
185
|
+
return !this._compat_writes && !this._warn_legacy_writes ? this._objects : (this._o_proxy || (this._o_proxy = new Proxy(this._objects, {
|
|
186
|
+
set: (t, e, s) => {
|
|
187
|
+
const i = String(e);
|
|
188
|
+
return this._warn_legacy_writes && console.warn(
|
|
189
|
+
`[XData] Legacy write: _o["${i}"] = ... ; prefer XData.set("${i}", value).`
|
|
190
|
+
), this._compat_writes ? this.set(i, s, { source: "legacy:_o" }) : t[i] = s, !0;
|
|
191
|
+
},
|
|
192
|
+
deleteProperty: (t, e) => {
|
|
193
|
+
const s = String(e);
|
|
194
|
+
return this._warn_legacy_writes && console.warn(
|
|
195
|
+
`[XData] Legacy delete: delete _o["${s}"] ; prefer XData.delete("${s}").`
|
|
196
|
+
), this._compat_writes ? this.delete(s, { source: "legacy:_o" }) : delete t[s], !0;
|
|
197
|
+
}
|
|
198
|
+
})), this._o_proxy);
|
|
199
|
+
}
|
|
200
|
+
/** Preferred read API */
|
|
201
|
+
get(t) {
|
|
202
|
+
return this._objects[t];
|
|
203
|
+
}
|
|
204
|
+
/** Preferred write API */
|
|
205
|
+
set(t, e, s) {
|
|
206
|
+
const i = this._objects[t];
|
|
207
|
+
this._objects[t] = e, this._emit({ key: t, value: e, prev: i, ts: Date.now(), op: "set", meta: s });
|
|
208
|
+
}
|
|
209
|
+
/** Shallow merge helper (nice for state objects) */
|
|
210
|
+
patch(t, e, s) {
|
|
211
|
+
const i = this._objects[t], r = { ...i && typeof i == "object" ? i : {}, ...e };
|
|
212
|
+
this._objects[t] = r, this._emit({ key: t, value: r, prev: i, ts: Date.now(), op: "patch", meta: s });
|
|
213
|
+
}
|
|
214
|
+
/** In-place mutation notifier */
|
|
215
|
+
touch(t, e) {
|
|
216
|
+
const s = this._objects[t];
|
|
217
|
+
this._emit({ key: t, value: s, prev: s, ts: Date.now(), op: "touch", meta: e });
|
|
218
|
+
}
|
|
219
|
+
has(t) {
|
|
220
|
+
return Object.prototype.hasOwnProperty.call(this._objects, t);
|
|
221
|
+
}
|
|
222
|
+
delete(t, e) {
|
|
223
|
+
const s = this._objects[t];
|
|
224
|
+
delete this._objects[t], this._emit({ key: t, value: void 0, prev: s, ts: Date.now(), op: "delete", meta: e });
|
|
225
|
+
}
|
|
226
|
+
pick(t, e) {
|
|
227
|
+
const s = this._objects[t];
|
|
228
|
+
return this.delete(t, e), s;
|
|
229
|
+
}
|
|
230
|
+
clean() {
|
|
231
|
+
this._objects = {};
|
|
232
|
+
}
|
|
233
|
+
// ----------------------------
|
|
234
|
+
// Subscriptions
|
|
235
|
+
// ----------------------------
|
|
236
|
+
on(t, e) {
|
|
237
|
+
let s = this._listeners.get(t);
|
|
238
|
+
return s || this._listeners.set(t, s = /* @__PURE__ */ new Set()), s.add(e), () => this.off(t, e);
|
|
239
|
+
}
|
|
240
|
+
off(t, e) {
|
|
241
|
+
const s = this._listeners.get(t);
|
|
242
|
+
s && (s.delete(e), s.size === 0 && this._listeners.delete(t));
|
|
243
|
+
}
|
|
244
|
+
onAny(t) {
|
|
245
|
+
return this._any_listeners.add(t), () => this._any_listeners.delete(t);
|
|
246
|
+
}
|
|
247
|
+
// ----------------------------
|
|
248
|
+
// Emit
|
|
249
|
+
// ----------------------------
|
|
250
|
+
_emit(t) {
|
|
251
|
+
this._verbose && t.meta?.trace && (t.stack = new Error().stack);
|
|
252
|
+
const e = this._listeners.get(t.key);
|
|
253
|
+
if (e) for (const s of e) s(t);
|
|
254
|
+
for (const s of this._any_listeners) s(t);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
const u = new S();
|
|
258
|
+
class M {
|
|
259
|
+
constructor(t) {
|
|
260
|
+
t && Object.keys(t).forEach((e) => {
|
|
261
|
+
this[e] = t[e];
|
|
262
|
+
}), this.d || (this.d = Date.now());
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Gets th parameter value from the XCommand whether it has a name or just a position
|
|
266
|
+
* There are 2 ways to send XCommand with parameters:
|
|
267
|
+
* 1. <module> <op> <param-0> <param-1> <param-2> // position is for this case
|
|
268
|
+
* 2. <module> <op> param-name:param-value // name is for this case
|
|
269
|
+
* @param position the position of the parameter if no name is send
|
|
270
|
+
* @param name the name of the parameter
|
|
271
|
+
* @param defaultValue the default value if none above exists
|
|
272
|
+
* @returns {any} the actual parameter value
|
|
273
|
+
*/
|
|
274
|
+
getParam(t, e, s) {
|
|
275
|
+
return this._params?.hasOwnProperty(e) ? this._params[e] : this._params?.hasOwnProperty(t) ? this._params[t] : s;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
const w = {
|
|
279
|
+
type: "_type",
|
|
280
|
+
children: "_children"
|
|
281
|
+
}, f = class f {
|
|
282
|
+
/**
|
|
283
|
+
* Adds HTML-Xpell Mapping item
|
|
284
|
+
* @param htmlElement HTML element to change from
|
|
285
|
+
* @param xpellElement Xpell element to change to
|
|
286
|
+
*/
|
|
287
|
+
static addHtml2XpellMapItem(t, e) {
|
|
288
|
+
f.html2XMap.elements[t] = e;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* convert text command to Xpell json command
|
|
292
|
+
* @param {string} txt
|
|
293
|
+
*/
|
|
294
|
+
static parse(t, e) {
|
|
295
|
+
const s = t.split(" ");
|
|
296
|
+
let i = new M();
|
|
297
|
+
if (e ? (i._module = e, i._op = s[0]) : (i._module = s[0], i._op = s[1]), i._params = {}, s.length > 1)
|
|
298
|
+
for (let n = 2; n < s.length; ++n) {
|
|
299
|
+
const r = s[n];
|
|
300
|
+
if (r.indexOf(":") > -1) {
|
|
301
|
+
const c = r.split(":");
|
|
302
|
+
i._params[c[0]] = c[1];
|
|
303
|
+
} else
|
|
304
|
+
i._params[n - 1] = s[n];
|
|
305
|
+
}
|
|
306
|
+
return i;
|
|
307
|
+
}
|
|
308
|
+
static replaceSpacesInQuotes(t, e = "_%20_") {
|
|
309
|
+
return t.replace(/(['"])(.*?)\1/g, (s, i, n) => {
|
|
310
|
+
const r = String(n).replace(/\s/g, e);
|
|
311
|
+
return `${i}${r}${i}`;
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
static parseObjectCommand(t, e) {
|
|
315
|
+
t = f.replaceSpacesInQuotes(t);
|
|
316
|
+
const s = t.trim().split(/\s+/), i = e || s.shift();
|
|
317
|
+
if (!i) throw new Error("Missing module name");
|
|
318
|
+
let n;
|
|
319
|
+
if (s[0]?.startsWith("#") && (n = s.shift().slice(1), !n))
|
|
320
|
+
throw new Error("Invalid object selector '#'. Use '#<id>'");
|
|
321
|
+
const r = s.shift();
|
|
322
|
+
if (!r) throw new Error("Missing operation");
|
|
323
|
+
const a = {};
|
|
324
|
+
let c = null, h = null;
|
|
325
|
+
if (s.forEach((l) => {
|
|
326
|
+
if (h) {
|
|
327
|
+
if (h += ` ${l}`, l.endsWith(h[0])) {
|
|
328
|
+
const m = h.slice(1, -1).replace(/_%20_/g, " ");
|
|
329
|
+
a[c] = m, h = null;
|
|
330
|
+
}
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
if (l.startsWith('"') || l.startsWith("'")) {
|
|
334
|
+
if (h = l, l.endsWith(l[0]) && l.length > 1) {
|
|
335
|
+
const m = l.slice(1, -1).replace(/_%20_/g, " ");
|
|
336
|
+
a[c] = m, h = null;
|
|
337
|
+
}
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
if (l.includes(":")) {
|
|
341
|
+
const m = l.split(":"), D = m[0], E = m.slice(1).join(":").replace(/_%20_/g, " ");
|
|
342
|
+
a[D] = E, c = null;
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
c = l.replace(/_%20_/g, " ");
|
|
346
|
+
}), h) throw new Error("Unclosed quoted parameter value");
|
|
347
|
+
return {
|
|
348
|
+
_module: i,
|
|
349
|
+
_object: n,
|
|
350
|
+
_op: r,
|
|
351
|
+
_params: a
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Converts XML/HTML string to XCommand
|
|
356
|
+
* @param xmlString XML string
|
|
357
|
+
* @returns
|
|
358
|
+
*/
|
|
359
|
+
static xmlString2Xpell(t) {
|
|
360
|
+
const s = new DOMParser().parseFromString(t, "text/xml");
|
|
361
|
+
return s.childNodes.length > 0 ? f.xml2Xpell(s.childNodes[0]) : {};
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Converts XML/HTML Document to Xpell JSON
|
|
365
|
+
* @param xmlNode XML Document Node
|
|
366
|
+
* @param forceXhtml force Xpell XHTML for every unknown object
|
|
367
|
+
* @returns {} Xpell JSON
|
|
368
|
+
*/
|
|
369
|
+
static xml2Xpell(t, e) {
|
|
370
|
+
const s = f.html2XMap;
|
|
371
|
+
let i = {};
|
|
372
|
+
i._children = [];
|
|
373
|
+
const n = t.nodeName, r = t.nodeName;
|
|
374
|
+
let a = e;
|
|
375
|
+
if (e ? (i[w.type] = "xhtml", i._html_ns = "http://www.w3.org/2000/svg") : i._type = s.elements[n] ? s.elements[n] : n, t.attributes)
|
|
376
|
+
for (let c = 0; c < t.attributes.length; ++c) {
|
|
377
|
+
const h = t.attributes[c], l = s.attributes[h.name] ? s.attributes[h.name] : h.name;
|
|
378
|
+
i[l] = h.value;
|
|
379
|
+
}
|
|
380
|
+
if (t?.firstChild?.nodeValue && (i.text = t?.firstChild.nodeValue.trim()), i[w.type] == "xhtml" ? i._html_tag = r : i[w.type] == "svg" && (a = !0, i._html_ns = "http://www.w3.org/2000/svg"), t?.childNodes.length > 0)
|
|
381
|
+
for (let c = 0; c < t.childNodes.length; ++c) {
|
|
382
|
+
const h = t.childNodes[c];
|
|
383
|
+
h.nodeName.startsWith("#") || i[w.children].push(f.xml2Xpell(h, a));
|
|
384
|
+
}
|
|
385
|
+
return i;
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
f.html2XMap = {
|
|
389
|
+
elements: {
|
|
390
|
+
div: "view",
|
|
391
|
+
a: "link",
|
|
392
|
+
b: "xhtml",
|
|
393
|
+
h1: "xhtml",
|
|
394
|
+
h2: "xhtml",
|
|
395
|
+
h3: "xhtml",
|
|
396
|
+
h4: "xhtml",
|
|
397
|
+
h5: "xhtml",
|
|
398
|
+
p: "xhtml",
|
|
399
|
+
small: "xhtml",
|
|
400
|
+
aside: "xhtml",
|
|
401
|
+
span: "xhtml",
|
|
402
|
+
table: "xhtml",
|
|
403
|
+
th: "xhtml",
|
|
404
|
+
td: "xhtml",
|
|
405
|
+
tr: "xhtml",
|
|
406
|
+
thead: "xhtml",
|
|
407
|
+
tbody: "xhtml",
|
|
408
|
+
ul: "xhtml",
|
|
409
|
+
li: "xhtml",
|
|
410
|
+
ol: "xhtml",
|
|
411
|
+
canvas: "xhtml",
|
|
412
|
+
img: "image"
|
|
413
|
+
},
|
|
414
|
+
attributes: {
|
|
415
|
+
id: "_id"
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
let g = f;
|
|
419
|
+
class I {
|
|
420
|
+
constructor() {
|
|
421
|
+
this._log_rules = {
|
|
422
|
+
register: !1,
|
|
423
|
+
remove: !1,
|
|
424
|
+
fire: !1
|
|
425
|
+
}, this._events = {}, this._listener_index = {};
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Register a listener on an event name (runtime bus only).
|
|
429
|
+
*
|
|
430
|
+
* Backward compatible:
|
|
431
|
+
* - Canonical: on(name, cb, { _once, _owner, _tag })
|
|
432
|
+
* - Legacy: on(name, cb, { _once }, owner)
|
|
433
|
+
*/
|
|
434
|
+
on(t, e, s = {}, i) {
|
|
435
|
+
this._events[t] || (this._events[t] = []);
|
|
436
|
+
const n = s?._owner ?? i, r = p.guid(), a = {
|
|
437
|
+
_id: r,
|
|
438
|
+
_callback: e,
|
|
439
|
+
_options: s,
|
|
440
|
+
_owner: n,
|
|
441
|
+
_tag: s?._tag
|
|
442
|
+
};
|
|
443
|
+
return this._events[t].push(a), this._listener_index[r] = t, this._log_rules.register && y.log("XEM Register", t, r), r;
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Register a listener that will be removed after first fire.
|
|
447
|
+
*/
|
|
448
|
+
once(t, e, s) {
|
|
449
|
+
return this.on(t, e, { _once: !0, _owner: s });
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Fire an event with optional payload.
|
|
453
|
+
*/
|
|
454
|
+
async fire(t, e) {
|
|
455
|
+
const s = this._events[t];
|
|
456
|
+
if (!s || s.length === 0) return;
|
|
457
|
+
this._log_rules.fire && y.log("XEM Fire", t, e);
|
|
458
|
+
const i = s.slice(), n = [];
|
|
459
|
+
for (const r of i) {
|
|
460
|
+
try {
|
|
461
|
+
r && r._callback && r._callback(e);
|
|
462
|
+
} catch (a) {
|
|
463
|
+
y.error(a);
|
|
464
|
+
}
|
|
465
|
+
r?._options?._once && n.push(r._id);
|
|
466
|
+
}
|
|
467
|
+
for (const r of n) this.remove(r);
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Remove a listener by id.
|
|
471
|
+
*/
|
|
472
|
+
remove(t) {
|
|
473
|
+
const e = this._listener_index[t];
|
|
474
|
+
if (!e) return;
|
|
475
|
+
const s = this._events[e];
|
|
476
|
+
if (s && s.length) {
|
|
477
|
+
const i = s.findIndex((n) => n?._id === t);
|
|
478
|
+
i >= 0 && s.splice(i, 1), s.length === 0 && delete this._events[e];
|
|
479
|
+
}
|
|
480
|
+
delete this._listener_index[t], this._log_rules.remove && y.log("XEM Remove", e, t);
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Remove all listeners for a given owner reference.
|
|
484
|
+
*/
|
|
485
|
+
removeOwner(t) {
|
|
486
|
+
if (!t) return;
|
|
487
|
+
const e = [];
|
|
488
|
+
for (const s of Object.values(this._events))
|
|
489
|
+
for (const i of s)
|
|
490
|
+
(i?._owner ?? i?._options?._owner) === t && e.push(i._id);
|
|
491
|
+
e.forEach((s) => this.remove(s));
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Clear the entire event bus (mostly for tests / hard reset).
|
|
495
|
+
*/
|
|
496
|
+
clear() {
|
|
497
|
+
this._events = {}, this._listener_index = {};
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
const b = new I();
|
|
501
|
+
class P {
|
|
502
|
+
#t;
|
|
503
|
+
#e;
|
|
504
|
+
#s;
|
|
505
|
+
constructor() {
|
|
506
|
+
this.#t = {}, this.#e = {}, this.#s = {};
|
|
507
|
+
}
|
|
508
|
+
get _objects() {
|
|
509
|
+
return this.#e;
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* Checks if an object is found in the object manager
|
|
513
|
+
* @param xObjectId
|
|
514
|
+
* @returns
|
|
515
|
+
*/
|
|
516
|
+
hasObject(t) {
|
|
517
|
+
return this.#e.hasOwnProperty(t);
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Register multiple classes dictionary into the object manager
|
|
521
|
+
* @param xObjects - key value list -> \{"view":XView,...\}
|
|
522
|
+
*/
|
|
523
|
+
registerObjects(t) {
|
|
524
|
+
Object.keys(t).forEach((s) => this.registerObject(s, t[s]));
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Registers single XObject
|
|
528
|
+
* @param name - name of the object
|
|
529
|
+
* @param xObjects The object class
|
|
530
|
+
*/
|
|
531
|
+
registerObject(t, e) {
|
|
532
|
+
this.#t[t] = e;
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Checks if a class (name) is found in the object manager classes dictionary
|
|
536
|
+
* @param name - class name
|
|
537
|
+
* @returns {boolean}
|
|
538
|
+
*/
|
|
539
|
+
hasObjectClass(t) {
|
|
540
|
+
return this.#t.hasOwnProperty(t);
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Retrieves XObject class instance
|
|
544
|
+
* @param name class name
|
|
545
|
+
* @returns {XObject}
|
|
546
|
+
*/
|
|
547
|
+
getObjectClass(t) {
|
|
548
|
+
return this.#t[t];
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Retrieves all the classes dictionary
|
|
552
|
+
* @returns XObjectManagerIndex
|
|
553
|
+
*/
|
|
554
|
+
getAllClasses() {
|
|
555
|
+
return this.#t;
|
|
556
|
+
}
|
|
557
|
+
get _classes() {
|
|
558
|
+
return this.#t;
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Add XObject instance to the manager
|
|
562
|
+
* @param xObject XObject to maintain
|
|
563
|
+
*/
|
|
564
|
+
addObject(t) {
|
|
565
|
+
t && t._id ? (this.#e[t._id] = t, (!t._name || t._name.length == 0) && (t._name = t._id), this.#s[t._name] = t._id) : _.log("unable to add object");
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Remove XObject from the manager
|
|
569
|
+
* @param xObjectId object id to remove
|
|
570
|
+
*/
|
|
571
|
+
removeObject(t) {
|
|
572
|
+
const e = this.#e[t];
|
|
573
|
+
e && (delete this.#s[e?._name], delete this.#e[t]);
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Retrieves XObject instance
|
|
577
|
+
* @param xObjectId XObject id
|
|
578
|
+
* @returns {XObject}
|
|
579
|
+
*/
|
|
580
|
+
getObject(t) {
|
|
581
|
+
return this.#e[t];
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* alias to getObject
|
|
585
|
+
* @param id
|
|
586
|
+
* @returns
|
|
587
|
+
*/
|
|
588
|
+
go(t) {
|
|
589
|
+
return this.getObject(t);
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* Retrieves XObject instance
|
|
593
|
+
* @param objectName XObject name
|
|
594
|
+
* @returns {XObject}
|
|
595
|
+
*/
|
|
596
|
+
getObjectByName(t) {
|
|
597
|
+
return this.#s[t] ? this.getObject(this.#s[t]) : null;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
const A = {
|
|
601
|
+
info: (o, t) => {
|
|
602
|
+
_.log("XObject id " + t?._id);
|
|
603
|
+
},
|
|
604
|
+
log: (o, t) => {
|
|
605
|
+
o._params && o._params[1] ? _.log(o._params[1]) : _.log(t);
|
|
606
|
+
},
|
|
607
|
+
fire: (o, t) => {
|
|
608
|
+
o._params && o._params[1] ? b.fire(o._params[1], o._params[2]) : o._params && o._params.event && b.fire(o._params.event, o._params.data);
|
|
609
|
+
}
|
|
610
|
+
}, j = { _children: "child nodes" };
|
|
611
|
+
class v {
|
|
612
|
+
/**
|
|
613
|
+
* XObject constructor is creating the object and adding all the data keys to the XObject instance
|
|
614
|
+
* @param data constructor input data (object)
|
|
615
|
+
* @param defaults - defaults to merge with data
|
|
616
|
+
* @param skipParse - skip data parsing
|
|
617
|
+
* if override this method make sure to call super.init(data,skipParse) and to set skipParse to true
|
|
618
|
+
*/
|
|
619
|
+
constructor(t, e, s) {
|
|
620
|
+
this._children = [], this._parent = null, this._on = {}, this._once = {}, this._process_frame = !0, this._process_data = !0, this._nano_commands = {}, this._event_listeners_ids = {}, this._event_parsed = !1, this._mounted = !1, this._xporter = {
|
|
621
|
+
_ignore_fields: [
|
|
622
|
+
"_to_xdata_ignore_fields",
|
|
623
|
+
"_xporter",
|
|
624
|
+
"_children",
|
|
625
|
+
"_on",
|
|
626
|
+
"_once",
|
|
627
|
+
"_on_create",
|
|
628
|
+
"_on_mount",
|
|
629
|
+
"_on_frame",
|
|
630
|
+
"_on_data",
|
|
631
|
+
"_process_frame",
|
|
632
|
+
"_process_data",
|
|
633
|
+
"_parent",
|
|
634
|
+
"_event_listeners_ids",
|
|
635
|
+
"_event_parsed",
|
|
636
|
+
"_mounted",
|
|
637
|
+
"_debug"
|
|
638
|
+
],
|
|
639
|
+
_instance_xporters: {}
|
|
640
|
+
}, e && p.mergeDefaultsWithData(t, e), this._id = t && t._id ? t._id : "xo-" + p.guid(), this._type = "object", this._children = [], this._nano_commands = {}, this.addNanoCommandPack(A), t && t.hasOwnProperty("_nano_commands") && t._nano_commands && (this.addNanoCommandPack(t._nano_commands), delete t._nano_commands), this.addXporterDataIgnoreFields(["_nano_commands"]), this.addXporterInstanceXporter(v, (i) => i.toXData()), this._xem_options = {
|
|
641
|
+
// _instance:_xem
|
|
642
|
+
// _object: this
|
|
643
|
+
// _support_html: true
|
|
644
|
+
}, !s && t && this.parse(t, j);
|
|
645
|
+
}
|
|
646
|
+
log(t, ...e) {
|
|
647
|
+
this._debug && t && _.log(this._type + "->" + this._id + "]", t, ...e);
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Initialize the XObject
|
|
651
|
+
* @param data - data to parse (XObjectData)
|
|
652
|
+
* @param skipParse - skip data parsing
|
|
653
|
+
* @deprecated - use parse method instead
|
|
654
|
+
*/
|
|
655
|
+
init(t, e) {
|
|
656
|
+
!e && t && this.parse(t, j);
|
|
657
|
+
}
|
|
658
|
+
parseEvents(t) {
|
|
659
|
+
if (!this._event_parsed) {
|
|
660
|
+
t || (t = this._xem_options), Object.keys(this._on).forEach((s) => {
|
|
661
|
+
this.addEventListener(s, this._on[s], t);
|
|
662
|
+
});
|
|
663
|
+
const e = {};
|
|
664
|
+
Object.assign(e, t), e._once = !0, Object.keys(this._once).forEach((s) => {
|
|
665
|
+
this.addEventListener(s, this._once[s], e);
|
|
666
|
+
}), this._event_parsed = !0;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
addEventListener(t, e, s) {
|
|
670
|
+
s || (s = this._xem_options);
|
|
671
|
+
let i;
|
|
672
|
+
if (typeof e == "function")
|
|
673
|
+
i = async (r) => {
|
|
674
|
+
e(this, r);
|
|
675
|
+
};
|
|
676
|
+
else if (typeof e == "string")
|
|
677
|
+
i = async (r) => {
|
|
678
|
+
const a = this._id + " " + e + " event-data='" + JSON.stringify(r).replace(/'/g, "\\'") + "'";
|
|
679
|
+
await this.run(a);
|
|
680
|
+
};
|
|
681
|
+
else
|
|
682
|
+
throw new Error("event handler must be a function");
|
|
683
|
+
const n = b.on(t, i, s, this);
|
|
684
|
+
this._event_listeners_ids[t] || (this._event_listeners_ids[t] = []), this._event_listeners_ids[t].push(n);
|
|
685
|
+
}
|
|
686
|
+
removeEventListener(t) {
|
|
687
|
+
const e = this._event_listeners_ids[t];
|
|
688
|
+
e && e.length && (e.forEach((s) => {
|
|
689
|
+
b.remove(s);
|
|
690
|
+
}), delete this._event_listeners_ids[t]);
|
|
691
|
+
}
|
|
692
|
+
removeAllEventListeners() {
|
|
693
|
+
Object.keys(this._event_listeners_ids).forEach((e) => this.removeEventListener(e));
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Append a child XObject to this XObject
|
|
697
|
+
* @param xobject
|
|
698
|
+
*/
|
|
699
|
+
append(t) {
|
|
700
|
+
this._children?.push(t), t._parent = this;
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Add single nano command to the object
|
|
704
|
+
* @param commandName - the nano command name
|
|
705
|
+
* @param nanoCommandFunction
|
|
706
|
+
*/
|
|
707
|
+
addNanoCommand(t, e) {
|
|
708
|
+
typeof e == "function" && (this._nano_commands[t] = e);
|
|
709
|
+
}
|
|
710
|
+
addNanoCommandPack(t) {
|
|
711
|
+
t && Object.keys(t).forEach((e) => {
|
|
712
|
+
this.addNanoCommand(e, t[e]);
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* List of fields to ignore when exporting the xobject to XData or string format
|
|
717
|
+
* @param <string[]> ignoreFields - an array with all the fields to ignore
|
|
718
|
+
*/
|
|
719
|
+
addXporterDataIgnoreFields(t) {
|
|
720
|
+
this._xporter._ignore_fields = this._xporter._ignore_fields.concat(t);
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* Add XData Xporter instance handler
|
|
724
|
+
* @param <XDataInstanceXporter> ie - the instance exporter object
|
|
725
|
+
*/
|
|
726
|
+
addXporterInstanceXporter(t, e) {
|
|
727
|
+
const s = p.guid();
|
|
728
|
+
this._xporter._instance_xporters[s] = {
|
|
729
|
+
cls: t,
|
|
730
|
+
handler: e
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Parse data to the XObject
|
|
735
|
+
* @param data data to parse
|
|
736
|
+
* @param ignore - lis of words to ignore in the parse process
|
|
737
|
+
*/
|
|
738
|
+
parse(t, e = j) {
|
|
739
|
+
Object.keys(t).forEach((i) => {
|
|
740
|
+
!e.hasOwnProperty(i) && t.hasOwnProperty(i) && (this[i] = t[i]);
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Parse data to the XObject
|
|
745
|
+
* @param data data to parse
|
|
746
|
+
* @param {object} fields- object with fields and default values (IXData format)
|
|
747
|
+
*
|
|
748
|
+
* fields example = {
|
|
749
|
+
* _name : "default-name",
|
|
750
|
+
* ...
|
|
751
|
+
* }
|
|
752
|
+
*/
|
|
753
|
+
parseFieldsFromXDataObject(t, e) {
|
|
754
|
+
Object.keys(e).forEach((i) => {
|
|
755
|
+
t.hasOwnProperty(i) ? this[i] = t[i] : this[i] = e[i];
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
/**
|
|
759
|
+
* Parse list of fields from IXObjectData to the class
|
|
760
|
+
* @param {IXObjectData} data - the data
|
|
761
|
+
* @param {Array<string>} fields - array of field names (string)
|
|
762
|
+
* @param checkNonXParams - also check non Xpell fields (fields that not starting with "_" sign)
|
|
763
|
+
*/
|
|
764
|
+
parseFields(t, e, s) {
|
|
765
|
+
e.forEach((i) => {
|
|
766
|
+
if (t.hasOwnProperty(i))
|
|
767
|
+
this[i] = t[i];
|
|
768
|
+
else if (s && i.startsWith("_")) {
|
|
769
|
+
const n = i.substring(1);
|
|
770
|
+
t.hasOwnProperty(n) && (this[i] = t[n], this[n] = t[n]);
|
|
771
|
+
}
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* this method triggered after the HTML DOM object has been created and added to the parent element
|
|
776
|
+
* support external _on_create anonymous function in the , example:
|
|
777
|
+
* _on_create: async (xObject) => {
|
|
778
|
+
* // xObject -> The XObject parent of the _on_create function, use instead of this keyword
|
|
779
|
+
* // write code that will be executed each frame.
|
|
780
|
+
* // make sure to write async anonymous function.
|
|
781
|
+
* }
|
|
782
|
+
*
|
|
783
|
+
*/
|
|
784
|
+
async onCreate() {
|
|
785
|
+
this._on_create ? this.checkAndRunInternalFunction(this._on_create) : this._on && this._on.create ? this.checkAndRunInternalFunction(this._on.create) : this._once && this._once.create && this.checkAndRunInternalFunction(this._once.create);
|
|
786
|
+
}
|
|
787
|
+
async checkAndRunInternalFunction(t, ...e) {
|
|
788
|
+
if (typeof t == "function")
|
|
789
|
+
await t(this, ...e);
|
|
790
|
+
else if (typeof t == "string")
|
|
791
|
+
if (e.length > 0) {
|
|
792
|
+
const s = e[0], i = JSON.stringify(s).replace(/'/g, "\\'");
|
|
793
|
+
await this.run(`${this._id} ${t} data:'${i}'`);
|
|
794
|
+
} else
|
|
795
|
+
await this.run(`${this._id} ${t}`);
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Triggers when the object is being mounted to other element
|
|
799
|
+
* support external _on_create anonymous function in the , example:
|
|
800
|
+
* _on_mount: async (xObject) => {
|
|
801
|
+
* // xObject -> The XObject parent of the _on_mount function, use instead of this keyword
|
|
802
|
+
* // write code that will be executed each frame.
|
|
803
|
+
* // make sure to write async anonymous function.
|
|
804
|
+
* }
|
|
805
|
+
*/
|
|
806
|
+
async onMount() {
|
|
807
|
+
if (!this._mounted) {
|
|
808
|
+
this.parseEvents(this._xem_options), this._process_data && typeof this._data_source == "string" && this._data_source.length > 0 && this.bindDataSource(this._data_source, { initial: !0 }), this._on_mount ? await this.checkAndRunInternalFunction(this._on_mount) : this._on && this._on.mount ? await this.checkAndRunInternalFunction(this._on.mount) : this._once && this._once.mount && await this.checkAndRunInternalFunction(this._once.mount), this._mounted = !0;
|
|
809
|
+
for (const t of this._children)
|
|
810
|
+
t.onMount && typeof t.onMount == "function" && t.onMount();
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
emptyDataSource() {
|
|
814
|
+
const t = this._data_source;
|
|
815
|
+
if (typeof t != "string" || t.length === 0) return;
|
|
816
|
+
const e = this._type ?? this.constructor.name, s = this._id ?? "no-id";
|
|
817
|
+
u.delete(t, { source: `${e}#${s}.emptyDataSource` });
|
|
818
|
+
}
|
|
819
|
+
/**
|
|
820
|
+
* Triggers when new data is being received from the data source
|
|
821
|
+
* @param data - the data
|
|
822
|
+
* if override this method make sure to call super.onData(data) to run the _on_data attribute
|
|
823
|
+
*/
|
|
824
|
+
async onData(t) {
|
|
825
|
+
this._process_data && (this._on_data ? this.checkAndRunInternalFunction(this._on_data, t) : this._on && this._on.data ? this.checkAndRunInternalFunction(this._on.data, t) : this._once && this._once.data && this.checkAndRunInternalFunction(this._once.data, t));
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* Triggers from Xpell frame every frame
|
|
829
|
+
* Support _on_frame atrribute that can be XCommand string or function
|
|
830
|
+
* @param {number} frameNumber
|
|
831
|
+
*
|
|
832
|
+
* XObject supports
|
|
833
|
+
* 1. External _on_frame anonymous function in the , example:
|
|
834
|
+
* _on_frame: async (xObject,frameNumber) => {
|
|
835
|
+
* // xObject -> The XObject parent of the _on_frame function, use instead of this keyword
|
|
836
|
+
* // frameNumber = Xpell current frame number
|
|
837
|
+
* // write code that will be executed each frame.
|
|
838
|
+
* // make sure to write async anonymous function.
|
|
839
|
+
* // be wise with the function execution and try to keep it in the 15ms running time to support 60 FPS
|
|
840
|
+
* }
|
|
841
|
+
*
|
|
842
|
+
* 2. String execution of nano commands
|
|
843
|
+
*
|
|
844
|
+
* _on_frame: "nano command text"
|
|
845
|
+
*
|
|
846
|
+
*/
|
|
847
|
+
async onFrame(t) {
|
|
848
|
+
this._process_frame && (this._on_frame ? this.checkAndRunInternalFunction(this._on_frame, t) : this._on && this._on.frame ? this.checkAndRunInternalFunction(this._on.frame, t) : this._once && this._once.frame && this.checkAndRunInternalFunction(this._once.frame, t));
|
|
849
|
+
for (const e of this._children)
|
|
850
|
+
e.onFrame && typeof e.onFrame == "function" && e.onFrame(t);
|
|
851
|
+
}
|
|
852
|
+
/**
|
|
853
|
+
* Runs object nano commands
|
|
854
|
+
* @param nanoCommand - object nano command (string)
|
|
855
|
+
* @param cache - cache last command to prevent multiple parsing on the same command
|
|
856
|
+
*/
|
|
857
|
+
async run(t, e = !0) {
|
|
858
|
+
let s = this._cache_cmd_txt && this._cache_cmd_txt == t ? this._cache_jcmd : g.parseObjectCommand(t);
|
|
859
|
+
e && (this._cache_cmd_txt = t, this._cache_jcmd = s), await this.execute(s);
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* Execute XCommand within the XObject Nano Commands
|
|
863
|
+
* @param xCommand XCommand to execute
|
|
864
|
+
*
|
|
865
|
+
* Nano command example:
|
|
866
|
+
*
|
|
867
|
+
* "set-text" : (xCommand,xObject) => {
|
|
868
|
+
* xObject.setText(xCommands.params.text)
|
|
869
|
+
* }
|
|
870
|
+
*
|
|
871
|
+
*/
|
|
872
|
+
async execute(t) {
|
|
873
|
+
if (t._op && this._nano_commands[t._op])
|
|
874
|
+
try {
|
|
875
|
+
await this._nano_commands[t._op](t, this);
|
|
876
|
+
} catch (e) {
|
|
877
|
+
_.error(this._id + " has error with command name " + t._op + " " + e);
|
|
878
|
+
}
|
|
879
|
+
else
|
|
880
|
+
_.error(this._id + " has no command name " + t._op);
|
|
881
|
+
}
|
|
882
|
+
/**
|
|
883
|
+
* Return an IXObjectData JSON representation of the XObject
|
|
884
|
+
* @returns IXObjectData
|
|
885
|
+
*/
|
|
886
|
+
toXData() {
|
|
887
|
+
const t = {};
|
|
888
|
+
return Object.keys(this).forEach((e) => {
|
|
889
|
+
if (!this._xporter._ignore_fields.includes(e) && this.hasOwnProperty(e) && this[e] !== void 0) {
|
|
890
|
+
const s = this[e];
|
|
891
|
+
if (typeof s == "function")
|
|
892
|
+
return;
|
|
893
|
+
if (typeof s == "object") {
|
|
894
|
+
const i = Object.keys(this._xporter._instance_xporters);
|
|
895
|
+
let n = !0;
|
|
896
|
+
i.forEach((r) => {
|
|
897
|
+
this._xporter._instance_xporters[r], s instanceof this._xporter._instance_xporters[r].cls && (t[e] = this._xporter._instance_xporters[r].handler(s), n = !1);
|
|
898
|
+
}), n && (t[e] = s);
|
|
899
|
+
} else
|
|
900
|
+
t[e] = s;
|
|
901
|
+
}
|
|
902
|
+
}), t._children = [], this._children.length > 0 && this._children.forEach((e) => {
|
|
903
|
+
typeof e.toXData == "function" && t._children?.push(e.toXData());
|
|
904
|
+
}), t;
|
|
905
|
+
}
|
|
906
|
+
/**
|
|
907
|
+
* Return a string representation of the XObject
|
|
908
|
+
* @returns string
|
|
909
|
+
*/
|
|
910
|
+
toString() {
|
|
911
|
+
return JSON.stringify(this.toXData());
|
|
912
|
+
}
|
|
913
|
+
clearAttributes(t) {
|
|
914
|
+
t.forEach((e) => {
|
|
915
|
+
this.hasOwnProperty(e) && (this[e] = null, delete this[e]);
|
|
916
|
+
});
|
|
917
|
+
}
|
|
918
|
+
bindDataSource(t, e) {
|
|
919
|
+
const s = e?.initial ?? !0, i = t ?? this._data_source;
|
|
920
|
+
typeof i != "string" || i.length === 0 || this._process_data && (this._xd_bound_key === i && this._xd_unsub || (this.unbindDataSource(), this._data_source = i, this._xd_bound_key = i, this._type ?? this.constructor.name, this._id, this._xd_unsub = u.on(i, async (n) => {
|
|
921
|
+
await this.onData(n.value);
|
|
922
|
+
}), s && u.has(i) && this.onData(u.get(i))));
|
|
923
|
+
}
|
|
924
|
+
unbindDataSource() {
|
|
925
|
+
this._xd_unsub?.(), this._xd_unsub = void 0, this._xd_bound_key = void 0;
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* Dispose the XObject and all its children
|
|
929
|
+
*/
|
|
930
|
+
async dispose() {
|
|
931
|
+
if (this.unbindDataSource(), this._parent) {
|
|
932
|
+
const t = this._parent._children.indexOf(this);
|
|
933
|
+
t > -1 && this._parent._children.splice(t, 1);
|
|
934
|
+
}
|
|
935
|
+
this._process_data = !1, this._process_frame = !1, this.removeAllEventListeners(), this.clearAttributes(["_cache_cmd_txt", "_cache_jcmd", "_nano_commands", "_event_listeners_ids", "_parent", "_on", "_once", "_xem_options", "_xporter"]), this._children && this._children.forEach((t) => {
|
|
936
|
+
typeof t.dispose == "function" && t.dispose();
|
|
937
|
+
}), this._children = [];
|
|
938
|
+
}
|
|
939
|
+
/**
|
|
940
|
+
* Remove a child from the XObject )
|
|
941
|
+
* @param child - the child to
|
|
942
|
+
* @returns void
|
|
943
|
+
*/
|
|
944
|
+
removeChild(t, e = !1) {
|
|
945
|
+
if (e)
|
|
946
|
+
t.dispose();
|
|
947
|
+
else {
|
|
948
|
+
const s = this._children.indexOf(t);
|
|
949
|
+
s > -1 && this._children.splice(s, 1), t._parent = null;
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
/**
|
|
953
|
+
* @param child - the child to add
|
|
954
|
+
* @deprecated use append method instead
|
|
955
|
+
*/
|
|
956
|
+
addChild(t) {
|
|
957
|
+
this.append(t);
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
class B {
|
|
961
|
+
/**
|
|
962
|
+
* Get all registered object in this ObjectPack
|
|
963
|
+
* @returns XObject dictionary
|
|
964
|
+
*/
|
|
965
|
+
static getObjects() {
|
|
966
|
+
return {
|
|
967
|
+
object: v
|
|
968
|
+
};
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
const $ = "engine:module:num-of-objects:";
|
|
972
|
+
class C {
|
|
973
|
+
//engine: any; //deprecated remove after spell3d
|
|
974
|
+
constructor(t) {
|
|
975
|
+
this._log_rules = {
|
|
976
|
+
createObject: !1,
|
|
977
|
+
removeObject: !1
|
|
978
|
+
}, this.#t = new P(), this._name = t._name, this._id = p.guid();
|
|
979
|
+
}
|
|
980
|
+
#t;
|
|
981
|
+
load() {
|
|
982
|
+
_.log("Module " + this._name + " loaded");
|
|
983
|
+
}
|
|
984
|
+
/**
|
|
985
|
+
* Creates new XObject from data object
|
|
986
|
+
* @param data - The data of the new object (JSON)
|
|
987
|
+
* @return {XObject|*}
|
|
988
|
+
*/
|
|
989
|
+
create(t) {
|
|
990
|
+
let e;
|
|
991
|
+
if (t.hasOwnProperty("_type"))
|
|
992
|
+
if (this.#t.hasObjectClass(t._type)) {
|
|
993
|
+
let s = this.#t.getObjectClass(t._type);
|
|
994
|
+
s.hasOwnProperty("defaults") && p.mergeDefaultsWithData(t, s.defaults), e = new s(t);
|
|
995
|
+
} else
|
|
996
|
+
throw "Xpell object '" + t._type + "' not found";
|
|
997
|
+
else
|
|
998
|
+
e = new v(t);
|
|
999
|
+
return this.#t.addObject(e), t._children && t._children.forEach((s) => {
|
|
1000
|
+
const i = this.create(s);
|
|
1001
|
+
e.append(i);
|
|
1002
|
+
}), e.onCreate(), e;
|
|
1003
|
+
}
|
|
1004
|
+
/**
|
|
1005
|
+
* removes and XObject from the object manager
|
|
1006
|
+
* @param objectId op
|
|
1007
|
+
*/
|
|
1008
|
+
remove(t) {
|
|
1009
|
+
const e = this.#t.getObject(t);
|
|
1010
|
+
if (!e) return;
|
|
1011
|
+
const s = [], i = (n) => {
|
|
1012
|
+
n?._id && (s.push(n._id), (n._children ?? []).forEach((r) => i(r)));
|
|
1013
|
+
};
|
|
1014
|
+
i(e), typeof e.dispose == "function" && e.dispose(), s.reverse().forEach((n) => this.#t.removeObject(n));
|
|
1015
|
+
}
|
|
1016
|
+
_info(t) {
|
|
1017
|
+
_.log("module info");
|
|
1018
|
+
}
|
|
1019
|
+
//xpell interpreter
|
|
1020
|
+
/**
|
|
1021
|
+
* Run xpell command -
|
|
1022
|
+
* CLI mode, parse the command to XCommand JSON format and call execute method
|
|
1023
|
+
* @param {string} XCommand input - text
|
|
1024
|
+
* @returns command execution result
|
|
1025
|
+
*/
|
|
1026
|
+
async run(t) {
|
|
1027
|
+
if (t) {
|
|
1028
|
+
let e = t.trim();
|
|
1029
|
+
e.startsWith(this._name) || (e = this._name + " " + e);
|
|
1030
|
+
let s = g.parse(e);
|
|
1031
|
+
return await this.execute(s);
|
|
1032
|
+
} else
|
|
1033
|
+
throw "Unable to parse Xpell Command";
|
|
1034
|
+
}
|
|
1035
|
+
/**
|
|
1036
|
+
* execute xpell command - CLI mode
|
|
1037
|
+
* @param {XCommand} XCommand input (JSON)
|
|
1038
|
+
* @returns command execution result
|
|
1039
|
+
*/
|
|
1040
|
+
// inside XModule class
|
|
1041
|
+
async execute(t) {
|
|
1042
|
+
if (!t || !t._op)
|
|
1043
|
+
throw new Error(`Invalid XCommand: missing _op (module: ${this._name})`);
|
|
1044
|
+
const e = t._object;
|
|
1045
|
+
if (e) {
|
|
1046
|
+
const n = this.#t.getObject(e);
|
|
1047
|
+
if (!n)
|
|
1048
|
+
throw new Error(`Module '${this._name}' cant find object id: ${e}`);
|
|
1049
|
+
return await n.execute(t);
|
|
1050
|
+
}
|
|
1051
|
+
const s = "_" + t._op.replaceAll("-", "_"), i = this[s];
|
|
1052
|
+
if (typeof i == "function")
|
|
1053
|
+
return await i.call(this, t);
|
|
1054
|
+
throw new Error(`Module '${this._name}' cant find op: ${t._op}`);
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* This method triggers every frame from the Xpell engine.
|
|
1058
|
+
* The method can be override by the extending module to support extended onFrame functionality
|
|
1059
|
+
* @param frameNumber Current frame number
|
|
1060
|
+
*/
|
|
1061
|
+
async onFrame(t) {
|
|
1062
|
+
const e = this.#t._objects, s = Object.keys(e);
|
|
1063
|
+
s.forEach((i) => {
|
|
1064
|
+
const n = e[i];
|
|
1065
|
+
n && n.onFrame && typeof n.onFrame == "function" && n?.onFrame(t);
|
|
1066
|
+
}), u.set($ + this._id, s.length, {
|
|
1067
|
+
source: "xmodule"
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
1070
|
+
/**
|
|
1071
|
+
* X Object Manager
|
|
1072
|
+
*/
|
|
1073
|
+
/**
|
|
1074
|
+
* getter for om (object manager) instance
|
|
1075
|
+
* @returns {XObjectManager}
|
|
1076
|
+
* @deprecated - use _object_manager instead
|
|
1077
|
+
* If you wish to get an object from the object manager use
|
|
1078
|
+
* getObject directly on the module instead of om.getObject
|
|
1079
|
+
*/
|
|
1080
|
+
get om() {
|
|
1081
|
+
return this.#t;
|
|
1082
|
+
}
|
|
1083
|
+
get _object_manager() {
|
|
1084
|
+
return this.#t;
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* Returns the XObject instance from the module Object Manager
|
|
1088
|
+
* @param objectId
|
|
1089
|
+
* @returns XObject
|
|
1090
|
+
*/
|
|
1091
|
+
getObject(t) {
|
|
1092
|
+
return this.#t.getObject(t);
|
|
1093
|
+
}
|
|
1094
|
+
/**
|
|
1095
|
+
* Returns the XObject instance from the module Object Manager
|
|
1096
|
+
* Usage:
|
|
1097
|
+
* xmodule._o["object-id"] is equivalent to xmodule.getObject("object-id")
|
|
1098
|
+
*/
|
|
1099
|
+
get _o() {
|
|
1100
|
+
return this.#t._objects;
|
|
1101
|
+
}
|
|
1102
|
+
/**
|
|
1103
|
+
* Imports external object pack to the engine
|
|
1104
|
+
* The object class should be like XObjects with static implementation of getObjects() method
|
|
1105
|
+
* @param {XObjects} xObjectPack
|
|
1106
|
+
*/
|
|
1107
|
+
importObjectPack(t) {
|
|
1108
|
+
this.#t.registerObjects(t.getObjects());
|
|
1109
|
+
}
|
|
1110
|
+
/**
|
|
1111
|
+
* Imports external object pack to the engine
|
|
1112
|
+
* @deprecated - use importObjectPack instead
|
|
1113
|
+
* @param xObjectPack
|
|
1114
|
+
*/
|
|
1115
|
+
importObjects(t) {
|
|
1116
|
+
this.importObjectPack(t);
|
|
1117
|
+
}
|
|
1118
|
+
/**
|
|
1119
|
+
* Imports external objects to the engine
|
|
1120
|
+
* The object class should be like XObjects with static implementation of getObjects() method
|
|
1121
|
+
* @param xObjectName
|
|
1122
|
+
* @param xObject
|
|
1123
|
+
*/
|
|
1124
|
+
importObject(t, e) {
|
|
1125
|
+
this.#t.registerObject(t, e);
|
|
1126
|
+
}
|
|
1127
|
+
// In XModule
|
|
1128
|
+
async _help(t) {
|
|
1129
|
+
const e = t?._params?._op ?? t?._params?._command ?? "";
|
|
1130
|
+
return this.help(e);
|
|
1131
|
+
}
|
|
1132
|
+
/**
|
|
1133
|
+
* Override in modules to provide help text.
|
|
1134
|
+
* @param op optional: specific command name (e.g. "navigate")
|
|
1135
|
+
*/
|
|
1136
|
+
help(t) {
|
|
1137
|
+
return {
|
|
1138
|
+
module: this._name,
|
|
1139
|
+
usage: `${this._name} help`,
|
|
1140
|
+
ops: ["help"],
|
|
1141
|
+
note: "No help() implemented for this module."
|
|
1142
|
+
};
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
class L {
|
|
1146
|
+
/* -------------------------------------------------- */
|
|
1147
|
+
/* core helpers */
|
|
1148
|
+
/* -------------------------------------------------- */
|
|
1149
|
+
static get(t, e, s) {
|
|
1150
|
+
if (!t?._params) return s;
|
|
1151
|
+
const i = t._params[e];
|
|
1152
|
+
return i !== void 0 ? i : s;
|
|
1153
|
+
}
|
|
1154
|
+
static has(t, e) {
|
|
1155
|
+
return t?._params && t._params[e] !== void 0;
|
|
1156
|
+
}
|
|
1157
|
+
static str(t, ...e) {
|
|
1158
|
+
for (const s of e) {
|
|
1159
|
+
const i = t?._params?.[s];
|
|
1160
|
+
if (i != null)
|
|
1161
|
+
return String(i);
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
/* -------------------------------------------------- */
|
|
1165
|
+
/* typed params */
|
|
1166
|
+
/* -------------------------------------------------- */
|
|
1167
|
+
static bool(t, e, s = !1) {
|
|
1168
|
+
const i = this.get(t, e, s);
|
|
1169
|
+
if (typeof i == "boolean") return i;
|
|
1170
|
+
if (typeof i == "number") return i !== 0;
|
|
1171
|
+
if (typeof i == "string") {
|
|
1172
|
+
const n = i.toLowerCase();
|
|
1173
|
+
if (["1", "true", "yes", "on"].includes(n)) return !0;
|
|
1174
|
+
if (["0", "false", "no", "off"].includes(n)) return !1;
|
|
1175
|
+
}
|
|
1176
|
+
return !!i;
|
|
1177
|
+
}
|
|
1178
|
+
static int(t, e, s = 0) {
|
|
1179
|
+
const i = this.get(t, e, s), n = parseInt(String(i), 10);
|
|
1180
|
+
return Number.isFinite(n) ? n : s;
|
|
1181
|
+
}
|
|
1182
|
+
static json(t, e, s) {
|
|
1183
|
+
const i = this.get(t, e, s);
|
|
1184
|
+
if (i == null) return s;
|
|
1185
|
+
if (typeof i == "object") return i;
|
|
1186
|
+
if (typeof i == "string")
|
|
1187
|
+
try {
|
|
1188
|
+
return JSON.parse(i);
|
|
1189
|
+
} catch {
|
|
1190
|
+
return s;
|
|
1191
|
+
}
|
|
1192
|
+
return s;
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
class O extends Error {
|
|
1196
|
+
constructor(t, e, s) {
|
|
1197
|
+
super(e), this.name = "XError", this._code = t, this._level = s?._level ?? "error", this._meta = s?._meta, this._cause = s?._cause;
|
|
1198
|
+
}
|
|
1199
|
+
toXData() {
|
|
1200
|
+
return {
|
|
1201
|
+
_code: this._code,
|
|
1202
|
+
_level: this._level,
|
|
1203
|
+
_meta: this._meta,
|
|
1204
|
+
_cause: this._cause,
|
|
1205
|
+
// optional: include name/message if you want them in protocol too
|
|
1206
|
+
name: this.name,
|
|
1207
|
+
message: this.message
|
|
1208
|
+
};
|
|
1209
|
+
}
|
|
1210
|
+
toJSON() {
|
|
1211
|
+
return {
|
|
1212
|
+
...this.toXData(),
|
|
1213
|
+
stack: this.stack
|
|
1214
|
+
// debug-only
|
|
1215
|
+
};
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
class d {
|
|
1219
|
+
constructor(t) {
|
|
1220
|
+
this._ok = !1, this._ts = Date.now(), this._pt = 0, t && this.setXData(t);
|
|
1221
|
+
}
|
|
1222
|
+
// ---------------------------------------------------------------------------
|
|
1223
|
+
// Factories
|
|
1224
|
+
// ---------------------------------------------------------------------------
|
|
1225
|
+
static create(t) {
|
|
1226
|
+
return new d(t);
|
|
1227
|
+
}
|
|
1228
|
+
static ok(t) {
|
|
1229
|
+
return new d({ _ok: !0, _result: t });
|
|
1230
|
+
}
|
|
1231
|
+
static error(t) {
|
|
1232
|
+
if (t instanceof O)
|
|
1233
|
+
return new d({
|
|
1234
|
+
_ok: !1,
|
|
1235
|
+
_result: t.toXData()
|
|
1236
|
+
});
|
|
1237
|
+
const e = new O(
|
|
1238
|
+
"E_INTERNAL",
|
|
1239
|
+
t?.message ?? String(t),
|
|
1240
|
+
{ _cause: t }
|
|
1241
|
+
);
|
|
1242
|
+
return new d({
|
|
1243
|
+
_ok: !1,
|
|
1244
|
+
_result: e.toXData()
|
|
1245
|
+
});
|
|
1246
|
+
}
|
|
1247
|
+
// ---------------------------------------------------------------------------
|
|
1248
|
+
// Lifecycle
|
|
1249
|
+
// ---------------------------------------------------------------------------
|
|
1250
|
+
stopProcessTimeCounter() {
|
|
1251
|
+
this._pt = Date.now() - this._ts;
|
|
1252
|
+
}
|
|
1253
|
+
// ---------------------------------------------------------------------------
|
|
1254
|
+
// Protocol
|
|
1255
|
+
// ---------------------------------------------------------------------------
|
|
1256
|
+
/**
|
|
1257
|
+
* Convert to wire-safe object.
|
|
1258
|
+
* NOTE: serialize == finalize timing
|
|
1259
|
+
*/
|
|
1260
|
+
toXData() {
|
|
1261
|
+
return this.stopProcessTimeCounter(), {
|
|
1262
|
+
_ok: this._ok,
|
|
1263
|
+
_ts: this._ts,
|
|
1264
|
+
_pt: this._pt,
|
|
1265
|
+
_result: this._result
|
|
1266
|
+
};
|
|
1267
|
+
}
|
|
1268
|
+
toString() {
|
|
1269
|
+
return JSON.stringify(this.toXData());
|
|
1270
|
+
}
|
|
1271
|
+
setXData(t) {
|
|
1272
|
+
t && ("_ok" in t && (this._ok = !!t._ok), "_ts" in t && typeof t._ts == "number" && (this._ts = t._ts), "_pt" in t && typeof t._pt == "number" && (this._pt = t._pt), "_result" in t && (this._result = t._result));
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
class T extends d {
|
|
1276
|
+
constructor(t) {
|
|
1277
|
+
super(d.error(t).toXData());
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
class W extends d {
|
|
1281
|
+
constructor(t) {
|
|
1282
|
+
super({ _ok: !0, _result: t });
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
const R = "engine:frame-number", N = "engine:fps";
|
|
1286
|
+
class U {
|
|
1287
|
+
constructor(t) {
|
|
1288
|
+
this._log_rules = {}, this._modules = {}, this._schedule_frame = t?._schedule_frame ?? p.createDefaultScheduler(t?._target_fps), this._version = "0.0.1", this._engine_id = p.guid(), this._frame_number = 0, this._fps_calc = new k(), this.parser = g, this._modules = {}, b.fire("xpell-init"), _._enabled = !1;
|
|
1289
|
+
}
|
|
1290
|
+
/**
|
|
1291
|
+
* @deprecated use _verbose instead
|
|
1292
|
+
* Enable Xpell logs to console
|
|
1293
|
+
*/
|
|
1294
|
+
set verbose(t) {
|
|
1295
|
+
_._enabled = t;
|
|
1296
|
+
}
|
|
1297
|
+
/**
|
|
1298
|
+
* Enable Xpell logs to console
|
|
1299
|
+
*/
|
|
1300
|
+
set _verbose(t) {
|
|
1301
|
+
_._enabled = t;
|
|
1302
|
+
}
|
|
1303
|
+
/**
|
|
1304
|
+
* Logs message to console using Xpell logger
|
|
1305
|
+
* make sure to enable verbose mode to see the logs
|
|
1306
|
+
* this method is a wrapper for XLogger.log
|
|
1307
|
+
* @param msg
|
|
1308
|
+
* @param optionalParams
|
|
1309
|
+
*/
|
|
1310
|
+
log(t, ...e) {
|
|
1311
|
+
_.log(t, ...e);
|
|
1312
|
+
}
|
|
1313
|
+
/**
|
|
1314
|
+
* Delay the execution of the next command
|
|
1315
|
+
* @param ms - delay in milliseconds
|
|
1316
|
+
* @returns
|
|
1317
|
+
*/
|
|
1318
|
+
async delay(t) {
|
|
1319
|
+
return new Promise((e) => setTimeout(e, t));
|
|
1320
|
+
}
|
|
1321
|
+
/**
|
|
1322
|
+
* Loads Xpell module into the engine
|
|
1323
|
+
* @param {XModule} xModule
|
|
1324
|
+
*/
|
|
1325
|
+
loadModule(t) {
|
|
1326
|
+
this._modules.hasOwnProperty(t._name) ? _.log("Module " + t._name + " already loaded") : (this._modules[t._name] = t, t.load());
|
|
1327
|
+
}
|
|
1328
|
+
/**
|
|
1329
|
+
* Loads multiple module at ones
|
|
1330
|
+
* @param {Array<XModule>} xModulesArray
|
|
1331
|
+
*/
|
|
1332
|
+
loadModules(...t) {
|
|
1333
|
+
t.forEach((e) => this.loadModule(e));
|
|
1334
|
+
}
|
|
1335
|
+
/**
|
|
1336
|
+
* Display information about the Xpell engine to the console
|
|
1337
|
+
*/
|
|
1338
|
+
info() {
|
|
1339
|
+
_.log(`Xpell information:
|
|
1340
|
+
- Engine Id: ` + this._engine_id + `
|
|
1341
|
+
- Version ` + this._version);
|
|
1342
|
+
}
|
|
1343
|
+
/**
|
|
1344
|
+
* Run textual xCommand -
|
|
1345
|
+
* @param {cmd} - text command
|
|
1346
|
+
*/
|
|
1347
|
+
run(t) {
|
|
1348
|
+
if (t?.length > 2) {
|
|
1349
|
+
let e = g.parse(t);
|
|
1350
|
+
return this.execute(e);
|
|
1351
|
+
} else
|
|
1352
|
+
throw "Unable to parse Xpell command";
|
|
1353
|
+
}
|
|
1354
|
+
/**
|
|
1355
|
+
* Execute Xpell Command
|
|
1356
|
+
* @param {XCommand}
|
|
1357
|
+
*/
|
|
1358
|
+
execute(t) {
|
|
1359
|
+
if (t && t._module && this._modules[t._module])
|
|
1360
|
+
return this._modules[t._module].execute(t);
|
|
1361
|
+
throw "Xpell module " + t._module + " not loaded";
|
|
1362
|
+
}
|
|
1363
|
+
/**
|
|
1364
|
+
* Main onFrame method
|
|
1365
|
+
* calls all the sub-modules onFrame methods (if implemented)
|
|
1366
|
+
*/
|
|
1367
|
+
onFrame() {
|
|
1368
|
+
this._frame_number++;
|
|
1369
|
+
for (const e of Object.keys(this._modules)) {
|
|
1370
|
+
const s = this._modules[e];
|
|
1371
|
+
s?.onFrame && typeof s.onFrame == "function" && s.onFrame(this._frame_number);
|
|
1372
|
+
}
|
|
1373
|
+
const t = this._fps_calc.calc();
|
|
1374
|
+
u.set(R, this._frame_number, { source: "engine" }), u.set(N, t, { source: "engine" }), u._compat_legacy_keys && (u.set("frame-number", this._frame_number, { source: "engine:legacy" }), u.set("fps", t, { source: "engine:legacy" })), this._schedule_frame(() => this.onFrame());
|
|
1375
|
+
}
|
|
1376
|
+
/**
|
|
1377
|
+
* Gets Xpell module by name
|
|
1378
|
+
* @param {string} moduleName - name of the loaded module
|
|
1379
|
+
* @returns {XModule}
|
|
1380
|
+
*/
|
|
1381
|
+
getModule(t) {
|
|
1382
|
+
return this._modules[t];
|
|
1383
|
+
}
|
|
1384
|
+
/**
|
|
1385
|
+
* Start Xpell engine for web browsers using requestAnimationFrame
|
|
1386
|
+
*/
|
|
1387
|
+
start() {
|
|
1388
|
+
_.log("Starting Xpell"), this.onFrame();
|
|
1389
|
+
}
|
|
1390
|
+
/**
|
|
1391
|
+
* deprecated - use XData._o directly
|
|
1392
|
+
*/
|
|
1393
|
+
getParam(t, e) {
|
|
1394
|
+
return t in u._o ? u._o[t] : e;
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
const J = new U();
|
|
1398
|
+
export {
|
|
1399
|
+
M as XCommand,
|
|
1400
|
+
N as XD_FPS,
|
|
1401
|
+
R as XD_FRAME_NUMBER,
|
|
1402
|
+
u as XData,
|
|
1403
|
+
O as XError,
|
|
1404
|
+
b as XEventManager,
|
|
1405
|
+
_ as XLogger,
|
|
1406
|
+
C as XModule,
|
|
1407
|
+
v as XObject,
|
|
1408
|
+
P as XObjectManager,
|
|
1409
|
+
B as XObjectPack,
|
|
1410
|
+
L as XParams,
|
|
1411
|
+
g as XParser,
|
|
1412
|
+
d as XResponse,
|
|
1413
|
+
T as XResponseError,
|
|
1414
|
+
W as XResponseOK,
|
|
1415
|
+
p as XUtils,
|
|
1416
|
+
J as Xpell,
|
|
1417
|
+
U as XpellEngine,
|
|
1418
|
+
S as _XData,
|
|
1419
|
+
I as _XEventManager,
|
|
1420
|
+
F as _XLogger,
|
|
1421
|
+
X as _XUtils,
|
|
1422
|
+
J as _x,
|
|
1423
|
+
u as _xd,
|
|
1424
|
+
b as _xem,
|
|
1425
|
+
_ as _xlog,
|
|
1426
|
+
p as _xu,
|
|
1427
|
+
J as default
|
|
1428
|
+
};
|