@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/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
+ }