@lmjs/core 1.0.6 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/bundle.js +264 -0
- package/build/plugins-registry.js +216 -0
- package/dist/lumenjs-core-with-plugins.js +59258 -0
- package/dist/lumenjs-core.js +50 -0
- package/dist/lumenjs-plugins.css +2822 -0
- package/package.json +59 -28
- package/src/_re.js +2307 -0
- package/src/dom-shim.js +473 -0
- package/src/index-bootstrap.js +47 -0
- package/src/lstnrs.js +1391 -0
- package/src/walk.js +749 -0
- package/src/workers/css.js +1 -0
- package/src/workers/cssRaw.js +1173 -0
- package/src/workers/esp.js +1 -0
- package/src/workers/espRaw.js +78 -0
- package/src/workers/up.js +1 -0
- package/src/workers/upRaw.js +491 -0
- package/src/workers/work.js +1 -0
- package/src/workers/workRaw.js +1097 -0
- package/src/ws.js +1162 -0
- package/vendor/astring.js +3 -0
- package/vendor/bootstrap2-less-stubs/mixins.less +16 -0
- package/vendor/bootstrap2-less-stubs/variables.less +13 -0
- package/vendor/md5.js +1 -0
- package/vendor/reconnecting-websocket.js +4118 -0
- package/vendor/webworker-helper.js +1 -0
- package/LICENSE +0 -201
- package/README.md +0 -3
- package/index.js +0 -14
package/src/_re.js
ADDED
|
@@ -0,0 +1,2307 @@
|
|
|
1
|
+
// `cl` is normally aliased in vendor/reconnecting-websocket.js (`var cl =
|
|
2
|
+
// console.log;`), but that file is concatenated AFTER this one (see
|
|
3
|
+
// build/bundle.js) — and this file's own Proxy traps below call `cl(e)` in
|
|
4
|
+
// their catch handlers. That's reachable before the vendor file ever runs:
|
|
5
|
+
// index-bootstrap.js (also after this file, before the vendor one) can
|
|
6
|
+
// trigger _x()'s `set` trap (e.g. `_vt.Global.vars["x"] = ...` from a
|
|
7
|
+
// compiled index.js) before any view exists, which throws internally
|
|
8
|
+
// (`_vt.View._re` is undefined) and get caught right here — if `cl` isn't
|
|
9
|
+
// defined yet at that point, the catch handler itself throws, aborting
|
|
10
|
+
// whatever script called it (found 2026-09-14 testing against a real
|
|
11
|
+
// running dev server). Harmless if vendor/reconnecting-websocket.js's own
|
|
12
|
+
// `var cl = console.log;` runs later too — same value, redeclaration is a
|
|
13
|
+
// no-op.
|
|
14
|
+
var cl = console.log;
|
|
15
|
+
|
|
16
|
+
class _v {
|
|
17
|
+
static name;
|
|
18
|
+
static type;
|
|
19
|
+
static vars;
|
|
20
|
+
static rvs;
|
|
21
|
+
static _pv;
|
|
22
|
+
static mx;
|
|
23
|
+
static views;
|
|
24
|
+
static hst;
|
|
25
|
+
static settings;
|
|
26
|
+
constructor(obj) {
|
|
27
|
+
this.name = obj.name ?? 'home';
|
|
28
|
+
this.type = obj.type ?? 'main';
|
|
29
|
+
this.hst = obj.hst ?? [];
|
|
30
|
+
this.views = obj.views ?? [];
|
|
31
|
+
this.vars = obj.vars ?? {};
|
|
32
|
+
this.rvs = obj.rvs ?? {};
|
|
33
|
+
this._pv = obj._pv ?? null;
|
|
34
|
+
this.mx = obj.mx ?? [];
|
|
35
|
+
this.settings = obj.settings ?? {
|
|
36
|
+
layout: "default",
|
|
37
|
+
requireAuth: false,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Override console.log
|
|
43
|
+
const consoleLogOriginal = console.log;
|
|
44
|
+
console.log = function () {
|
|
45
|
+
for (let i = 0; i < arguments.length; i++) {
|
|
46
|
+
const arg = arguments[i];
|
|
47
|
+
if (arg && arg.hasOwnProperty('__isProxy') || arg?.target) {
|
|
48
|
+
arguments[i] = arguments[i].target;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
consoleLogOriginal.apply(console, arguments);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// ---- Central error reporting (2026-09-13) ----------------------------------
|
|
55
|
+
// Replaces scattered `catch(e){cl(e)}` sites that silently swallowed errors.
|
|
56
|
+
// Wired into a representative, developer-facing subset for now: expression
|
|
57
|
+
// evaluation (scopedEval/lookup/evalExp), the pre-rewrite validator in
|
|
58
|
+
// walk.js, and a compiled <script> block's own runtime errors. Not yet wired
|
|
59
|
+
// into every catch site in this file — that's a deliberate, incremental scope,
|
|
60
|
+
// not an oversight; the ones above are where a developer's own .view mistake
|
|
61
|
+
// actually surfaces, which is what this phase set out to fix.
|
|
62
|
+
//
|
|
63
|
+
// _lumenDevMode is a plain constant for now, not wired to a real build/env
|
|
64
|
+
// flag yet — flip it by hand until that decision is made.
|
|
65
|
+
var _lumenDevMode = true;
|
|
66
|
+
var _lumenErrorLog = [];
|
|
67
|
+
|
|
68
|
+
// HST wire-format version this runtime expects (2026-09-15) — must be
|
|
69
|
+
// bumped in lockstep with packages/cli/lib/fcs.js's HST_FORMAT_VERSION
|
|
70
|
+
// whenever this file's walk()/renderHST() changes what fields it reads
|
|
71
|
+
// from the parser's output. See renderView()'s version check and fcs.js's
|
|
72
|
+
// own HST_FORMAT_VERSION comment for the full rationale.
|
|
73
|
+
var EXPECTED_HST_FORMAT_VERSION = 1;
|
|
74
|
+
|
|
75
|
+
// `_vt.View.vars["x"]` is what a runtime error will mention after the
|
|
76
|
+
// walk.js rewrite — this recovers the developer's original name `x` so the
|
|
77
|
+
// message reads the way the developer would expect, not the compiled form.
|
|
78
|
+
function _translateLumenError(message) {
|
|
79
|
+
if (!message) return message;
|
|
80
|
+
return message.replace(/_vt\.View\.vars\[["'`]([^"'`\]]+)["'`]\]/g, '$1');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function reportLumenError(info) {
|
|
84
|
+
info = info || {};
|
|
85
|
+
var rawMessage = info.message || (info.error && info.error.message) || 'Unknown error';
|
|
86
|
+
var entry = {
|
|
87
|
+
time: new Date().toISOString(),
|
|
88
|
+
stage: info.stage || 'runtime',
|
|
89
|
+
view: info.view || (typeof _vt !== 'undefined' && _vt.View ? _vt.View.name : undefined),
|
|
90
|
+
expr: info.expr,
|
|
91
|
+
message: _translateLumenError(rawMessage),
|
|
92
|
+
hint: info.hint
|
|
93
|
+
};
|
|
94
|
+
_lumenErrorLog.push(entry);
|
|
95
|
+
|
|
96
|
+
if (_lumenDevMode) {
|
|
97
|
+
console.error(
|
|
98
|
+
'[LumenJS] ' + entry.stage + ' error in "' + (entry.view || 'unknown') + '"' +
|
|
99
|
+
(entry.expr ? ' — ' + entry.expr : '') +
|
|
100
|
+
': ' + entry.message +
|
|
101
|
+
(entry.hint ? '\n ' + entry.hint : '')
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
// Production stays quiet on-screen by design (point 6: don't crash the
|
|
105
|
+
// page the way V1's uncaught errors did) — the entry is still kept in
|
|
106
|
+
// _lumenErrorLog for later inspection; no telemetry hook wired yet.
|
|
107
|
+
return entry;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
function _x(_x) {
|
|
112
|
+
var currPath = [];
|
|
113
|
+
const handler = {
|
|
114
|
+
get(target, key) {
|
|
115
|
+
if (key == "__isProxy") return true;
|
|
116
|
+
// 2026-09-14: reset must fire on ANY root key, not just "View" —
|
|
117
|
+
// this closure's currPath is shared by the whole _vt proxy tree,
|
|
118
|
+
// so a stale tail from a prior _vt.Global read (which never hit
|
|
119
|
+
// "View" to reset it) would otherwise get prepended to the next
|
|
120
|
+
// chain and corrupt which key set()'s update(key) fires for.
|
|
121
|
+
if (key == "View" || key == "Global") currPath = [];
|
|
122
|
+
currPath.push(key);
|
|
123
|
+
if (typeof target[key] === 'object' && target[key] !== null && key != "_re") {
|
|
124
|
+
// cl("salsaa", target, key)
|
|
125
|
+
return new Proxy(target[key], handler);
|
|
126
|
+
} else {
|
|
127
|
+
// cl("tartat", target, key);
|
|
128
|
+
return target[key] ?? (key == 'target' ? target : undefined) ?? undefined;
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
set(target, key, value) {
|
|
132
|
+
|
|
133
|
+
// cl(["hiiiiii", key, value]);
|
|
134
|
+
// console.log(`${key} set from ${target[key]} to ${value}`, target, Object.keys({ target })[0]);
|
|
135
|
+
target[key] = value;
|
|
136
|
+
// var _View = currPath[1] == "views" ? currPath[2] : "";
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
// cl(["hiiiiii", currPath, key, value]);
|
|
140
|
+
// `_vt.View._re` genuinely doesn't exist yet during
|
|
141
|
+
// index.js's own bootstrap (before any view has mounted —
|
|
142
|
+
// see index-bootstrap.js) — that's the normal case now,
|
|
143
|
+
// not an error, so it's guarded here rather than left to
|
|
144
|
+
// throw into the catch below on every such write.
|
|
145
|
+
if (currPath.length == 2 && currPath[1] == "vars") {
|
|
146
|
+
if (_vt.View._re) _vt.View._re.update(key);
|
|
147
|
+
} else if (currPath.length > 2 && currPath[1] == "vars") {
|
|
148
|
+
let ky = clone(currPath[2]);
|
|
149
|
+
if (_vt.View._re) _vt.View._re.update(ky);
|
|
150
|
+
}
|
|
151
|
+
// if (currPath.length) {
|
|
152
|
+
// _vt.View._re.set(key, value);
|
|
153
|
+
// }
|
|
154
|
+
// cl(currPath, _View);
|
|
155
|
+
// eval("var kira = " + "_vt." + currPath.join("."));
|
|
156
|
+
// if (kira.__isProxy) {
|
|
157
|
+
// currPath.push(key);
|
|
158
|
+
// eval("kira = " + "_vt." + currPath.join("."));
|
|
159
|
+
// }
|
|
160
|
+
|
|
161
|
+
// if (kira) {
|
|
162
|
+
// // if (_el.data('_re')) _el.data('_re').set(key, value);
|
|
163
|
+
// }
|
|
164
|
+
} catch (e) {
|
|
165
|
+
cl(e);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
currPath = [];
|
|
169
|
+
return true;
|
|
170
|
+
},
|
|
171
|
+
deleteProperty(target, key) {
|
|
172
|
+
if (!(key in target)) {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
delete target[key];
|
|
176
|
+
|
|
177
|
+
try {
|
|
178
|
+
// cl(["hiiiiii", currPath, key, value]);
|
|
179
|
+
// `_vt.View._re` genuinely doesn't exist yet during
|
|
180
|
+
// index.js's own bootstrap (before any view has mounted —
|
|
181
|
+
// see index-bootstrap.js) — that's the normal case now,
|
|
182
|
+
// not an error, so it's guarded here rather than left to
|
|
183
|
+
// throw into the catch below on every such write.
|
|
184
|
+
if (currPath.length == 2 && currPath[1] == "vars") {
|
|
185
|
+
if (_vt.View._re) _vt.View._re.update(key);
|
|
186
|
+
} else if (currPath.length > 2 && currPath[1] == "vars") {
|
|
187
|
+
let ky = clone(currPath[2]);
|
|
188
|
+
if (_vt.View._re) _vt.View._re.update(ky);
|
|
189
|
+
}
|
|
190
|
+
// if (currPath.length) {
|
|
191
|
+
// _vt.View._re.set(key, value);
|
|
192
|
+
// }
|
|
193
|
+
// cl(currPath, _View);
|
|
194
|
+
// eval("var kira = " + "_vt." + currPath.join("."));
|
|
195
|
+
// if (kira.__isProxy) {
|
|
196
|
+
// currPath.push(key);
|
|
197
|
+
// eval("kira = " + "_vt." + currPath.join("."));
|
|
198
|
+
// }
|
|
199
|
+
|
|
200
|
+
// if (kira) {
|
|
201
|
+
// // if (_el.data('_re')) _el.data('_re').set(key, value);
|
|
202
|
+
// }
|
|
203
|
+
} catch (e) {
|
|
204
|
+
cl(e);
|
|
205
|
+
}
|
|
206
|
+
return true;
|
|
207
|
+
},
|
|
208
|
+
ownKeys(target) {
|
|
209
|
+
return Reflect.ownKeys(target);
|
|
210
|
+
},
|
|
211
|
+
has(target, key) {
|
|
212
|
+
return key in target;
|
|
213
|
+
},
|
|
214
|
+
defineProperty(target, key, descriptor) {
|
|
215
|
+
if (descriptor && "value" in descriptor) {
|
|
216
|
+
target[key] = descriptor.value;
|
|
217
|
+
}
|
|
218
|
+
return target;
|
|
219
|
+
},
|
|
220
|
+
getOwnPropertyDescriptor(target, key) {
|
|
221
|
+
const value = target[key];
|
|
222
|
+
return key in target
|
|
223
|
+
? {
|
|
224
|
+
value,
|
|
225
|
+
enumerable: true,
|
|
226
|
+
configurable: true,
|
|
227
|
+
}
|
|
228
|
+
: undefined;
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
var x = new Proxy(_x, handler);
|
|
232
|
+
return x;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// "Global" (2026-09-14): a second, permanent root next to "View" — unlike
|
|
236
|
+
// _vt.View (replaced wholesale by a fresh _v() on every main-view navigation,
|
|
237
|
+
// see _lm's constructor below), this object is never reassigned, so state
|
|
238
|
+
// written here survives navigation. This is the target walk.js now rewrites
|
|
239
|
+
// index.js's top-level vars into, since index.js runs once at bootstrap and
|
|
240
|
+
// its vars (V1's documented convention for app-wide state like `isAdmin`)
|
|
241
|
+
// need to outlive any single view. concatVarsAtLevel() below merges it into
|
|
242
|
+
// every scope lookup so ordinary view code can just reference the name.
|
|
243
|
+
let _vt = _x({
|
|
244
|
+
"View": new _v({}),
|
|
245
|
+
"Global": { "vars": {} }
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
class _lm {
|
|
249
|
+
_RealDOM = [];
|
|
250
|
+
_effects = {};
|
|
251
|
+
_cc = {};
|
|
252
|
+
_jj = {};
|
|
253
|
+
_ready = false;
|
|
254
|
+
view = undefined;
|
|
255
|
+
sbscrbs = [];
|
|
256
|
+
reactiveVariables = [];
|
|
257
|
+
vrs = {};
|
|
258
|
+
_CXR = [];
|
|
259
|
+
_LXR = [];
|
|
260
|
+
|
|
261
|
+
constructor(view) {
|
|
262
|
+
this.view = view;
|
|
263
|
+
this.view._re = this;
|
|
264
|
+
this.reactiveVariables = view?.rvs ?? {};
|
|
265
|
+
this.init();
|
|
266
|
+
if (this.view.type == "main") _vt.View = this.view;
|
|
267
|
+
|
|
268
|
+
// this.reactiveVariables = this.view.vars ?? _vt.View.vars ?? [];
|
|
269
|
+
|
|
270
|
+
if (this.view._pv) {
|
|
271
|
+
// cl("Subscribing to " , this.view);
|
|
272
|
+
this.view._pv.subscribe(this.view);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return this;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
init() {
|
|
279
|
+
var par = this;
|
|
280
|
+
this.view.hst.forEach(function (doc) {
|
|
281
|
+
par.walk(doc, null);
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
subscribe(view) {
|
|
286
|
+
this.sbscrbs.push(view);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
scopedEval(context, expr, kk) {
|
|
290
|
+
// cl("Cleaning", expr, kk, context);
|
|
291
|
+
// 2026-09-14: `ctx` was read/deleted here before its own `let ctx =`
|
|
292
|
+
// declaration a few lines down — a real TDZ bug (ReferenceError:
|
|
293
|
+
// Cannot access 'ctx' before initialization), not something either
|
|
294
|
+
// of us introduced. Only triggers on the TypeError-retry path (a
|
|
295
|
+
// failed eval retrying with the offending property stripped), which
|
|
296
|
+
// is common enough — any expression touching a property of
|
|
297
|
+
// something momentarily undefined hits it. Fixed by computing `ctx`
|
|
298
|
+
// first, same effect, no TDZ violation.
|
|
299
|
+
let ctx = this.concatVarsAtLevel(context, this);
|
|
300
|
+
if (kk) {
|
|
301
|
+
if (!ctx.hasOwnProperty(kk)) return undefined;
|
|
302
|
+
delete ctx[kk];
|
|
303
|
+
}
|
|
304
|
+
// cl("CONTEXT");
|
|
305
|
+
// cl(context);
|
|
306
|
+
// cl(ctx);
|
|
307
|
+
try {
|
|
308
|
+
// cl(["LopIsMissing???", context, expr]);
|
|
309
|
+
const evaluator = Function.apply(null, [
|
|
310
|
+
...Object.keys(ctx),
|
|
311
|
+
"expr",
|
|
312
|
+
"return eval(expr)",
|
|
313
|
+
]);
|
|
314
|
+
// cl(evaluator.apply(null, [...Object.values(context), expr]));
|
|
315
|
+
// if(expr=="patientProfile['Gender']") alert([evaluator.apply(null, [...Object.values(context), expr]), expr, Object.keys(context), context['patientProfile'], Object.keys(context.patientProfile)]);
|
|
316
|
+
return evaluator.apply(null, [...Object.values(ctx), expr]);
|
|
317
|
+
} catch (e) {
|
|
318
|
+
// if (_debugMode)
|
|
319
|
+
// cl([expr, context, e]);
|
|
320
|
+
if (e instanceof TypeError) {
|
|
321
|
+
return this.scopedEval(ctx, expr, e.message.split(" ")[0]);
|
|
322
|
+
}
|
|
323
|
+
reportLumenError({ stage: 'expression', expr: expr, error: e });
|
|
324
|
+
return undefined;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
getVals(effect) {
|
|
329
|
+
let val = '';
|
|
330
|
+
// let mss = [];
|
|
331
|
+
if (effect.type == "text") {
|
|
332
|
+
if (!effect.isSplit) {
|
|
333
|
+
for (let i = 0; i < effect.splits.length; i++) {
|
|
334
|
+
let split = effect.splits[i];
|
|
335
|
+
if (split.type == 'mustache') {
|
|
336
|
+
val += this.getVal(split.content);
|
|
337
|
+
} else {
|
|
338
|
+
val += split.content;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
} else {
|
|
342
|
+
val = this.getVal(effect.content);
|
|
343
|
+
}
|
|
344
|
+
} else if (effect.type == "attr" || effect.type == "event") {
|
|
345
|
+
for (let i = 0; i < effect.splits.length; i++) {
|
|
346
|
+
let split = effect.splits[i];
|
|
347
|
+
if (split.type == 'mustache') {
|
|
348
|
+
val += this.getVal(split.content);
|
|
349
|
+
} else {
|
|
350
|
+
val += split.content;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
// mss = effect.mss[effect.name];
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// for (let i = 0; i < mss.length; i++) {
|
|
357
|
+
// const ms = "{{" + mss[i] + "}}";
|
|
358
|
+
// cl(ms, this.getVal(ms, _.cloneDeep(_vt.View.vars)));
|
|
359
|
+
// val = val.split(ms).join(this.getVal(ms, _.cloneDeep(this.reactiveVariables)));
|
|
360
|
+
// }
|
|
361
|
+
|
|
362
|
+
return val;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
renderAll() {
|
|
366
|
+
if (this._ready) return; //CHECK APPLICABILITY
|
|
367
|
+
this._ready = true;
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
for (const rv in this._effects) {
|
|
371
|
+
if (Object.prototype.hasOwnProperty.call(this._effects, rv)) {
|
|
372
|
+
const effects = this._effects[rv];
|
|
373
|
+
for (let ei = 0; ei < effects.length; ei++) {
|
|
374
|
+
const effect = effects[ei];
|
|
375
|
+
// cl("Effect for " + rv, effect);
|
|
376
|
+
// effect.nd.textContent = "1234";
|
|
377
|
+
|
|
378
|
+
if (!effect.nd) continue;
|
|
379
|
+
// if (!effect.nd.isConnected) continue;
|
|
380
|
+
try {
|
|
381
|
+
if (effect.type == "text") {
|
|
382
|
+
// cl(k, effect);
|
|
383
|
+
effect.nd.textContent = this.render(effect);
|
|
384
|
+
} else if (effect.type == "attr") {
|
|
385
|
+
// cl("Setting Attr", k, effect, effect.name, this.render(effect));
|
|
386
|
+
if (effect.name == "value") {
|
|
387
|
+
effect.nd.value = this.render(effect);
|
|
388
|
+
} else {
|
|
389
|
+
effect.nd.setAttribute(effect.name, this.render(effect));
|
|
390
|
+
if (effect.name == "view") {
|
|
391
|
+
cl("We Must Trigger View Change", effect, this.render(effect));
|
|
392
|
+
effect.nd.subPath = this.render(effect);
|
|
393
|
+
renderView(this.render(effect), true, {});
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
} else if (effect.type == "event") {
|
|
397
|
+
effect.nd.events[effect.name] = this.render(effect);
|
|
398
|
+
}
|
|
399
|
+
} catch (e) {
|
|
400
|
+
cl("Eeeeee", e);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
this.updateCXRs();
|
|
408
|
+
this.updateLXRs();
|
|
409
|
+
this.updateVXRs();
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
chainConnected(cx) {
|
|
413
|
+
for (let i = cx.chain.length - 1; i >= 0; i--) {
|
|
414
|
+
const cxs = cx.chain[i];
|
|
415
|
+
if (cxs.ref.isPreConnected) {
|
|
416
|
+
return true;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
return false;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
async updateVXRs(k) {
|
|
423
|
+
let subsNames = [];
|
|
424
|
+
for (let i = 0; i < this.view.views.length; i++) {
|
|
425
|
+
const _view = this.view.views[i];
|
|
426
|
+
cl("We Must Render A SubView", _view, subsNames.includes(_view.subPath), subsNames, _view.subPath);
|
|
427
|
+
if (!subsNames.includes(_view.subPath)) subsNames.push(_view.subPath);
|
|
428
|
+
}
|
|
429
|
+
// cl(subsNames);
|
|
430
|
+
for (let i = 0; i < subsNames.length; i++) {
|
|
431
|
+
const n = subsNames[i];
|
|
432
|
+
renderView(n, true, {});
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
async updateCXRs(k) {
|
|
437
|
+
for (let i = 0; i < this._CXR.length; i++) {
|
|
438
|
+
const cx = this._CXR[i];
|
|
439
|
+
if (cx.name == "if") {
|
|
440
|
+
let isTrue = this.evalExp(cx.content, this.reactiveVariables);
|
|
441
|
+
// cl("IF", isTrue, cx.content, this.reactiveVariables, cx);
|
|
442
|
+
if (isTrue) {
|
|
443
|
+
await this.showSectionCX(cx, k);
|
|
444
|
+
} else {
|
|
445
|
+
await this.hideSectionCX(cx);
|
|
446
|
+
}
|
|
447
|
+
} else if (cx.name == "else-if") {
|
|
448
|
+
if (!this.chainConnected(cx)) {
|
|
449
|
+
let isTrue = this.evalExp(cx.content, this.reactiveVariables);
|
|
450
|
+
// cl("ELSE-IF", isTrue, cx.content, this.reactiveVariables, cx);
|
|
451
|
+
if (isTrue) {
|
|
452
|
+
await this.showSectionCX(cx, k);
|
|
453
|
+
} else {
|
|
454
|
+
await this.hideSectionCX(cx);
|
|
455
|
+
}
|
|
456
|
+
} else {
|
|
457
|
+
await this.hideSectionCX(cx);
|
|
458
|
+
}
|
|
459
|
+
} else if (cx.name == "else") {
|
|
460
|
+
// cl("ELSE", !this.chainConnected(cx), cx);
|
|
461
|
+
if (!this.chainConnected(cx)) {
|
|
462
|
+
await this.showSectionCX(cx, k);
|
|
463
|
+
} else {
|
|
464
|
+
await this.hideSectionCX(cx);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// @before-render / @after-render for :if/:else-if/:else (2026-09-14) —
|
|
472
|
+
// shared by all three updateCXRs() branches above. This runs on EVERY
|
|
473
|
+
// reactive update those branches are eligible for, not just when the
|
|
474
|
+
// condition actually flips — `cx.ref.node.isConnected` (a real, always-
|
|
475
|
+
// accurate DOM property) is what gates hook firing to genuine
|
|
476
|
+
// hidden->visible / visible->hidden transitions, not `isPreConnected`
|
|
477
|
+
// (an internal bookkeeping flag with more edge cases across the
|
|
478
|
+
// if/else-if/else chain than is worth relying on here).
|
|
479
|
+
async showSectionCX(cx, k) {
|
|
480
|
+
let wasConnected = cx.ref.node.isConnected;
|
|
481
|
+
cx.ref.isPreConnected = true;
|
|
482
|
+
await renderSection(cx.ref, cx.doc, this, k);
|
|
483
|
+
if (!wasConnected) await fireRenderHook(cx, 'after-render', cx.ref.node, { visible: true });
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
async hideSectionCX(cx) {
|
|
487
|
+
if (cx.ref.node.isConnected) await fireRenderHook(cx, 'before-render', cx.ref.node, { visible: false });
|
|
488
|
+
cx.ref.isPreConnected = false;
|
|
489
|
+
cx.ref.node.replaceWith(cx.ref);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
render(effect) {
|
|
493
|
+
let x = "";
|
|
494
|
+
|
|
495
|
+
try {
|
|
496
|
+
if (effect.type == "text" || effect.type == "attr" || effect.type == "event") {
|
|
497
|
+
x = this.getVals(effect);
|
|
498
|
+
}
|
|
499
|
+
} catch (e) {
|
|
500
|
+
cl(e);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
return x;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
update(k) {
|
|
507
|
+
if (!this._ready) return;
|
|
508
|
+
// cl("Hello", k);
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
// cl(k, this._effects.hasOwnProperty(k));
|
|
512
|
+
|
|
513
|
+
if (this._effects.hasOwnProperty(k)) {
|
|
514
|
+
const effects = this._effects[k];
|
|
515
|
+
// cl(effects);
|
|
516
|
+
for (let ei = 0; ei < effects.length; ei++) {
|
|
517
|
+
const effect = effects[ei];
|
|
518
|
+
// cl("Effect for " + k, effect);
|
|
519
|
+
// effect.nd.textContent = "1234";
|
|
520
|
+
|
|
521
|
+
if (!effect.nd) continue;
|
|
522
|
+
// if (!effect.nd.isConnected) continue;
|
|
523
|
+
try {
|
|
524
|
+
if (effect.type == "text") {
|
|
525
|
+
// cl(k, effect);
|
|
526
|
+
effect.nd.textContent = this.render(effect);
|
|
527
|
+
} else if (effect.type == "attr") {
|
|
528
|
+
// cl("Setting Attr", k, effect, effect.name, this.render(effect));
|
|
529
|
+
if (effect.name == "value") {
|
|
530
|
+
effect.nd.value = this.render(effect);
|
|
531
|
+
} else {
|
|
532
|
+
effect.nd.setAttribute(effect.name, this.render(effect));
|
|
533
|
+
if (effect.name == "view") {
|
|
534
|
+
cl("We Must Trigger View Change", effect, this.render(effect));
|
|
535
|
+
effect.nd.subPath = this.render(effect);
|
|
536
|
+
renderView(this.render(effect), true, {});
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
} else if (effect.type == "event") {
|
|
540
|
+
effect.nd.events[effect.name] = this.render(effect);
|
|
541
|
+
}
|
|
542
|
+
} catch (e) {
|
|
543
|
+
cl("Eeeeee", e);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
this.updateCXRs(k);
|
|
549
|
+
this.updateLXRs(k);
|
|
550
|
+
for (let sbscsi = 0; sbscsi < this.sbscrbs.length; sbscsi++) {
|
|
551
|
+
const sbscr = this.sbscrbs[sbscsi];
|
|
552
|
+
sbscr._re.update(k);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
async updateLXRs(k) {
|
|
557
|
+
for (let i = 0; i < this._LXR.length; i++) {
|
|
558
|
+
var cx = this._LXR[i];
|
|
559
|
+
|
|
560
|
+
var forX = cx.forX;
|
|
561
|
+
|
|
562
|
+
if (k && k != forX['js']) continue;
|
|
563
|
+
|
|
564
|
+
var val = this.getVal(forX['js'], "");
|
|
565
|
+
|
|
566
|
+
// cl("FORR", cx, val);
|
|
567
|
+
|
|
568
|
+
var tempVal = [];
|
|
569
|
+
if (this.typeStr(val) == "number") {
|
|
570
|
+
for (let i = 0; i < val; i++) {
|
|
571
|
+
tempVal.push(i);
|
|
572
|
+
}
|
|
573
|
+
val = tempVal;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
let vals = [];
|
|
578
|
+
let isObj = false;
|
|
579
|
+
if (this.typeStr(val) == "object") {
|
|
580
|
+
isObj = true;
|
|
581
|
+
|
|
582
|
+
for (const oKey in val) {
|
|
583
|
+
if (Object.hasOwnProperty.call(val, oKey)) {
|
|
584
|
+
const item = val[oKey];
|
|
585
|
+
let objj = {
|
|
586
|
+
key: oKey,
|
|
587
|
+
value: item,
|
|
588
|
+
};
|
|
589
|
+
vals.push(objj);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
} else vals = clone(val);
|
|
593
|
+
|
|
594
|
+
if (this.typeStr(vals) == "array" && vals.length > 0) {
|
|
595
|
+
// cl("ARRAY", cx.ref, vals);
|
|
596
|
+
let forIf = cx.cond;
|
|
597
|
+
let limit = vals.length;
|
|
598
|
+
let offset = 0;
|
|
599
|
+
if (cx.limit) limit = (isNaN(cx.limit) ? cx.limit : limit) > vals.length ? vals.length : cx.limit * 1;
|
|
600
|
+
if (cx.offset) offset = (isNaN(cx.offset) ? cx.offset : offset) < 0 ? 0 : cx.offset * 1;
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
let marray = [];
|
|
604
|
+
if (forIf) {
|
|
605
|
+
marray = vals.slice(offset * 1, vals.length);
|
|
606
|
+
} else {
|
|
607
|
+
marray = vals.slice(offset * 1, limit * 1 + offset * 1);
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// cl(cx, vals, limit, offset, forIf, marray);
|
|
611
|
+
|
|
612
|
+
let myLimit = 0;
|
|
613
|
+
// let myClones = [];
|
|
614
|
+
|
|
615
|
+
let arrayToRender = [];
|
|
616
|
+
let arrayToRenderVXs = [];
|
|
617
|
+
|
|
618
|
+
for (var index = 0; index < marray.length; index++) {
|
|
619
|
+
if (myLimit == limit * 1) break;
|
|
620
|
+
try {
|
|
621
|
+
let vx = {}; //clone(_vt.View.vars);
|
|
622
|
+
vx['index'] = myLimit;
|
|
623
|
+
if (forX['dx'] != "") vx[forX['dx']] = myLimit;
|
|
624
|
+
if (isObj) {
|
|
625
|
+
if (forX['as']['v'] != "") {
|
|
626
|
+
if (forX['as']['k']) vx[forX['as']['k']] = marray[index]['key'];
|
|
627
|
+
if (forX['as']['v']) vx[forX['as']['v']] = marray[index]['value'];
|
|
628
|
+
} else {
|
|
629
|
+
if (forX['as']['k']) vx[forX['as']['k']] = marray[index];
|
|
630
|
+
}
|
|
631
|
+
vx['key'] = marray[index]['key'];
|
|
632
|
+
vx['value'] = marray[index]['value'];
|
|
633
|
+
} else {
|
|
634
|
+
if (forX['as']['k']) vx[forX['as']['k']] = marray[index];
|
|
635
|
+
}
|
|
636
|
+
// cl(forX, vx);
|
|
637
|
+
// cl("VXXXX", vx, this);
|
|
638
|
+
|
|
639
|
+
if (forIf) {
|
|
640
|
+
let isTrue = this.evalExp(forIf, vx);
|
|
641
|
+
if (!isTrue) continue;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
let miIndexx = offset * 1 + index * 1;
|
|
645
|
+
|
|
646
|
+
|
|
647
|
+
// let cln = this.createSection(cx, vx, forX, k);
|
|
648
|
+
arrayToRender.push(marray[index]);
|
|
649
|
+
arrayToRenderVXs.push(vx);
|
|
650
|
+
// let basket = await renderSection(cx.ref, cx.doc, this, k, {
|
|
651
|
+
// cx, vx, forX, miIndexx
|
|
652
|
+
// });
|
|
653
|
+
// cl(basket);
|
|
654
|
+
// cl([
|
|
655
|
+
// cx.ref.isConnected,
|
|
656
|
+
// cx.ref.node.isConnected,
|
|
657
|
+
// cx,
|
|
658
|
+
// "REAL INDEX: " + myLimit,
|
|
659
|
+
// miIndexx,
|
|
660
|
+
// forIf,
|
|
661
|
+
// isObj,
|
|
662
|
+
// forX,
|
|
663
|
+
// vx
|
|
664
|
+
// ]);
|
|
665
|
+
myLimit++;
|
|
666
|
+
} catch (e) {
|
|
667
|
+
cl(e);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// cl("ATR", arrayToRender);
|
|
672
|
+
let oldATR = cx.atr;
|
|
673
|
+
cx.atr = arrayToRender;
|
|
674
|
+
// cl(oldATR, arrayToRender);
|
|
675
|
+
|
|
676
|
+
const actions = this.compareArrays(oldATR, arrayToRender);
|
|
677
|
+
// cl("ACTNS", actions);
|
|
678
|
+
|
|
679
|
+
// @before-render / @after-render (2026-09-14) — lets a
|
|
680
|
+
// developer tear down and re-initialize a DOM-owning plugin
|
|
681
|
+
// (a slider, for instance) around this :for loop's own
|
|
682
|
+
// diff-and-patch pass, instead of it silently breaking the
|
|
683
|
+
// next time the underlying data changes. Skipped entirely
|
|
684
|
+
// when nothing actually changed. Fires on the very first
|
|
685
|
+
// render too (`actions` is all "add" then), so one
|
|
686
|
+
// @after-render handler covers both "initialize" and
|
|
687
|
+
// "re-initialize after data changed" — no separate manual
|
|
688
|
+
// bootstrap call needed. See fireRenderHook()'s own comment.
|
|
689
|
+
if (actions.length) await fireRenderHook(cx, 'before-render', cx.ref.parentElement, { items: arrayToRender, actions });
|
|
690
|
+
|
|
691
|
+
for (let ai = 0; ai < actions.length; ai++) {
|
|
692
|
+
const actn = actions[ai];
|
|
693
|
+
if (actn.action == 'add') {
|
|
694
|
+
//Add Items To The DOM at Index
|
|
695
|
+
// actn = {
|
|
696
|
+
// "action": "add",
|
|
697
|
+
// "index": 0,
|
|
698
|
+
// "element": {
|
|
699
|
+
// "key": "Name",
|
|
700
|
+
// "value": "Abdul Rahman"
|
|
701
|
+
// }
|
|
702
|
+
// };
|
|
703
|
+
let vx = arrayToRenderVXs[actn.index];
|
|
704
|
+
// cl([cx, vx, isObj, forX])
|
|
705
|
+
let cln = await this.createSection(cx, vx, isObj, forX);
|
|
706
|
+
cx.ref.before(cln);
|
|
707
|
+
|
|
708
|
+
|
|
709
|
+
cln.replaceWith(cln.node);
|
|
710
|
+
// cln.node.innerHTML = "";
|
|
711
|
+
// cln.node.append(...cln._re._RealDOM);
|
|
712
|
+
// cl(cln);
|
|
713
|
+
|
|
714
|
+
} else if (actn.action == 'remove') {
|
|
715
|
+
|
|
716
|
+
// cl("Remove", actn);
|
|
717
|
+
// let vx = arrayToRenderVXs[actn.index];
|
|
718
|
+
// let cln = await this.createSection(cx, vx);
|
|
719
|
+
// cx.ref.before(cln);
|
|
720
|
+
|
|
721
|
+
var keyed = cx.key + '_' + actn.index;
|
|
722
|
+
|
|
723
|
+
let tx = cx.ref?.nodes[keyed];
|
|
724
|
+
|
|
725
|
+
if (tx) {
|
|
726
|
+
tx.remove();
|
|
727
|
+
tx.node.remove();
|
|
728
|
+
delete cx.tx?.nodes[keyed];
|
|
729
|
+
// if(ref.isConnected){
|
|
730
|
+
// } else if(ref.node.isConnected){
|
|
731
|
+
|
|
732
|
+
// }
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
// cln.replaceWith(cln.node);
|
|
736
|
+
// cln.node.innerHTML = "";
|
|
737
|
+
// cln.node.append(...cln._re._RealDOM);
|
|
738
|
+
// cl(cln);
|
|
739
|
+
} else {
|
|
740
|
+
// let vx = arrayToRenderVXs[actn.index];
|
|
741
|
+
// let cln = await this.createSection(cx, vx);
|
|
742
|
+
// cx.ref.before(cln);
|
|
743
|
+
|
|
744
|
+
var keyed = cx.key + '_' + actn.index;
|
|
745
|
+
|
|
746
|
+
let tx = cx.ref?.nodes[keyed];
|
|
747
|
+
|
|
748
|
+
let vx = arrayToRenderVXs[actn.index];
|
|
749
|
+
if (tx) {
|
|
750
|
+
// tx._re.reactiveVariables = [...tx._re.reactiveVariables, ...Object.keys(vx)];
|
|
751
|
+
// cl("UPDATE", [tx], vx, tx._re);
|
|
752
|
+
tx._re.vrs = vx;
|
|
753
|
+
if (tx.isObj) {
|
|
754
|
+
if (tx.forX.as['k'] != "") tx._re.update(tx.forX.as['k']);
|
|
755
|
+
else tx._re.update(tx.forX.js);
|
|
756
|
+
if (tx.forX.as['v'] != "") tx._re.update(tx.forX.as['v']);
|
|
757
|
+
// cl("Updating", tx.forX.as['k'], tx.forX.as['v']);
|
|
758
|
+
for (let actnsi = 0; actnsi < actn.updates.length; actnsi++) {
|
|
759
|
+
const actnu = actn.updates[actnsi];
|
|
760
|
+
tx._re.update(actnu.property);
|
|
761
|
+
}
|
|
762
|
+
} else {
|
|
763
|
+
if (tx.forX.as['k'] != "") tx._re.update(tx.forX.as['k']);
|
|
764
|
+
else tx._re.update(tx.forX.js);
|
|
765
|
+
// cl("Updating", tx.forX);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
// tx._re.renderAll();
|
|
769
|
+
// if(ref.isConnected){
|
|
770
|
+
// } else if(ref.node.isConnected){
|
|
771
|
+
|
|
772
|
+
// }
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
// cln.replaceWith(cln.node);
|
|
776
|
+
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
if (actions.length) await fireRenderHook(cx, 'after-render', cx.ref.parentElement, { items: arrayToRender, actions });
|
|
781
|
+
|
|
782
|
+
} else {
|
|
783
|
+
// cl("NO ARRAY", cx.ref);
|
|
784
|
+
cx.nodes = [];
|
|
785
|
+
}
|
|
786
|
+
// if (cx.name == "if") {
|
|
787
|
+
// let isTrue = this.evalExp(cx.value, this.reactiveVariables);
|
|
788
|
+
// if (isTrue) {
|
|
789
|
+
// await renderSection(cx.ref, cx.doc, this, k);
|
|
790
|
+
// } else {
|
|
791
|
+
// cx.ref.node.replaceWith(cx.ref);
|
|
792
|
+
// }
|
|
793
|
+
// }
|
|
794
|
+
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
compareLogic(array1, array2) {
|
|
800
|
+
if (array1.length === array2.length) {
|
|
801
|
+
// Perform update-only algorithm when arrays have the same length
|
|
802
|
+
// ...
|
|
803
|
+
return 1;
|
|
804
|
+
} else {
|
|
805
|
+
if (array1.length > array2.length) {
|
|
806
|
+
// Array1 has more elements, indicating there are deleted items
|
|
807
|
+
// Use two-way comparison to find deleted indexes
|
|
808
|
+
// If successful, perform the necessary removals
|
|
809
|
+
// Otherwise, proceed with update and removal comparisons
|
|
810
|
+
// ...
|
|
811
|
+
return 2;
|
|
812
|
+
} else {
|
|
813
|
+
// Array2 has more elements, indicating there are added items
|
|
814
|
+
// Use two-way comparison to find added indexes
|
|
815
|
+
// If successful, perform the necessary additions
|
|
816
|
+
// Otherwise, proceed with update and addition comparisons
|
|
817
|
+
// ...
|
|
818
|
+
return 3;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
compareArrays(array1, array2) {
|
|
824
|
+
const actions = [];
|
|
825
|
+
// let cpl = this.compareLogic(array1, array2);
|
|
826
|
+
|
|
827
|
+
// if (cpl == 2) {
|
|
828
|
+
// cl("Deleted", this.findDeletedIndexes(array1, array2));
|
|
829
|
+
// } else if (cpl == 3) {
|
|
830
|
+
// cl("Added", this.findAddedIndexes(array1, array2));
|
|
831
|
+
// }
|
|
832
|
+
|
|
833
|
+
const maxLength = Math.max(array1.length, array2.length);
|
|
834
|
+
for (let i = 0; i < maxLength; i++) {
|
|
835
|
+
const element1 = array1[i];
|
|
836
|
+
const element2 = array2[i];
|
|
837
|
+
|
|
838
|
+
if (!element2) {
|
|
839
|
+
actions.push({
|
|
840
|
+
action: 'remove',
|
|
841
|
+
index: i
|
|
842
|
+
});
|
|
843
|
+
} else if (!element1) {
|
|
844
|
+
actions.push({
|
|
845
|
+
action: 'add',
|
|
846
|
+
index: i,
|
|
847
|
+
element: element2
|
|
848
|
+
});
|
|
849
|
+
} else if (!this.deepCompare(element1, element2)) {
|
|
850
|
+
actions.push({
|
|
851
|
+
action: 'update',
|
|
852
|
+
index: i,
|
|
853
|
+
updates: this.getUpdates(element1, element2)
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
return actions;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
findDeletedIndexes(array1, array2) {
|
|
862
|
+
const deletedIndexes = [];
|
|
863
|
+
let par = this;
|
|
864
|
+
|
|
865
|
+
array1.forEach((item, index) => {
|
|
866
|
+
const foundIndex = array2.findIndex((el) => par.deepCompare(el, item));
|
|
867
|
+
if (foundIndex === -1) {
|
|
868
|
+
deletedIndexes.push(index);
|
|
869
|
+
}
|
|
870
|
+
});
|
|
871
|
+
|
|
872
|
+
return deletedIndexes;
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
findAddedIndexes(array1, array2) {
|
|
876
|
+
const addedIndexes = [];
|
|
877
|
+
let par = this;
|
|
878
|
+
|
|
879
|
+
array2.forEach((item, index) => {
|
|
880
|
+
const foundIndex = array1.findIndex((el) => par.deepCompare(el, item));
|
|
881
|
+
if (foundIndex === -1) {
|
|
882
|
+
addedIndexes.push(index);
|
|
883
|
+
}
|
|
884
|
+
});
|
|
885
|
+
|
|
886
|
+
return addedIndexes;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
deepCompare(obj1, obj2) {
|
|
890
|
+
// Compare objects by stringifying and comparing their JSON representation
|
|
891
|
+
return JSON.stringify(obj1) === JSON.stringify(obj2);
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
getUpdates(oldObj, newObj) {
|
|
895
|
+
const updates = [];
|
|
896
|
+
for (const key in newObj) {
|
|
897
|
+
if (newObj.hasOwnProperty(key) && newObj[key] !== oldObj[key]) {
|
|
898
|
+
updates.push({ property: key, value: newObj[key] });
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
return updates;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
|
|
905
|
+
getVal(mo, indexName) {
|
|
906
|
+
let vars = {};
|
|
907
|
+
try {
|
|
908
|
+
for (let i = 0; i < this.reactiveVariables.length; i++) {
|
|
909
|
+
// 2026-09-14: fall back to _vt.Global.vars when a view
|
|
910
|
+
// doesn't declare this var itself — the real-world case of
|
|
911
|
+
// a mustache/:if referencing an index.js global (e.g.
|
|
912
|
+
// `isAdmin`) that this view's own script never assigns.
|
|
913
|
+
// concatVarsAtLevel() already does this merge for
|
|
914
|
+
// lookup()/scopedEval(); getVal() (what mustache text nodes
|
|
915
|
+
// actually call) had its own separate, unmerged read here
|
|
916
|
+
// and was silently rendering these as empty.
|
|
917
|
+
let __name = this.reactiveVariables[i];
|
|
918
|
+
vars[__name] = _vt.View.vars.hasOwnProperty(__name)
|
|
919
|
+
? _vt.View.vars[__name]
|
|
920
|
+
: _vt.Global.vars[__name];
|
|
921
|
+
}
|
|
922
|
+
for (const ky in this.vrs) {
|
|
923
|
+
if (Object.prototype.hasOwnProperty.call(this.vrs, ky)) {
|
|
924
|
+
vars[ky] = this.vrs[ky]
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
} catch (e) {
|
|
928
|
+
cl(e);
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
mo = (mo).trim();
|
|
932
|
+
// cl(["getVal", mo, vars, indexName]);
|
|
933
|
+
// if (mo == "patientProfile['Gender']") {
|
|
934
|
+
// cl(["getVal", mo, vars, indexName]);
|
|
935
|
+
// }
|
|
936
|
+
if (mo.slice(0, 2) == "{{") {
|
|
937
|
+
mo = mo.slice(2, -2);
|
|
938
|
+
}
|
|
939
|
+
// if (mo == 'new Date(article.createdAt.split("T")[0]).getDate()')
|
|
940
|
+
// if(mo=="genders[`patientProfile['Gender']`]") cl(["getVal", mo, vars, indexName]);
|
|
941
|
+
let value = "";
|
|
942
|
+
let _mo = mo;
|
|
943
|
+
|
|
944
|
+
if (mo.indexOf("`") > -1) {
|
|
945
|
+
var matchesVal = _mo.match(/\.`[\s\S]*?`/g);
|
|
946
|
+
// cl(["shuuuu", matchesVal, _mo]);
|
|
947
|
+
if (matchesVal)
|
|
948
|
+
for (var y = 0; y < matchesVal.length; y++) {
|
|
949
|
+
_mo = _mo
|
|
950
|
+
.split(matchesVal[y])
|
|
951
|
+
.join(
|
|
952
|
+
"." +
|
|
953
|
+
this.getVal(
|
|
954
|
+
matchesVal[y].substr(1).slice(1, -1),
|
|
955
|
+
indexName
|
|
956
|
+
)
|
|
957
|
+
);
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
var matchesVal = _mo.match(/`[\s\S]*?`/g);
|
|
961
|
+
// cl(["suuuu", matchesVal, _mo]);
|
|
962
|
+
if (matchesVal)
|
|
963
|
+
for (var y = 0; y < matchesVal.length; y++) {
|
|
964
|
+
// cl([
|
|
965
|
+
// "3uuu",
|
|
966
|
+
// this.getVal(matchesVal[y].slice(1, -1), vars, indexName),
|
|
967
|
+
// matchesVal,
|
|
968
|
+
// y,
|
|
969
|
+
// matchesVal[y].slice(1, -1),
|
|
970
|
+
// vars,
|
|
971
|
+
// indexName,
|
|
972
|
+
// ]);
|
|
973
|
+
_mo = _mo
|
|
974
|
+
.split(matchesVal[y])
|
|
975
|
+
.join(
|
|
976
|
+
"'" +
|
|
977
|
+
this.getVal(matchesVal[y].slice(1, -1), indexName) +
|
|
978
|
+
"'"
|
|
979
|
+
);
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
// cl([this.getVal(_mo, vars, indexName), "kuuuuk", _mo, vars, indexName]);
|
|
983
|
+
return this.getVal(_mo, indexName);
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
if (mo.indexOf(";") > -1) {
|
|
987
|
+
let zxx = mo.split(";");
|
|
988
|
+
mo = $.trim(zxx[0]);
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
if (mo.indexOf(" as ") > -1) {
|
|
992
|
+
mo = mo.split(" as ");
|
|
993
|
+
return this.getVal(mo[0], indexName);
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
if (indexName) {
|
|
997
|
+
indexName = indexName.toString();
|
|
998
|
+
if (
|
|
999
|
+
mo.indexOf(indexName) > -1 &&
|
|
1000
|
+
mo != indexName &&
|
|
1001
|
+
vars.hasOwnProperty(indexName) &&
|
|
1002
|
+
mo != "index"
|
|
1003
|
+
) {
|
|
1004
|
+
mo = mo.split(indexName).join(vars[indexName]);
|
|
1005
|
+
return this.getVal(mo, indexName);
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
var Ondex = mo.match(/\bindex\b/g);
|
|
1010
|
+
if (Ondex && mo != "index" && vars.hasOwnProperty("index")) {
|
|
1011
|
+
_mo = mo.replace(/\bindex\b/g, vars["index"]);
|
|
1012
|
+
// cl(["Hassss",mo,vars["index"], vars, this.getVal(_mo, vars, indexName)]);
|
|
1013
|
+
return this.getVal(_mo, indexName);
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
// if (this.isJS(mo, vars)) {
|
|
1017
|
+
// cl("get",mo);
|
|
1018
|
+
value = this.lookup(mo, vars);
|
|
1019
|
+
// } else {
|
|
1020
|
+
// value = this.lookup(mo, vars);
|
|
1021
|
+
// // if (mo == "index") cl("kiki", value);
|
|
1022
|
+
// }
|
|
1023
|
+
|
|
1024
|
+
// cl(["VALZZZZZZZZ", mo, vars, value, value ?? ""]);
|
|
1025
|
+
return value ?? "";
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
concatVarsAtLevel(levelVars, parent) {
|
|
1029
|
+
|
|
1030
|
+
if (!parent.view._pv) {
|
|
1031
|
+
var concatenatedVars = { ...levelVars };
|
|
1032
|
+
if (parent.view.vars) {
|
|
1033
|
+
// Global vars (index.js's top-level state, see _vt.Global
|
|
1034
|
+
// above) sit at the lowest priority here — a view or a
|
|
1035
|
+
// narrower scope declaring the same name shadows it, same
|
|
1036
|
+
// as real JS scoping would.
|
|
1037
|
+
concatenatedVars = { ..._vt.Global.vars, ...parent.view.vars, ...concatenatedVars };
|
|
1038
|
+
}
|
|
1039
|
+
return concatenatedVars;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
var concatenatedVars = { ...levelVars };
|
|
1043
|
+
if (parent.view.vars) {
|
|
1044
|
+
// Object.assign(concatenatedVars, parent.view.vars);
|
|
1045
|
+
concatenatedVars = { ...parent.view.vars, ...concatenatedVars };
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
return this.concatVarsAtLevel(concatenatedVars, parent.view._pv);
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
lookup(name, vaz) {
|
|
1052
|
+
|
|
1053
|
+
// for (const key in _vt.View.vars) {
|
|
1054
|
+
// if (Object.prototype.hasOwnProperty.call(_vt.View.vars, key)) {
|
|
1055
|
+
// vaz[key] = _vt.View.vars[key];
|
|
1056
|
+
// }
|
|
1057
|
+
// }
|
|
1058
|
+
// if(name == '{{new Date(article.createdAt.split("T")[0]).getDate()}}')
|
|
1059
|
+
// cl(["lookup", name, vaz]);
|
|
1060
|
+
// cl(vaz);
|
|
1061
|
+
// cl(this.concatVarsAtLevel(vaz, this));
|
|
1062
|
+
|
|
1063
|
+
let vars = this.concatVarsAtLevel(vaz, this);
|
|
1064
|
+
// cl("VAAZZZ");
|
|
1065
|
+
// cl(vaz);
|
|
1066
|
+
// cl(vars);
|
|
1067
|
+
|
|
1068
|
+
try {
|
|
1069
|
+
var value;
|
|
1070
|
+
var names,
|
|
1071
|
+
index,
|
|
1072
|
+
lookupHit = false;
|
|
1073
|
+
|
|
1074
|
+
if (this.hasProperty(vars, name)) {
|
|
1075
|
+
value = vars[name];
|
|
1076
|
+
// cl(["luuuu", vars, name, value]);
|
|
1077
|
+
} else if (name.indexOf(".") > -1 && name.indexOf("[") == -1) {
|
|
1078
|
+
// cl(["laaaaaa", vars, name, value]);
|
|
1079
|
+
var value = this.scopedEval(vars, name);
|
|
1080
|
+
// cl(["liiii", vars, name, value]);
|
|
1081
|
+
if (!(value || value == 0)) {
|
|
1082
|
+
value = vars;
|
|
1083
|
+
names = name.split(".");
|
|
1084
|
+
index = 0;
|
|
1085
|
+
while (value != null && index < names.length) {
|
|
1086
|
+
if (index === names.length - 1)
|
|
1087
|
+
lookupHit = this.hasProperty(value, names[index]);
|
|
1088
|
+
value = value[names[index++]];
|
|
1089
|
+
//{{v.0.kuku}} v then v.0 then v.0.kuku ...... iterate through nested chains
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
} else {
|
|
1093
|
+
var value = this.scopedEval(vars, name);
|
|
1094
|
+
// if (name == "patientProfile['Gender']") {
|
|
1095
|
+
// cl(["==zzzzzlookup", name, vaz, value, vars, name]);
|
|
1096
|
+
// }
|
|
1097
|
+
// if (name == 'new Date(article.createdAt.split("T")[0]).getDate()') cl(["laaa", vars, name, value]);
|
|
1098
|
+
if (!(value || value == 0)) {
|
|
1099
|
+
if (name.indexOf(".") == -1 && name.indexOf("[") > -1) {
|
|
1100
|
+
let _name = name;
|
|
1101
|
+
var matchesVal = _name.match(/\[[\s\S]*?\]/g);
|
|
1102
|
+
for (var y = 0; y < matchesVal.length; y++) {
|
|
1103
|
+
if (
|
|
1104
|
+
matchesVal[y].indexOf("'") == -1 &&
|
|
1105
|
+
matchesVal[y].indexOf('"') == -1
|
|
1106
|
+
)
|
|
1107
|
+
_name = _name
|
|
1108
|
+
.split(matchesVal[y])
|
|
1109
|
+
.join("['" + matchesVal[y].slice(1, -1) + "']");
|
|
1110
|
+
}
|
|
1111
|
+
var value = this.scopedEval(vars, _name);
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
if (this.isFunction(value)) value = value.call(value);
|
|
1117
|
+
|
|
1118
|
+
// if (name == "patientProfile['Gender']") {
|
|
1119
|
+
// cl(["===========lookup", name, vaz, value]);
|
|
1120
|
+
// }
|
|
1121
|
+
|
|
1122
|
+
// if (name == 'new Date(article.createdAt.split("T")[0]).getDate()') cl(["lookup", name, vaz, value]);
|
|
1123
|
+
|
|
1124
|
+
// if (value || value==0) return value;
|
|
1125
|
+
|
|
1126
|
+
// else {
|
|
1127
|
+
// value = this.scopedEval(vars, name);
|
|
1128
|
+
// }
|
|
1129
|
+
|
|
1130
|
+
// cl("n: ",name," val: ",value," v: ",vaz)
|
|
1131
|
+
} catch (e) {
|
|
1132
|
+
reportLumenError({ stage: 'lookup', expr: name, error: e });
|
|
1133
|
+
return "";
|
|
1134
|
+
}
|
|
1135
|
+
// if (name == 'new Date(article.createdAt.split("T")[0]).getDate()') cl("halaaaaaa", value);
|
|
1136
|
+
// cl("halaaaaaa", value);
|
|
1137
|
+
return value;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
|
|
1141
|
+
objectToString = Object.prototype.toString;
|
|
1142
|
+
isArray =
|
|
1143
|
+
Array.isArray ||
|
|
1144
|
+
function isArrayPolyfill(object) {
|
|
1145
|
+
return objectToString.call(object) === "[object Array]";
|
|
1146
|
+
};
|
|
1147
|
+
isFunction(object) {
|
|
1148
|
+
return typeof object === "function";
|
|
1149
|
+
}
|
|
1150
|
+
typeStr(obj) {
|
|
1151
|
+
return this.isArray(obj) ? "array" : typeof obj;
|
|
1152
|
+
}
|
|
1153
|
+
hasProperty(obj, propName) {
|
|
1154
|
+
return obj != null && typeof obj === "object" && propName in obj;
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
createEl(tag, attrs, children, events, doc) {
|
|
1158
|
+
const _el = document.createElement(tag);
|
|
1159
|
+
|
|
1160
|
+
_el.isSub = false;
|
|
1161
|
+
if (attrs.hasOwnProperty('view')) {
|
|
1162
|
+
_el.isSub = true;
|
|
1163
|
+
_el.subPath = attrs['view'];
|
|
1164
|
+
this.view.views.push(_el);
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
_el.events = {};
|
|
1168
|
+
for (const prop in attrs) {
|
|
1169
|
+
if (prop == "view" || prop == ":if" || prop == ":else-if" || prop == ":else" || prop == ":for" || prop == ":for-limit" || prop == ":for-offset" || prop == ":for-if") continue;
|
|
1170
|
+
try {
|
|
1171
|
+
// cl("DD", doc);
|
|
1172
|
+
let val = (doc && doc.ax.hasOwnProperty(prop)) ? "" : attrs[prop];
|
|
1173
|
+
if (prop == "value") {
|
|
1174
|
+
_el.value = val;
|
|
1175
|
+
} else _el.setAttribute(prop, val);
|
|
1176
|
+
} catch (e) {
|
|
1177
|
+
cl(e);
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
for (const prop in events) {
|
|
1181
|
+
try {
|
|
1182
|
+
_el.events[prop] = events[prop];
|
|
1183
|
+
} catch (e) {
|
|
1184
|
+
cl(e);
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
if (children.length) _el.append(...children);
|
|
1188
|
+
|
|
1189
|
+
// 2026-09-16: @after-render generalized to fire on MOUNT for every
|
|
1190
|
+
// element, not just :for items / :if sections. Those two already
|
|
1191
|
+
// get their own batch-level hook fired elsewhere (updateLXRs() /
|
|
1192
|
+
// showSectionCX() / hideSectionCX()) — with :items/:visible extra
|
|
1193
|
+
// data a per-element mount fire here can't provide, and firing
|
|
1194
|
+
// both would double-fire for them — so they're explicitly
|
|
1195
|
+
// excluded here via the same directive-attribute check createEl()
|
|
1196
|
+
// already does above. No @before-render equivalent for a generic
|
|
1197
|
+
// mount: there's no prior DOM state to act on before an element
|
|
1198
|
+
// exists for the first time (unlike :for/:if's before-render,
|
|
1199
|
+
// which runs against DOM that's already connected).
|
|
1200
|
+
if (events && events['@after-render'] && !(attrs && (attrs.hasOwnProperty(':for') || attrs.hasOwnProperty(':if') || attrs.hasOwnProperty(':else-if') || attrs.hasOwnProperty(':else')))) {
|
|
1201
|
+
fireRenderHook({ doc: doc }, 'after-render', _el, {});
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
// 2026-09-16: V1's real automatic plugin-init pass, ported
|
|
1205
|
+
// faithfully from bea.js's own renderPlugins()/dtp() (real source:
|
|
1206
|
+
// SBEACDN/s.beacdn.com/beajs/core.js, not reverse-engineered from
|
|
1207
|
+
// minified code) — [sl]/[color]/[time]/[date]/[datetime] elements
|
|
1208
|
+
// become their respective widgets on mount, no explicit script
|
|
1209
|
+
// call needed, matching V1's documented behavior (lumenjs-
|
|
1210
|
+
// spec.md §5.6/§6.7). Built into core directly rather than living
|
|
1211
|
+
// only in the --with-plugins bundle (explicit choice, 2026-09-16)
|
|
1212
|
+
// — autoInitPlugins() itself guards every call on the matching
|
|
1213
|
+
// $.fn.* method actually existing, so a plain (no --with-plugins)
|
|
1214
|
+
// project's dom-shim-based bundle silently no-ops instead of
|
|
1215
|
+
// throwing when it encounters one of these attributes.
|
|
1216
|
+
autoInitPlugins(_el, attrs);
|
|
1217
|
+
|
|
1218
|
+
return _el;
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
// processAttr(n, v, res) {
|
|
1222
|
+
// if (n == 'scoped') {
|
|
1223
|
+
|
|
1224
|
+
// } else if (n == 'binds') {
|
|
1225
|
+
// res.domNode.mxs = v.split(",").map((s) => s.trim());
|
|
1226
|
+
// } else {
|
|
1227
|
+
// if (n.substr(0, 1) == "@") {
|
|
1228
|
+
// res.domNode.setAttribute(n.substr(0,1), v);
|
|
1229
|
+
// } else res.domNode.setAttribute(n, v);
|
|
1230
|
+
// }
|
|
1231
|
+
// }
|
|
1232
|
+
|
|
1233
|
+
// getPVsScope(par) {
|
|
1234
|
+
// let _vz = {};
|
|
1235
|
+
|
|
1236
|
+
// if (par) {
|
|
1237
|
+
// cl("VZZZZ", par.view.vars);
|
|
1238
|
+
// _vz = this.getPVsScope(par.view._pv);
|
|
1239
|
+
// }
|
|
1240
|
+
|
|
1241
|
+
// return _vz;
|
|
1242
|
+
// }
|
|
1243
|
+
|
|
1244
|
+
// getScope() {
|
|
1245
|
+
// let vz = clone(_vt.View.vars) ?? {};
|
|
1246
|
+
// let _vz = this.getPVsScope(this.view._pv);
|
|
1247
|
+
// cl("VXXXX", vz, _vz);
|
|
1248
|
+
|
|
1249
|
+
// return vz;
|
|
1250
|
+
// }
|
|
1251
|
+
|
|
1252
|
+
evalExp(expr, vars) {
|
|
1253
|
+
// let svs = this.getScope();
|
|
1254
|
+
// cl("SVS", svs);
|
|
1255
|
+
// cl("SVS", expr, vars);
|
|
1256
|
+
let rvars = {};
|
|
1257
|
+
try {
|
|
1258
|
+
for (let i = 0; i < vars.length; i++) {
|
|
1259
|
+
// 2026-09-14: same Global-vars fallback as getVal() above —
|
|
1260
|
+
// without it this object always carries an explicit
|
|
1261
|
+
// `name: undefined` for anything index.js declares (since
|
|
1262
|
+
// it's never in _vt.View.vars), and because it's spread
|
|
1263
|
+
// LAST in concatVarsAtLevel()'s merge (highest priority),
|
|
1264
|
+
// that explicit undefined would silently clobber the real
|
|
1265
|
+
// value scopedEval() would otherwise have found in
|
|
1266
|
+
// _vt.Global.vars — breaking :if/:for conditions on any
|
|
1267
|
+
// index.js-declared var, not just mustache text (getVal()).
|
|
1268
|
+
let __name = vars[i];
|
|
1269
|
+
rvars[__name] = _vt.View.vars.hasOwnProperty(__name)
|
|
1270
|
+
? _vt.View.vars[__name]
|
|
1271
|
+
: _vt.Global.vars[__name];
|
|
1272
|
+
}
|
|
1273
|
+
} catch (e) {
|
|
1274
|
+
cl(e);
|
|
1275
|
+
}
|
|
1276
|
+
//If Lookaup
|
|
1277
|
+
// let value = this.lookup(expr, vars);
|
|
1278
|
+
// if (value || value == 0) return false;
|
|
1279
|
+
try {
|
|
1280
|
+
var value = this.scopedEval(rvars, expr);
|
|
1281
|
+
// cl("VV", value);
|
|
1282
|
+
if (value && value != 0) return true;
|
|
1283
|
+
} catch (e) {
|
|
1284
|
+
reportLumenError({ stage: 'condition', expr: expr, error: e });
|
|
1285
|
+
return false;
|
|
1286
|
+
}
|
|
1287
|
+
return false;
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
splitTextWithMustaches(text, mustaches) {
|
|
1291
|
+
// Sort mustaches by start index to process in order
|
|
1292
|
+
mustaches.sort((a, b) => a.start - b.start);
|
|
1293
|
+
|
|
1294
|
+
const elements = [];
|
|
1295
|
+
let currentIndex = 0;
|
|
1296
|
+
|
|
1297
|
+
for (const mustache of mustaches) {
|
|
1298
|
+
// Add static text before mustache if any
|
|
1299
|
+
if (currentIndex < mustache.start) {
|
|
1300
|
+
elements.push({
|
|
1301
|
+
type: 'static',
|
|
1302
|
+
content: text.substring(currentIndex, mustache.start)
|
|
1303
|
+
});
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
// Add the mustache
|
|
1307
|
+
elements.push({
|
|
1308
|
+
type: 'mustache',
|
|
1309
|
+
jst: mustache.jst,
|
|
1310
|
+
rvs: mustache.rvs,
|
|
1311
|
+
content: text.substring(mustache.start, mustache.end)
|
|
1312
|
+
});
|
|
1313
|
+
|
|
1314
|
+
// Update current index
|
|
1315
|
+
currentIndex = mustache.end;
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
// Add any remaining static text after the last mustache
|
|
1319
|
+
if (currentIndex < text.length) {
|
|
1320
|
+
elements.push({
|
|
1321
|
+
type: 'static',
|
|
1322
|
+
content: text.substring(currentIndex)
|
|
1323
|
+
});
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
return elements;
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
|
|
1330
|
+
walk(doc, parent) {
|
|
1331
|
+
var par = this;
|
|
1332
|
+
var tx, el;
|
|
1333
|
+
switch (doc.type) {
|
|
1334
|
+
case 'text':
|
|
1335
|
+
|
|
1336
|
+
if (doc.mss.length) {
|
|
1337
|
+
|
|
1338
|
+
let splitIt = true;
|
|
1339
|
+
|
|
1340
|
+
if (doc.tag == "textarea") {
|
|
1341
|
+
splitIt = false;
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
if (splitIt) {
|
|
1345
|
+
let splits = this.splitTextWithMustaches(doc.content, doc.mss);
|
|
1346
|
+
// cl(splits);
|
|
1347
|
+
for (let si = 0; si < splits.length; si++) {
|
|
1348
|
+
const split = splits[si];
|
|
1349
|
+
if (split.type == 'static') {
|
|
1350
|
+
let txnd = document.createTextNode(split.content);
|
|
1351
|
+
if (!parent) par._RealDOM.push(txnd);
|
|
1352
|
+
(tx ?? (tx = [])).push(txnd);
|
|
1353
|
+
} else {
|
|
1354
|
+
let txnd = document.createTextNode("");
|
|
1355
|
+
for (let ri = 0; ri < split.rvs.length; ri++) {
|
|
1356
|
+
const element = split.rvs[ri];
|
|
1357
|
+
(this._effects[element] ?? (this._effects[element] = [])).push({
|
|
1358
|
+
"type": "text",
|
|
1359
|
+
"content": split.content,
|
|
1360
|
+
"jst": split.jst,
|
|
1361
|
+
"rvs": split.rvs,
|
|
1362
|
+
"isSplit": true,
|
|
1363
|
+
"nd": txnd,
|
|
1364
|
+
"tag": doc.tag
|
|
1365
|
+
});
|
|
1366
|
+
}
|
|
1367
|
+
if (!parent) par._RealDOM.push(txnd);
|
|
1368
|
+
(tx ?? (tx = [])).push(txnd);
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
return tx;
|
|
1372
|
+
} else {
|
|
1373
|
+
tx = document.createTextNode("");
|
|
1374
|
+
for (let mui = 0; mui < doc.mss.length; mui++) {
|
|
1375
|
+
const mus = doc.mss[mui];
|
|
1376
|
+
|
|
1377
|
+
for (let ri = 0; ri < mus.rvs.length; ri++) {
|
|
1378
|
+
const element = mus.rvs[ri];
|
|
1379
|
+
(this._effects[element] ?? (this._effects[element] = [])).push({
|
|
1380
|
+
"type": "text",
|
|
1381
|
+
"content": doc.content,
|
|
1382
|
+
"splits": this.splitTextWithMustaches(doc.content, doc.mss),
|
|
1383
|
+
"jst": mus.jst,
|
|
1384
|
+
"rvs": mus.rvs,
|
|
1385
|
+
"isSplit": false,
|
|
1386
|
+
"nd": tx,
|
|
1387
|
+
"tag": doc.tag
|
|
1388
|
+
});
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
if (!parent) par._RealDOM.push(tx);
|
|
1393
|
+
return tx;
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
|
|
1397
|
+
} else {
|
|
1398
|
+
tx = document.createTextNode(doc.content);
|
|
1399
|
+
if (!parent) par._RealDOM.push(tx);
|
|
1400
|
+
return tx;
|
|
1401
|
+
}
|
|
1402
|
+
break;
|
|
1403
|
+
case 'sections':
|
|
1404
|
+
case 'section':
|
|
1405
|
+
var _dd = md5(new Date().getTime() / 1000 + "::" + Math.random());
|
|
1406
|
+
tx = document.createTextNode("");
|
|
1407
|
+
var typeN = null;
|
|
1408
|
+
if (doc.attrs.hasOwnProperty(":else")) typeN = "else";
|
|
1409
|
+
else if (doc.attrs.hasOwnProperty(":else-if")) typeN = "else-if";
|
|
1410
|
+
else if (doc.attrs.hasOwnProperty(":if")) typeN = "if";
|
|
1411
|
+
else typeN = 'for';
|
|
1412
|
+
|
|
1413
|
+
if (doc.type == "section") {
|
|
1414
|
+
|
|
1415
|
+
var chain = [];
|
|
1416
|
+
if (typeN == "else-if" || typeN == "else") {
|
|
1417
|
+
try {
|
|
1418
|
+
let lastInChain = this._CXR.at(-1);
|
|
1419
|
+
if (lastInChain) {
|
|
1420
|
+
_dd = lastInChain.key;
|
|
1421
|
+
chain.push(...lastInChain.chain, lastInChain);
|
|
1422
|
+
}
|
|
1423
|
+
} catch (e) {
|
|
1424
|
+
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
el = par.createEl(doc.name, doc.attrs, [], doc.evs, doc);
|
|
1429
|
+
tx.node = el;
|
|
1430
|
+
|
|
1431
|
+
// cl("SECCCCC", doc);
|
|
1432
|
+
// return;
|
|
1433
|
+
this._CXR.push({
|
|
1434
|
+
"type": "section",
|
|
1435
|
+
"name": typeN,
|
|
1436
|
+
"content": doc.cond,
|
|
1437
|
+
"doc": doc,
|
|
1438
|
+
"key": _dd,
|
|
1439
|
+
"chain": chain,
|
|
1440
|
+
"ref": tx
|
|
1441
|
+
});
|
|
1442
|
+
|
|
1443
|
+
this.setEffects(doc, el);
|
|
1444
|
+
|
|
1445
|
+
} else if (doc.type == "sections") {
|
|
1446
|
+
|
|
1447
|
+
tx.key = _dd;
|
|
1448
|
+
tx.node = null;
|
|
1449
|
+
tx.nodes = {};
|
|
1450
|
+
|
|
1451
|
+
let docRaw = doc;
|
|
1452
|
+
// delete docRaw.attrs[':for'];
|
|
1453
|
+
// delete docRaw.attrs[':for-limit'];
|
|
1454
|
+
// delete docRaw.attrs[':for-if'];
|
|
1455
|
+
// delete docRaw.attrs[':for-offset'];
|
|
1456
|
+
// docRaw.type = 'tag';
|
|
1457
|
+
|
|
1458
|
+
// cl("SECCCCCSSS", doc);
|
|
1459
|
+
// return;
|
|
1460
|
+
|
|
1461
|
+
this._LXR.push({
|
|
1462
|
+
"type": "sections",
|
|
1463
|
+
"name": typeN,
|
|
1464
|
+
"cond": doc.attrs.hasOwnProperty(":for-if") ? doc.attrs[':for-if'] : null,
|
|
1465
|
+
"limit": doc.attrs.hasOwnProperty(":for-limit") ? doc.attrs[':for-limit'] : 0,
|
|
1466
|
+
"offset": doc.attrs.hasOwnProperty(":for-offset") ? doc.attrs[':for-offset'] : 0,
|
|
1467
|
+
"content": doc.content,
|
|
1468
|
+
"forX": doc.forX,
|
|
1469
|
+
"doc": docRaw,
|
|
1470
|
+
"key": _dd,
|
|
1471
|
+
"atr": [],
|
|
1472
|
+
"ref": tx
|
|
1473
|
+
});
|
|
1474
|
+
|
|
1475
|
+
// cl(tx, doc);
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
|
|
1479
|
+
if (!parent) par._RealDOM.push(tx);
|
|
1480
|
+
return tx;
|
|
1481
|
+
break;
|
|
1482
|
+
case 'tag':
|
|
1483
|
+
var _dd = md5(new Date().getTime() / 1000 + "::" + Math.random());
|
|
1484
|
+
|
|
1485
|
+
// cl("DOC", doc);
|
|
1486
|
+
|
|
1487
|
+
if (doc.name.toLowerCase() == "settings") {
|
|
1488
|
+
if (par.view.type == "main") {
|
|
1489
|
+
var defaultSettings = {
|
|
1490
|
+
layout: "default",
|
|
1491
|
+
requireAuth: false,
|
|
1492
|
+
};
|
|
1493
|
+
try {
|
|
1494
|
+
let settingsC = doc.children[0].content;
|
|
1495
|
+
let settings = {};
|
|
1496
|
+
eval("settings = " + settingsC + ";");
|
|
1497
|
+
if (settings) {
|
|
1498
|
+
if (settings.layout == null) settings.layout = "default";
|
|
1499
|
+
if (settings.requireAuth == null) settings.requireAuth = false;
|
|
1500
|
+
par.view.settings = settings;
|
|
1501
|
+
} else {
|
|
1502
|
+
par.view.settings = defaultSettings;
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
} catch (e) {
|
|
1506
|
+
setError(e, "Error in your settings tag inside the '" + par.view.name.toLowerCase() + "' main view!");
|
|
1507
|
+
par.view.settings = defaultSettings;
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
} else if (doc.name.toLowerCase() == "script" || doc.name.toLowerCase() == "js") {
|
|
1511
|
+
let child = doc.children[0];
|
|
1512
|
+
let js = child.content;
|
|
1513
|
+
let jst = child.jst;
|
|
1514
|
+
let isScoped = false;
|
|
1515
|
+
if (doc.attrs.hasOwnProperty('scoped')) {
|
|
1516
|
+
delete doc.attrs['scoped'];
|
|
1517
|
+
isScoped = true;
|
|
1518
|
+
}
|
|
1519
|
+
el = par.createEl("script", doc.attrs, [], doc.evs, doc);
|
|
1520
|
+
el._sc = isScoped;
|
|
1521
|
+
el._dd = _dd;
|
|
1522
|
+
// el._js = js;
|
|
1523
|
+
el._jst = jst;
|
|
1524
|
+
// cl(child);
|
|
1525
|
+
// _jswacrk.trigger('msg', {
|
|
1526
|
+
// "code": js,
|
|
1527
|
+
// "type": par.view.type,
|
|
1528
|
+
// "key": _dd
|
|
1529
|
+
// });
|
|
1530
|
+
// _jsuid[_dd] = el;
|
|
1531
|
+
(par._jj[_dd] ?? (par._jj[_dd] = [])).push({
|
|
1532
|
+
"nd": el,
|
|
1533
|
+
});
|
|
1534
|
+
|
|
1535
|
+
} else if (doc.name.toLowerCase() == "style") {
|
|
1536
|
+
let css = doc.children[0].content;
|
|
1537
|
+
let isScoped = false;
|
|
1538
|
+
|
|
1539
|
+
el = par.createEl("style", {}, [], doc.evs, doc);
|
|
1540
|
+
|
|
1541
|
+
if (doc.attrs.hasOwnProperty('scoped')) {
|
|
1542
|
+
if (!parent) {
|
|
1543
|
+
if (par.view._dd) _dd = par.view._dd;
|
|
1544
|
+
else {
|
|
1545
|
+
par.view._dd = _dd;
|
|
1546
|
+
if (par.view.type == "main") $('[body]')[0].setAttribute('vuid', _dd);
|
|
1547
|
+
}
|
|
1548
|
+
} else {
|
|
1549
|
+
if (parent._dd) _dd = parent._dd;
|
|
1550
|
+
else {
|
|
1551
|
+
parent._dd = _dd;
|
|
1552
|
+
parent.setAttribute('vuid', _dd);
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
delete doc.attrs['scoped'];
|
|
1556
|
+
isScoped = true;
|
|
1557
|
+
el._sc = isScoped;
|
|
1558
|
+
el._dd = _dd;
|
|
1559
|
+
el._css = css;
|
|
1560
|
+
(par._cc[_dd] ?? (par._cc[_dd] = [])).push({
|
|
1561
|
+
"nd": el,
|
|
1562
|
+
"_css": css
|
|
1563
|
+
});
|
|
1564
|
+
} else {
|
|
1565
|
+
el._sc = isScoped;
|
|
1566
|
+
el._dd = _dd;
|
|
1567
|
+
el.textContent = css;
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
|
|
1571
|
+
for (const prop in doc.attrs) {
|
|
1572
|
+
try {
|
|
1573
|
+
_el.setAttribute(prop, doc.attrs[prop]);
|
|
1574
|
+
} catch (e) {
|
|
1575
|
+
cl(e);
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
} else if (doc.name.toLowerCase() == "icon") {
|
|
1579
|
+
let child = par.createEl("span", {
|
|
1580
|
+
"class": "iconify",
|
|
1581
|
+
"data-icon": doc?.icon ?? "mdi:home"
|
|
1582
|
+
}, [], {}, null);
|
|
1583
|
+
|
|
1584
|
+
el = par.createEl("span", doc.attrs, [child], doc.evs, doc);
|
|
1585
|
+
|
|
1586
|
+
} else if (doc.name.toLowerCase() == "slot") {
|
|
1587
|
+
// Layout slot content (2026-09-15) — a view wraps
|
|
1588
|
+
// content meant for a named layout region (anything
|
|
1589
|
+
// other than the default `[body]` target) in
|
|
1590
|
+
// <slot name="...">...</slot>. Collected onto
|
|
1591
|
+
// par.view._slots[name] (an array of real, walked DOM
|
|
1592
|
+
// nodes) instead of being pushed into _RealDOM —
|
|
1593
|
+
// renderView() injects each populated slot into its
|
|
1594
|
+
// matching `[slot="name"]` layout element, after the
|
|
1595
|
+
// default content. Same non-participating-in-_RealDOM
|
|
1596
|
+
// shape as the `settings` branch above (no `el` gets
|
|
1597
|
+
// set here either) — but slot content needs to be
|
|
1598
|
+
// walked/rendered, unlike settings' raw config text, so
|
|
1599
|
+
// this uses a throwaway wrapper purely as a real DOM
|
|
1600
|
+
// parent for that walk; it's never attached anywhere.
|
|
1601
|
+
let slotName = doc.attrs && doc.attrs.name;
|
|
1602
|
+
if (slotName) {
|
|
1603
|
+
let tempWrapper = document.createElement('div');
|
|
1604
|
+
let childs = [];
|
|
1605
|
+
for (let i = 0; i < doc.children.length; i++) {
|
|
1606
|
+
const dc = doc.children[i];
|
|
1607
|
+
let chils = par.walk(dc, tempWrapper);
|
|
1608
|
+
if (chils) {
|
|
1609
|
+
if (Array.isArray(chils)) {
|
|
1610
|
+
if (chils.length) childs = [...childs, ...chils];
|
|
1611
|
+
} else {
|
|
1612
|
+
childs.push(chils);
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
(par.view._slots ?? (par.view._slots = {}))[slotName] = childs;
|
|
1617
|
+
}
|
|
1618
|
+
} else {
|
|
1619
|
+
el = par.createEl(doc.name, doc.attrs, [], doc.evs, doc);
|
|
1620
|
+
|
|
1621
|
+
if (!doc.isV && !el.isSub) {
|
|
1622
|
+
let childs = [];
|
|
1623
|
+
for (let i = 0; i < doc.children.length; i++) {
|
|
1624
|
+
const dc = doc.children[i];
|
|
1625
|
+
let chils = par.walk(dc, el);
|
|
1626
|
+
if (chils) {
|
|
1627
|
+
if (Array.isArray(chils)) {
|
|
1628
|
+
if (chils.length) childs = [...childs, ...chils];
|
|
1629
|
+
} else {
|
|
1630
|
+
childs.push(chils);
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
childs.length ? el.append(...childs) : null;
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
this.setEffects(doc, el);
|
|
1639
|
+
|
|
1640
|
+
if (el) {
|
|
1641
|
+
if (!parent) par._RealDOM.push(el);
|
|
1642
|
+
}
|
|
1643
|
+
return el;
|
|
1644
|
+
|
|
1645
|
+
break;
|
|
1646
|
+
case 'comment':
|
|
1647
|
+
|
|
1648
|
+
break;
|
|
1649
|
+
default:
|
|
1650
|
+
break;
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
setEffects(doc, el) {
|
|
1655
|
+
let rvs = [];
|
|
1656
|
+
if (Object.keys(doc.ax).length) {
|
|
1657
|
+
for (const attrName in doc.ax) {
|
|
1658
|
+
if (Object.hasOwnProperty.call(doc.ax, attrName)) {
|
|
1659
|
+
const attrMustaches = doc.ax[attrName];
|
|
1660
|
+
for (let i = 0; i < attrMustaches.length; i++) {
|
|
1661
|
+
const mus = attrMustaches[i];
|
|
1662
|
+
for (let ri = 0; ri < mus.rvs.length; ri++) {
|
|
1663
|
+
const element = mus.rvs[ri];
|
|
1664
|
+
rvs.push(element);
|
|
1665
|
+
(this._effects[element] ?? (this._effects[element] = [])).push({
|
|
1666
|
+
"type": "attr",
|
|
1667
|
+
"name": attrName,
|
|
1668
|
+
"content": doc.attrs[attrName],
|
|
1669
|
+
"splits": this.splitTextWithMustaches(doc.attrs[attrName], doc.ax[attrName]),
|
|
1670
|
+
"jst": mus.jst,
|
|
1671
|
+
"rvs": mus.rvs,
|
|
1672
|
+
"nd": el
|
|
1673
|
+
});
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
if (Object.keys(doc.ex).length) {
|
|
1681
|
+
for (const ky in doc.ex) {
|
|
1682
|
+
if (Object.hasOwnProperty.call(doc.ex, ky)) {
|
|
1683
|
+
const mss = doc.ex[ky];
|
|
1684
|
+
for (let i = 0; i < mss.length; i++) {
|
|
1685
|
+
const mus = mss[i];
|
|
1686
|
+
for (let ri = 0; ri < mus.rvs.length; ri++) {
|
|
1687
|
+
const element = mus.rvs[ri];
|
|
1688
|
+
rvs.push(element);
|
|
1689
|
+
(this._effects[element] ?? (this._effects[element] = [])).push({
|
|
1690
|
+
"type": "event",
|
|
1691
|
+
"name": ky,
|
|
1692
|
+
"content": doc.evs[ky],
|
|
1693
|
+
"splits": this.splitTextWithMustaches(doc.evs[ky], doc.ex[ky]),
|
|
1694
|
+
"jst": mus.jst,
|
|
1695
|
+
"rvs": mus.rvs,
|
|
1696
|
+
"nd": el
|
|
1697
|
+
});
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
return rvs.filter((value, index, self) => {
|
|
1705
|
+
return self.indexOf(value) === index;
|
|
1706
|
+
});
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
async createSection(cx, vx, isObj, forX) {
|
|
1710
|
+
var keyed = cx.key + '_' + vx.index;
|
|
1711
|
+
// cl("DD", cx, vx, keyed);
|
|
1712
|
+
var tx = document.createTextNode("");
|
|
1713
|
+
var typeN = null;
|
|
1714
|
+
if (cx.doc.attrs.hasOwnProperty(":else")) typeN = "else";
|
|
1715
|
+
else if (cx.doc.attrs.hasOwnProperty(":else-if")) typeN = "else-if";
|
|
1716
|
+
else if (cx.doc.attrs.hasOwnProperty(":if")) typeN = "if";
|
|
1717
|
+
else typeN = 'for';
|
|
1718
|
+
|
|
1719
|
+
// cl("CREATE", cx.doc.name, cx.doc.attrs, [], cx.doc.evs, cx.doc);
|
|
1720
|
+
|
|
1721
|
+
let el = this.createEl(cx.doc.name, cx.doc.attrs, [], cx.doc.evs, cx.doc);
|
|
1722
|
+
tx.node = el;
|
|
1723
|
+
tx.key = cx.key;
|
|
1724
|
+
tx.keyed = keyed;
|
|
1725
|
+
tx.isObj = isObj;
|
|
1726
|
+
tx.forX = forX;
|
|
1727
|
+
tx.vx = vx;
|
|
1728
|
+
|
|
1729
|
+
// cl("RENDERSECTION", tx, cx.doc, this, cx.key);
|
|
1730
|
+
|
|
1731
|
+
// this._CXR.push({
|
|
1732
|
+
// "type": "section",
|
|
1733
|
+
// "name": typeN,
|
|
1734
|
+
// "value": doc.cond,
|
|
1735
|
+
// "doc": doc,
|
|
1736
|
+
// "key": _dd,
|
|
1737
|
+
// "chain": chain,
|
|
1738
|
+
// "ref": tx
|
|
1739
|
+
// });
|
|
1740
|
+
|
|
1741
|
+
|
|
1742
|
+
let scsc = await renderSection(tx, cx.doc, this, cx.key);
|
|
1743
|
+
// cl(23);
|
|
1744
|
+
// cl(scsc);
|
|
1745
|
+
scsc._re = scsc;
|
|
1746
|
+
|
|
1747
|
+
|
|
1748
|
+
|
|
1749
|
+
// let rvs = scsc._re.setEffects(cx.doc, el);
|
|
1750
|
+
// // scsc._re.rvs = _vt.View.vars;
|
|
1751
|
+
// // scsc._re.reactiveVariables = rvs;
|
|
1752
|
+
|
|
1753
|
+
// scsc._re.renderAll('sections');
|
|
1754
|
+
|
|
1755
|
+
cx.ref.nodes[keyed] = tx;
|
|
1756
|
+
|
|
1757
|
+
|
|
1758
|
+
return tx;
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
|
|
1762
|
+
attrString(attrs) {
|
|
1763
|
+
var buff = [];
|
|
1764
|
+
for (var key in attrs) {
|
|
1765
|
+
// if(key != "@click")
|
|
1766
|
+
buff.push(key + '="' + attrs[key] + '"');
|
|
1767
|
+
}
|
|
1768
|
+
if (!buff.length) return '';
|
|
1769
|
+
return ' ' + buff.join(' ');
|
|
1770
|
+
}
|
|
1771
|
+
_stringify(buff, doc) {
|
|
1772
|
+
var par = this;
|
|
1773
|
+
switch (doc.type) {
|
|
1774
|
+
case 'text':
|
|
1775
|
+
return buff + doc.content;
|
|
1776
|
+
case 'tag':
|
|
1777
|
+
buff += '<' + doc.name + (doc.attrs ? par.attrString(doc.attrs) : '') + (doc.isV ? '/>' : '>');
|
|
1778
|
+
if (doc.isV) return buff;
|
|
1779
|
+
for (let i = 0; i < doc.children.length; i++) {
|
|
1780
|
+
const dc = doc.children[i];
|
|
1781
|
+
buff = buff + (par._stringify('', dc));
|
|
1782
|
+
}
|
|
1783
|
+
return buff + '</' + doc.name + '>';
|
|
1784
|
+
case 'comment':
|
|
1785
|
+
// buff += '<!--' + doc.comment + '-->';
|
|
1786
|
+
return buff;
|
|
1787
|
+
default:
|
|
1788
|
+
return '';
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
stringify(doc) {
|
|
1792
|
+
var par = this;
|
|
1793
|
+
return doc.reduce(function (token, rootEl) {
|
|
1794
|
+
return token + par._stringify('', rootEl);
|
|
1795
|
+
}, '');
|
|
1796
|
+
};
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
|
|
1800
|
+
async function renderHST(hst, n, type = 'main', tx, _pv = null) {
|
|
1801
|
+
|
|
1802
|
+
var reactiveVariables = hst.reactiveVars;
|
|
1803
|
+
hst = hst.hst;
|
|
1804
|
+
|
|
1805
|
+
let _re = new _lm(new _v({
|
|
1806
|
+
"name": n,
|
|
1807
|
+
"type": type,
|
|
1808
|
+
"hst": hst,
|
|
1809
|
+
"vars": tx?.vx,
|
|
1810
|
+
"rvs": reactiveVariables,
|
|
1811
|
+
"_pv": _pv
|
|
1812
|
+
}));
|
|
1813
|
+
|
|
1814
|
+
if (Object.keys(_re._cc).length) {
|
|
1815
|
+
|
|
1816
|
+
// let cssObjs = {};
|
|
1817
|
+
// for (const ky in _re._cc) {
|
|
1818
|
+
// if (Object.hasOwnProperty.call(_re._cc, ky)) {
|
|
1819
|
+
// const csses = _re._cc[ky];
|
|
1820
|
+
// for (let inde = 0; inde < csses.length; inde++) {
|
|
1821
|
+
// const css = csses[inde];
|
|
1822
|
+
// let myKey = ky + "_::" + inde;
|
|
1823
|
+
// cssObjs[myKey] = css._css;
|
|
1824
|
+
// }
|
|
1825
|
+
// }
|
|
1826
|
+
// }
|
|
1827
|
+
|
|
1828
|
+
|
|
1829
|
+
|
|
1830
|
+
|
|
1831
|
+
for (const ky in _re._cc) {
|
|
1832
|
+
if (Object.hasOwnProperty.call(_re._cc, ky)) {
|
|
1833
|
+
const csses = _re._cc[ky];
|
|
1834
|
+
for (let inde = 0; inde < csses.length; inde++) {
|
|
1835
|
+
let prom = new defer();
|
|
1836
|
+
const css = csses[inde];
|
|
1837
|
+
_csswrk.trigger('css-ready', {
|
|
1838
|
+
"csses": [css._css],
|
|
1839
|
+
"pre": "[vuid='" + ky + "']",
|
|
1840
|
+
"key": ky
|
|
1841
|
+
});
|
|
1842
|
+
_vuid[ky] = prom;
|
|
1843
|
+
let _csses = await prom;
|
|
1844
|
+
css.nd.textContent = _csses[0];
|
|
1845
|
+
|
|
1846
|
+
// _jsuid[_dd] = el;
|
|
1847
|
+
// prom
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
|
|
1852
|
+
|
|
1853
|
+
|
|
1854
|
+
// let prom = new defer();
|
|
1855
|
+
// var _dd = md5(new Date().getTime() / 1000 + "::" + Math.random());
|
|
1856
|
+
// _csswrk.trigger('css-ready', {
|
|
1857
|
+
// "csses": cssObjs,
|
|
1858
|
+
// "key": _dd,
|
|
1859
|
+
// "pre": _dd
|
|
1860
|
+
// });
|
|
1861
|
+
// _vuid[_dd] = prom;
|
|
1862
|
+
// let _csses = await prom;
|
|
1863
|
+
|
|
1864
|
+
// cl(_csses);
|
|
1865
|
+
|
|
1866
|
+
// for (const ky in _re._cc) {
|
|
1867
|
+
// if (Object.hasOwnProperty.call(_re._cc, ky)) {
|
|
1868
|
+
// const csses = _re._cc[ky];
|
|
1869
|
+
// for (let inde = 0; inde < csses.length; inde++) {
|
|
1870
|
+
// const css = csses[inde];
|
|
1871
|
+
// let myKey = ky + "_::" + inde;
|
|
1872
|
+
// css.nd.textContent = _csses[myKey];
|
|
1873
|
+
// }
|
|
1874
|
+
// }
|
|
1875
|
+
// }
|
|
1876
|
+
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
if (Object.keys(_re._jj).length) {
|
|
1880
|
+
for (const ky in _re._jj) {
|
|
1881
|
+
if (Object.hasOwnProperty.call(_re._jj, ky)) {
|
|
1882
|
+
const jses = _re._jj[ky];
|
|
1883
|
+
for (let inde = 0; inde < jses.length; inde++) {
|
|
1884
|
+
const nd = jses[inde].nd;
|
|
1885
|
+
let code = getWatcher(nd._jst, _re.view, reactiveVariables).code;
|
|
1886
|
+
code = `try { ` + code + ` } catch (e) { reportLumenError({ stage: 'script', error: e }); }`;
|
|
1887
|
+
// sourceURL: DevTools shows this <script>'s errors against
|
|
1888
|
+
// "<viewname>.view" instead of an anonymous VM context.
|
|
1889
|
+
// 2026-09-14, real bug found testing a real project
|
|
1890
|
+
// end-to-end: this used to be appended BEFORE the
|
|
1891
|
+
// try/catch wrap above, landing the comment — and
|
|
1892
|
+
// everything after it on the same line, including the
|
|
1893
|
+
// wrap's own closing brace and catch clause — inside
|
|
1894
|
+
// the try block. A `//` comment eats the rest of its
|
|
1895
|
+
// line, so that silently commented out the catch
|
|
1896
|
+
// entirely and left an unterminated `try`, throwing
|
|
1897
|
+
// "Unexpected end of input" the moment any real
|
|
1898
|
+
// <script> block actually ran (about.view's real
|
|
1899
|
+
// script on roxyon.com, in this case). Must come after
|
|
1900
|
+
// the wrap, on its own trailing line.
|
|
1901
|
+
code = code + `\n//# sourceURL=` + (_re.view?.name || 'view') + `.view.generated.js`;
|
|
1902
|
+
nd.textContent = code;
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1908
|
+
return _re;
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
// @before-render / @after-render (2026-09-14) — a developer-facing
|
|
1912
|
+
// lifecycle hook fired around a :for loop's diff-and-patch pass
|
|
1913
|
+
// (updateLXRs) or a :if/:else-if/:else section's show/hide transition
|
|
1914
|
+
// (updateCXRs' showSectionCX/hideSectionCX), letting a DOM-owning plugin
|
|
1915
|
+
// (a slider, for instance) safely tear down before its content is
|
|
1916
|
+
// replaced and re-initialize once it's settled — instead of silently
|
|
1917
|
+
// breaking the next time the underlying data or condition changes.
|
|
1918
|
+
// Reuses lstnrs.js's own evalEvAttr() — the same handler-resolution logic
|
|
1919
|
+
// every other @-attribute already goes through (@click, @sl-select, ...:
|
|
1920
|
+
// a plain function name calls window[name](ev, el, ...), anything else is
|
|
1921
|
+
// eval'd as an inline expression) — rather than inventing a second one;
|
|
1922
|
+
// the only new part is WHEN this gets called. Errors inside the handler
|
|
1923
|
+
// itself are already swallowed by evalEvAttr — matches the established,
|
|
1924
|
+
// silent-on-error precedent every other @-attribute handler already has;
|
|
1925
|
+
// not changed here to keep this hook's error behavior consistent with them.
|
|
1926
|
+
async function fireRenderHook(cx, n, containerEl, extra) {
|
|
1927
|
+
if (!containerEl) return;
|
|
1928
|
+
let attrKey = '@' + n;
|
|
1929
|
+
// The parser lifts @-prefixed attributes into `doc.evs` (its events
|
|
1930
|
+
// map) at compile time, same as @click/@sl-select/etc — NOT into
|
|
1931
|
+
// `doc.attrs` alongside plain attributes like :for/:if. Verified
|
|
1932
|
+
// against real parser output (fcs.js's getAllFiles), not assumed.
|
|
1933
|
+
if (!cx.doc || !cx.doc.evs || !cx.doc.evs.hasOwnProperty(attrKey)) return;
|
|
1934
|
+
let attrVal = cx.doc.evs[attrKey];
|
|
1935
|
+
if (!attrVal) return;
|
|
1936
|
+
let ev = Object.assign({ cType: n }, extra || {});
|
|
1937
|
+
let result = evalEvAttr(attrVal, ev, $(containerEl), n);
|
|
1938
|
+
if (result && typeof result.then === 'function') {
|
|
1939
|
+
try { await result; } catch (e) { }
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1943
|
+
// 2026-09-16: V1's real automatic plugin-init pass — [sl] (Select2),
|
|
1944
|
+
// [color] (bootstrap-colorpicker), [time]/[date]/[datetime]
|
|
1945
|
+
// (bootstrap-datetimepicker via dtp()) — ported faithfully from bea.js's
|
|
1946
|
+
// own real, un-minified renderPlugins()/dtp() source
|
|
1947
|
+
// (SBEACDN/s.beacdn.com/beajs/core.js:2846/3834, confirmed against the
|
|
1948
|
+
// real V1 build root this session already located, not reverse-engineered
|
|
1949
|
+
// from minified code). Called from createEl() on every element's mount.
|
|
1950
|
+
// Deliberately built into packages/core's own engine rather than kept
|
|
1951
|
+
// inside the --with-plugins bundle only — every call below is guarded on
|
|
1952
|
+
// the matching $.fn.* method actually existing, so a plain project (no
|
|
1953
|
+
// --with-plugins, dom-shim-based, none of these libraries loaded) safely
|
|
1954
|
+
// no-ops instead of throwing when a view happens to use one of these
|
|
1955
|
+
// attributes.
|
|
1956
|
+
function autoInitPlugins(el, attrs) {
|
|
1957
|
+
if (!attrs) return;
|
|
1958
|
+
try {
|
|
1959
|
+
if (attrs.hasOwnProperty('sl') && typeof $.fn.select2 === 'function') {
|
|
1960
|
+
initSl($(el));
|
|
1961
|
+
}
|
|
1962
|
+
if (attrs.hasOwnProperty('color') && typeof $.fn.colorpicker === 'function') {
|
|
1963
|
+
$(el).removeAttr('color').colorpicker({ format: 'rgba' });
|
|
1964
|
+
}
|
|
1965
|
+
if (typeof $.fn.datetimepicker === 'function') {
|
|
1966
|
+
if (attrs.hasOwnProperty('time')) dtp($(el), 'time');
|
|
1967
|
+
if (attrs.hasOwnProperty('date')) dtp($(el), 'date');
|
|
1968
|
+
if (attrs.hasOwnProperty('datetime')) dtp($(el), 'datetime');
|
|
1969
|
+
}
|
|
1970
|
+
} catch (e) { cl(e); }
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1973
|
+
// Real V1 source, ported as-is (SBEACDN core.js:3404-3518) — the `sl-*`
|
|
1974
|
+
// attribute family is documented in lumenjs-spec.md §6.7. `:not(.select2-
|
|
1975
|
+
// hidden-accessible)`-equivalent guard kept even though this only ever
|
|
1976
|
+
// runs once per element (on mount, never re-checked) — matches V1's own
|
|
1977
|
+
// idempotency guard exactly, cheap insurance if this is ever called from
|
|
1978
|
+
// anywhere else in the future.
|
|
1979
|
+
function initSl(t) {
|
|
1980
|
+
if (t.hasClass('select2-hidden-accessible')) return;
|
|
1981
|
+
try {
|
|
1982
|
+
var plchldr = t.attr("placeholder") ? t.attr("placeholder") : "";
|
|
1983
|
+
var dir = $("body").hasClass("rtl") ? "rtl" : "ltr";
|
|
1984
|
+
var nr = t.attr("sl-nrmsg") ? t.attr("sl-nrmsg") : "No results found";
|
|
1985
|
+
var minResultsForSearch = t.attr("sl-mins") ? t.attr("sl-mins") : 10;
|
|
1986
|
+
var allowNewTags = t.attr("sl-ntgs") ? true : false;
|
|
1987
|
+
var dropdownParent = t.attr("sl-prt") ? t.attr("sl-prt") : "body";
|
|
1988
|
+
if (dropdownParent == "self") dropdownParent = t.parent();
|
|
1989
|
+
else dropdownParent = $(dropdownParent);
|
|
1990
|
+
|
|
1991
|
+
var query = t.attr("sl-query") ? t.attr("sl-query") : null;
|
|
1992
|
+
var uniquer = Date.now();
|
|
1993
|
+
|
|
1994
|
+
if (typeof window[query] === "function") {
|
|
1995
|
+
t.select2.amd.define(
|
|
1996
|
+
"adapt_" + uniquer,
|
|
1997
|
+
["select2/data/array", "select2/utils"],
|
|
1998
|
+
function (ArrayAdapter, Utils) {
|
|
1999
|
+
function CustomDataAdapter($element, options) {
|
|
2000
|
+
CustomDataAdapter.__super__.constructor.call(this, $element, options);
|
|
2001
|
+
}
|
|
2002
|
+
Utils.Extend(CustomDataAdapter, ArrayAdapter);
|
|
2003
|
+
CustomDataAdapter.prototype.query = function (params, callback) {
|
|
2004
|
+
clearTimeout(_dbcrs[uniquer]);
|
|
2005
|
+
let _t = t;
|
|
2006
|
+
_dbcrs[uniquer] = setTimeout(function () {
|
|
2007
|
+
window[query](params, callback, _t);
|
|
2008
|
+
}, !_dbcrs.hasOwnProperty(uniquer) ? 0 : _dbcrsTime);
|
|
2009
|
+
};
|
|
2010
|
+
return CustomDataAdapter;
|
|
2011
|
+
}
|
|
2012
|
+
);
|
|
2013
|
+
|
|
2014
|
+
t.select2({
|
|
2015
|
+
dropdownParent: dropdownParent,
|
|
2016
|
+
minimumResultsForSearch: minResultsForSearch,
|
|
2017
|
+
placeholder: plchldr,
|
|
2018
|
+
dir: dir,
|
|
2019
|
+
tags: allowNewTags,
|
|
2020
|
+
allowClear: true,
|
|
2021
|
+
language: { noResults: function () { return nr; } },
|
|
2022
|
+
...(t.select2.amd.require("adapt_" + uniquer)
|
|
2023
|
+
? { ajax: {}, dataAdapter: t.select2.amd.require("adapt_" + uniquer) }
|
|
2024
|
+
: {}),
|
|
2025
|
+
});
|
|
2026
|
+
} else {
|
|
2027
|
+
t.select2({
|
|
2028
|
+
dropdownParent: dropdownParent,
|
|
2029
|
+
minimumResultsForSearch: minResultsForSearch,
|
|
2030
|
+
placeholder: plchldr,
|
|
2031
|
+
dir: dir,
|
|
2032
|
+
tags: allowNewTags,
|
|
2033
|
+
allowClear: true,
|
|
2034
|
+
language: { noResults: function () { return nr; } },
|
|
2035
|
+
});
|
|
2036
|
+
}
|
|
2037
|
+
|
|
2038
|
+
if (t.attr("sl-nosrch"))
|
|
2039
|
+
t.on("select2:opening select2:closing", function (event) {
|
|
2040
|
+
$(this).parent().find(".select2-search__field").prop("disabled", true);
|
|
2041
|
+
});
|
|
2042
|
+
if (t.attr("sl-class")) {
|
|
2043
|
+
t.on("select2:opening", function (event) { dropdownParent.addClass(t.attr("sl-class")); });
|
|
2044
|
+
t.on("select2:closing", function (event) { dropdownParent.removeClass(t.attr("sl-class")); });
|
|
2045
|
+
}
|
|
2046
|
+
|
|
2047
|
+
if (t.attr("sl-id") || t.attr("sl-text")) {
|
|
2048
|
+
let text = t.attr("sl-text");
|
|
2049
|
+
let id = t.attr("sl-id");
|
|
2050
|
+
if (!text) text = id;
|
|
2051
|
+
if (!id) id = text;
|
|
2052
|
+
let newOption = new Option(text, id, true, true);
|
|
2053
|
+
t.append(newOption).trigger('select');
|
|
2054
|
+
} else {
|
|
2055
|
+
t.select2("val", "");
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
if (t.attr("sl-value")) t.val(t.attr("sl-value")).trigger('change');
|
|
2059
|
+
} catch (e) { cl(e); }
|
|
2060
|
+
}
|
|
2061
|
+
var _dbcrs = {};
|
|
2062
|
+
var _dbcrsTime = 250;
|
|
2063
|
+
|
|
2064
|
+
// Real V1 source, ported as-is (SBEACDN core.js:3834-3891) — bootstrap-
|
|
2065
|
+
// datetimepicker option builder + optional start/end date-linking. Not
|
|
2066
|
+
// documented in lumenjs-spec.md (see PROVENANCE.md's --with-plugins
|
|
2067
|
+
// section); this exact option shape was confirmed directly against V1's
|
|
2068
|
+
// real source once it was located this session, not reverse-engineered.
|
|
2069
|
+
function dtp(el, t) {
|
|
2070
|
+
el.removeAttr(t);
|
|
2071
|
+
let opts = {
|
|
2072
|
+
format: t == "date" ? "yyyy-mm-dd" : t == "time" ? "hh:ii" : "yyyy-mm-dd hh:ii",
|
|
2073
|
+
weekStart: el.attr("date-week-start") ?? 1,
|
|
2074
|
+
startView: t == "time" ? 1 : (el.attr("startview") ? el.attr("startview") : 2),
|
|
2075
|
+
minView: el.attr("minview") ? el.attr("minview") : t == "time" ? 0 : t == "datetime" ? 0 : 2,
|
|
2076
|
+
maxView: el.attr("maxview") ? el.attr("maxview") : t == "time" ? 1 : 4,
|
|
2077
|
+
todayBtn: t == "time" ? 0 : el.attr("date-today") == "false" ? 0 : 1,
|
|
2078
|
+
todayHighlight: t == "time" ? 0 : el.attr("date-today") == "false" ? 0 : 1,
|
|
2079
|
+
language: el.attr("date-lang") ?? "en",
|
|
2080
|
+
minuteStep: el.attr("date-minute-step") ?? 5,
|
|
2081
|
+
pickerPosition: el.attr("date-position") ?? "top-right",
|
|
2082
|
+
autoclose: 1,
|
|
2083
|
+
showMeridian: false,
|
|
2084
|
+
};
|
|
2085
|
+
if (el.attr("date-start")) opts["startDate"] = el.attr("date-start");
|
|
2086
|
+
if (el.attr("date-end")) opts["endDate"] = el.attr("date-end");
|
|
2087
|
+
if (el.attr("date-value")) opts["date"] = el.attr("date-value");
|
|
2088
|
+
|
|
2089
|
+
el.datetimepicker(opts);
|
|
2090
|
+
|
|
2091
|
+
if (t == "time") {
|
|
2092
|
+
el.on("show", function (ev) {
|
|
2093
|
+
$(".table-condensed > thead, .table-condensed > thead > tr > th, .table-condensed > thead > tr > th > i")
|
|
2094
|
+
.attr("style", "visibility: hidden; font-size:0px !important; overflow: hidden; height: 0px;");
|
|
2095
|
+
}).on("hide", function (ev) {
|
|
2096
|
+
$(".table-condensed > thead, .table-condensed > thead > tr > th, .table-condensed > thead > tr > th > i")
|
|
2097
|
+
.attr("style", "visibility: visible;");
|
|
2098
|
+
});
|
|
2099
|
+
}
|
|
2100
|
+
if (el.attr("date-link-start")) {
|
|
2101
|
+
el.on("change", function (e) {
|
|
2102
|
+
let dp1 = el.data("datetimepicker");
|
|
2103
|
+
let dp2 = $(el.attr("date-link-start")).data("datetimepicker");
|
|
2104
|
+
dp2.setStartDate(dp1.getFormattedDate());
|
|
2105
|
+
if (dp2.getFormattedDate() < dp1.getFormattedDate() || dp2.getFormattedDate() == "")
|
|
2106
|
+
$(el.attr("date-link-start")).val(dp1.getFormattedDate());
|
|
2107
|
+
});
|
|
2108
|
+
} else if (el.attr("date-link-end")) {
|
|
2109
|
+
el.on("change", function (e) {
|
|
2110
|
+
let dp1 = $(el.attr("date-link-end")).data("datetimepicker");
|
|
2111
|
+
let dp2 = el.data("datetimepicker");
|
|
2112
|
+
dp1.setEndDate(dp2.getFormattedDate());
|
|
2113
|
+
});
|
|
2114
|
+
opts["useCurrent"] = false;
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
|
|
2118
|
+
async function renderSection(tx, doc, par, k, sectionsData) {
|
|
2119
|
+
if (tx.node.isConnected) {
|
|
2120
|
+
if (k) {
|
|
2121
|
+
tx._re.update(k);
|
|
2122
|
+
}
|
|
2123
|
+
return tx._re;
|
|
2124
|
+
}
|
|
2125
|
+
|
|
2126
|
+
|
|
2127
|
+
var hst = doc.children;
|
|
2128
|
+
|
|
2129
|
+
let _re = await renderHST({ hst, mxes: [] }, tx.key, 'section', tx, par);
|
|
2130
|
+
// if(par) {
|
|
2131
|
+
// _re.reactiveVariables = par.reactiveVariables;
|
|
2132
|
+
// }
|
|
2133
|
+
tx._re = _re;
|
|
2134
|
+
|
|
2135
|
+
// if (doc.type == "sections") {
|
|
2136
|
+
|
|
2137
|
+
// return _re;
|
|
2138
|
+
// }
|
|
2139
|
+
// cl(tx.key);
|
|
2140
|
+
// cl(par);
|
|
2141
|
+
// cl(hst);
|
|
2142
|
+
// cl(tx);
|
|
2143
|
+
// cl(doc);
|
|
2144
|
+
// cl(_re);
|
|
2145
|
+
|
|
2146
|
+
// cl("section", _re, par);
|
|
2147
|
+
|
|
2148
|
+
if (tx.node) {
|
|
2149
|
+
tx.replaceWith(tx.node);
|
|
2150
|
+
tx.node.innerHTML = "";
|
|
2151
|
+
tx.node.append(..._re._RealDOM);
|
|
2152
|
+
|
|
2153
|
+
_re.setEffects(doc, tx.node);
|
|
2154
|
+
|
|
2155
|
+
_re.renderAll('section');
|
|
2156
|
+
}
|
|
2157
|
+
return _re;
|
|
2158
|
+
}
|
|
2159
|
+
|
|
2160
|
+
async function renderView(n, isSub, d, type = 'views') {
|
|
2161
|
+
let filePath = "src/views/" + n + ".view"
|
|
2162
|
+
if (type == 'layouts') filePath = "src/layouts/" + n + ".layout";
|
|
2163
|
+
|
|
2164
|
+
cl(arguments);
|
|
2165
|
+
let fileKey = btoa(filePath);
|
|
2166
|
+
if (!isSub) {
|
|
2167
|
+
View.props = d ?? {};
|
|
2168
|
+
var _queryParams = window.location.href.split("?");
|
|
2169
|
+
var nn = _queryParams.shift();
|
|
2170
|
+
View.params = paraToObj(_queryParams) ?? {};
|
|
2171
|
+
}
|
|
2172
|
+
n = prepareNode(n);
|
|
2173
|
+
var _queryParams = n.split("?");
|
|
2174
|
+
n = _queryParams.shift();
|
|
2175
|
+
|
|
2176
|
+
// 2026-09-15, real bug found implementing HST versioning: `_vcD` is
|
|
2177
|
+
// only ever assigned by ws.js's syncViewFiles() (dev-only, gated on
|
|
2178
|
+
// `!_beaTn`) — production never runs that, so `_vcD` itself stays
|
|
2179
|
+
// undefined forever in a real prod build, even though the SAME data
|
|
2180
|
+
// (views/layouts) is already sitting in the embedded `_vcData` global
|
|
2181
|
+
// (baked directly into the bundle at build time — see fcs.js's `vt`).
|
|
2182
|
+
// Resolved fresh on every call, not cached at module-load time: fcs.js
|
|
2183
|
+
// hands `vt` (which declares `_vcData`) to a remote endpoint that
|
|
2184
|
+
// weaves it into the final bundle at a position this code can't see or
|
|
2185
|
+
// control, so there's no reliable "by now it's definitely defined"
|
|
2186
|
+
// point earlier than an actual function call like this one — by the
|
|
2187
|
+
// time any event-driven code (this function) runs, all synchronous
|
|
2188
|
+
// top-level script content, wherever the remote endpoint placed it,
|
|
2189
|
+
// has already executed.
|
|
2190
|
+
let _payload = _vcD || (typeof _vcData !== 'undefined' ? _vcData : undefined);
|
|
2191
|
+
|
|
2192
|
+
// HST wire-format version check (2026-09-15) — see fcs.js's own
|
|
2193
|
+
// HST_FORMAT_VERSION comment for the full rationale. Checked once per
|
|
2194
|
+
// payload object (not once per call) via a property stamped directly
|
|
2195
|
+
// onto it, so a hot-reloaded payload during dev gets re-checked too.
|
|
2196
|
+
if (_payload && !_payload.__hstVersionChecked) {
|
|
2197
|
+
_payload.__hstVersionChecked = true;
|
|
2198
|
+
if (_payload.hstFormatVersion !== undefined && _payload.hstFormatVersion !== EXPECTED_HST_FORMAT_VERSION) {
|
|
2199
|
+
reportLumenError({
|
|
2200
|
+
stage: 'hst-version-mismatch',
|
|
2201
|
+
error: new Error('This project was compiled for HST format v' + _payload.hstFormatVersion + ', but this LumenJS runtime expects v' + EXPECTED_HST_FORMAT_VERSION + '. @lmjs/cli and @lmjs/core are out of sync — reinstall/upgrade both together.'),
|
|
2202
|
+
});
|
|
2203
|
+
return;
|
|
2204
|
+
}
|
|
2205
|
+
}
|
|
2206
|
+
|
|
2207
|
+
if ((_payload && _payload[type].hasOwnProperty(fileKey)) /*&& _jswacrk.isStarted()*/ && _csswrk.isStarted()) {
|
|
2208
|
+
if (isSub) cl("Rendering", n, fileKey);
|
|
2209
|
+
var hst = _payload[type][fileKey];
|
|
2210
|
+
// var mxes = hst.mxes;
|
|
2211
|
+
// hst = hst.hst;
|
|
2212
|
+
// cl("HHHSSSTTT", hst);
|
|
2213
|
+
// return;
|
|
2214
|
+
|
|
2215
|
+
if (isSub) {
|
|
2216
|
+
let els = [];
|
|
2217
|
+
for (let i = 0; i < _vt.View.views.length; i++) {
|
|
2218
|
+
let _el = _vt.View.views[i];
|
|
2219
|
+
if (_el.__isProxy) _el = _el.target;
|
|
2220
|
+
if (_el.subPath == n) els.push(_el);
|
|
2221
|
+
}
|
|
2222
|
+
if (els.length) {
|
|
2223
|
+
// cl(els);
|
|
2224
|
+
for (let i = 0; i < els.length; i++) {
|
|
2225
|
+
let _re = await renderHST(hst, n, 'sub');
|
|
2226
|
+
const el = els[i];
|
|
2227
|
+
el.innerHTML = "";
|
|
2228
|
+
// cl(el);
|
|
2229
|
+
el.append(..._re._RealDOM);
|
|
2230
|
+
_re.renderAll();
|
|
2231
|
+
}
|
|
2232
|
+
// _re._RealDOM.forEach(_el => el[0].appendChild(_el))
|
|
2233
|
+
// cl(_re);
|
|
2234
|
+
}
|
|
2235
|
+
} else {
|
|
2236
|
+
if (type == 'layouts') {
|
|
2237
|
+
let appSelector = appSettings.App ?? "[app]";
|
|
2238
|
+
var appContainer = $(appSelector);
|
|
2239
|
+
if (appContainer.length) {
|
|
2240
|
+
let _rel = await renderHST(hst, n, 'layout');
|
|
2241
|
+
appContainer.data('layout', n).html(_rel._RealDOM);
|
|
2242
|
+
_rel.renderAll();
|
|
2243
|
+
goToNode();
|
|
2244
|
+
}
|
|
2245
|
+
} else {
|
|
2246
|
+
let _re = await renderHST(hst, n, 'main');
|
|
2247
|
+
// cl("RRR", _re);
|
|
2248
|
+
let layout = _re.view.settings.layout;
|
|
2249
|
+
|
|
2250
|
+
let filePathL = "src/layouts/" + layout + ".layout";
|
|
2251
|
+
let fileKeyL = btoa(filePathL);
|
|
2252
|
+
let hstL = _payload['layouts'][fileKeyL];
|
|
2253
|
+
// cl(_rel);
|
|
2254
|
+
|
|
2255
|
+
|
|
2256
|
+
let appSelector = appSettings.App ?? "[app]";
|
|
2257
|
+
var appContainer = $(appSelector);
|
|
2258
|
+
if (appContainer.length) {
|
|
2259
|
+
let currentLayout = $(appSelector).data('layout');
|
|
2260
|
+
if (currentLayout != layout) {
|
|
2261
|
+
let _rel = await renderHST(hstL, layout, 'layout');
|
|
2262
|
+
appContainer.data('layout', layout).html(_rel._RealDOM);
|
|
2263
|
+
_rel.renderAll();
|
|
2264
|
+
} else {
|
|
2265
|
+
// cl("Same Layout");
|
|
2266
|
+
}
|
|
2267
|
+
} else {
|
|
2268
|
+
$("body").prepend("<div " + (appSelector) + "></div>");
|
|
2269
|
+
let _rel = await renderHST(hstL, layout, 'layout');
|
|
2270
|
+
appContainer = $(appSelector);
|
|
2271
|
+
appContainer.data('layout', layout).html(_rel._RealDOM);
|
|
2272
|
+
_rel.renderAll();
|
|
2273
|
+
}
|
|
2274
|
+
|
|
2275
|
+
// return;
|
|
2276
|
+
// setLayout();
|
|
2277
|
+
$('[body]').html(_re._RealDOM);
|
|
2278
|
+
|
|
2279
|
+
// Layout slots (2026-09-15) — see walk()'s "slot" branch
|
|
2280
|
+
// above for how _re.view._slots gets populated. Injected
|
|
2281
|
+
// the same way [body] is, right above — .html() moves the
|
|
2282
|
+
// already-walked real DOM nodes (doesn't clone them), so
|
|
2283
|
+
// this can run before or after renderAll() without
|
|
2284
|
+
// affecting which node each reactive effect targets;
|
|
2285
|
+
// matching [body]'s own ordering here just for consistency.
|
|
2286
|
+
// A view targeting a slot name no loaded layout declares
|
|
2287
|
+
// is a legitimate, silent no-op (the layout may simply not
|
|
2288
|
+
// have that optional region) — $('[slot="x"]') matching
|
|
2289
|
+
// nothing is real jQuery/dom-shim behavior already, not a
|
|
2290
|
+
// new case to handle.
|
|
2291
|
+
if (_re.view._slots) {
|
|
2292
|
+
for (const slotName in _re.view._slots) {
|
|
2293
|
+
if (Object.prototype.hasOwnProperty.call(_re.view._slots, slotName)) {
|
|
2294
|
+
$('[slot="' + slotName + '"]').html(_re.view._slots[slotName]);
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
|
|
2299
|
+
_re.renderAll();
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
} else {
|
|
2303
|
+
setTimeout(() => {
|
|
2304
|
+
renderView(n, isSub, d);
|
|
2305
|
+
}, 10);
|
|
2306
|
+
}
|
|
2307
|
+
}
|